mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-29 15:40:55 +08:00
Try to have some cleaner hierarchy
This commit is contained in:
parent
0f4a62b7bf
commit
00188fde29
@ -1,36 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.events
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
|
||||||
import com.squareup.moshi.JsonClass
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.RoomThirdPartyInvite
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class representing an event content
|
|
||||||
*/
|
|
||||||
@JsonClass(generateAdapter = true)
|
|
||||||
data class EventContent(
|
|
||||||
/**
|
|
||||||
* The display name for this user, if any.
|
|
||||||
*/
|
|
||||||
@Json(name = "displayname") val displayName: String? = null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The avatar URL for this user, if any.
|
|
||||||
*/
|
|
||||||
@Json(name = "avatar_url") val avatarUrl: String? = null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The membership state of the user. One of: ["invite", "join", "knock", "leave", "ban"]
|
|
||||||
*/
|
|
||||||
@Json(name = "membership") val membership: String? = null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the third party invite
|
|
||||||
*/
|
|
||||||
@Json(name = "third_party_invite") val thirdPartyInvite: RoomThirdPartyInvite? = null,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* e2e encryption format
|
|
||||||
*/
|
|
||||||
@Json(name = "algorithm") val algorithm: String? = null
|
|
||||||
)
|
|
@ -1,2 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.events
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
|
||||||
|
|
||||||
import im.vector.matrix.android.api.rooms.timeline.EventTimeline
|
|
||||||
|
|
||||||
interface Room {
|
|
||||||
|
|
||||||
fun timeline(): EventTimeline
|
|
||||||
|
|
||||||
}
|
|
@ -1,749 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import im.vector.matrix.android.api.events.Event
|
|
||||||
import im.vector.matrix.android.api.events.EventType
|
|
||||||
import im.vector.matrix.android.api.rooms.timeline.EventTimeline
|
|
||||||
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
|
||||||
import im.vector.matrix.android.internal.legacy.call.MXCallsManager
|
|
||||||
import im.vector.matrix.android.internal.legacy.data.store.IMXStore
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.callback.ApiCallback
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.callback.SimpleApiCallback
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.*
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomDirectoryVisibility
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomMember
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.pid.RoomThirdPartyInvite
|
|
||||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils
|
|
||||||
import im.vector.matrix.android.internal.legacy.util.Log
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The state of a room.
|
|
||||||
*/
|
|
||||||
data class RoomState(
|
|
||||||
var roomId: String? = null,
|
|
||||||
var powerLevels: PowerLevels? = null,
|
|
||||||
var canonicalAlias: String? = null,
|
|
||||||
var name: String? = null,
|
|
||||||
var topic: String? = null,
|
|
||||||
var roomTombstoneContent: RoomTombstoneContent? = null,
|
|
||||||
var url: String? = null,
|
|
||||||
var avatarUrl: String? = null,
|
|
||||||
var roomCreateContent: RoomCreateContent? = null,
|
|
||||||
var roomPinnedEventsContent: RoomPinnedEventsContent? = null,
|
|
||||||
var joinRule: String? = null,
|
|
||||||
var guestAccess: String = RoomState.GUEST_ACCESS_FORBIDDEN,
|
|
||||||
var historyVisibility: String? = RoomState.HISTORY_VISIBILITY_SHARED,
|
|
||||||
var visibility: String? = null,
|
|
||||||
var algorithm: String? = null,
|
|
||||||
var groups: List<String> = emptyList(),
|
|
||||||
var token: String? = null,
|
|
||||||
|
|
||||||
private var mergedAliasesList: MutableList<String>? = null,
|
|
||||||
private var currentAliases: MutableList<String> = ArrayList(),
|
|
||||||
private var roomAliases: MutableMap<String, Event> = HashMap(),
|
|
||||||
private var aliasesByDomain_: MutableMap<String, MutableList<String>> = HashMap(),
|
|
||||||
private var stateEvents: MutableMap<String, MutableList<Event>> = HashMap(),
|
|
||||||
private var notificationCount_: Int = 0,
|
|
||||||
private var highlightCount_: Int = 0,
|
|
||||||
private val members: HashMap<String, RoomMember> = HashMap(),
|
|
||||||
private var allMembersAreLoaded: Boolean = false,
|
|
||||||
private val getAllMembersCallbacks: ArrayList<ApiCallback<List<RoomMember>>> = ArrayList(),
|
|
||||||
private val thirdPartyInvites: HashMap<String, RoomThirdPartyInvite> = HashMap(),
|
|
||||||
private val membersWithThirdPartyInviteTokenCache: HashMap<String, RoomMember> = HashMap(),
|
|
||||||
private var isLive: Boolean = false,
|
|
||||||
private var memberDisplayNameByUserId: MutableMap<String, String> = HashMap()
|
|
||||||
) {
|
|
||||||
|
|
||||||
lateinit var dataHandler: MXDataHandler
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a copy of the room members list. May be incomplete if the full list is not loaded yet
|
|
||||||
*/
|
|
||||||
// make a copy to avoid concurrency modifications
|
|
||||||
val loadedMembers: List<RoomMember>
|
|
||||||
get() {
|
|
||||||
val res: List<RoomMember>
|
|
||||||
synchronized(this) {
|
|
||||||
res = ArrayList(members.values)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a copy of the displayable members list. May be incomplete if the full list is not loaded yet
|
|
||||||
*/
|
|
||||||
val displayableLoadedMembers: List<RoomMember>
|
|
||||||
get() {
|
|
||||||
val conferenceUserId = getMember(MXCallsManager.getConferenceUserId(roomId))
|
|
||||||
return loadedMembers.filter { it != conferenceUserId }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells if the room is a call conference one
|
|
||||||
* i.e. this room has been created to manage the call conference
|
|
||||||
*
|
|
||||||
* @return true if it is a call conference room.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Set this room as a conference user room
|
|
||||||
*
|
|
||||||
* @param isConferenceUserRoom true when it is an user conference room.
|
|
||||||
*/
|
|
||||||
var isConferenceUserRoom: Boolean
|
|
||||||
get() = dataHandler.store.getSummary(roomId)?.isConferenceUserRoom ?: false
|
|
||||||
set(isConferenceUserRoom) = dataHandler.store!!.getSummary(roomId)!!.setIsConferenceUserRoom(isConferenceUserRoom)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the notified messages count.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the notified messages count.
|
|
||||||
*
|
|
||||||
* @param notificationCount the new notified messages count.
|
|
||||||
*/
|
|
||||||
var notificationCount: Int
|
|
||||||
get() = notificationCount_
|
|
||||||
set(notificationCount) {
|
|
||||||
Timber.d("## setNotificationCount() : $notificationCount room id $roomId")
|
|
||||||
notificationCount_ = notificationCount
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the highlighted messages count.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the highlighted messages count.
|
|
||||||
*
|
|
||||||
* @param highlightCount the new highlighted messages count.
|
|
||||||
*/
|
|
||||||
var highlightCount: Int
|
|
||||||
get() = highlightCount_
|
|
||||||
set(highlightCount) {
|
|
||||||
Timber.d("## setHighlightCount() : $highlightCount room id $roomId")
|
|
||||||
highlightCount_ = highlightCount
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the currentAliases by domain
|
|
||||||
*
|
|
||||||
* @return the currentAliases list map
|
|
||||||
*/
|
|
||||||
val aliasesByDomain: Map<String, List<String>>
|
|
||||||
get() = HashMap(aliasesByDomain_)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the room is encrypted
|
|
||||||
*/
|
|
||||||
// When a client receives an m.room.encryption event as above, it should set a flag to indicate that messages sent in the room should be encrypted.
|
|
||||||
// This flag should not be cleared if a later m.room.encryption event changes the configuration. This is to avoid a situation where a MITM can simply
|
|
||||||
// ask participants to disable encryption. In short: once encryption is enabled in a room, it can never be disabled.
|
|
||||||
val isEncrypted: Boolean
|
|
||||||
get() = null != algorithm
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the room is versioned, it means that the room is obsolete.
|
|
||||||
* You can't interact with it anymore, but you can still browse the past messages.
|
|
||||||
*/
|
|
||||||
val isVersioned: Boolean
|
|
||||||
get() = roomTombstoneContent != null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the room is a public one
|
|
||||||
*/
|
|
||||||
val isPublic: Boolean
|
|
||||||
get() = TextUtils.equals(if (null != visibility) visibility else joinRule, RoomDirectoryVisibility.DIRECTORY_VISIBILITY_PUBLIC)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of all the room members. Fetch from server if the full list is not loaded yet.
|
|
||||||
*
|
|
||||||
* @param callback The callback to get a copy of the room members list.
|
|
||||||
*/
|
|
||||||
fun getMembersAsync(callback: ApiCallback<List<RoomMember>>) {
|
|
||||||
if (areAllMembersLoaded()) {
|
|
||||||
val res: List<RoomMember>
|
|
||||||
|
|
||||||
synchronized(this) {
|
|
||||||
// make a copy to avoid concurrency modifications
|
|
||||||
res = ArrayList(members.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.onSuccess(res)
|
|
||||||
} else {
|
|
||||||
val doTheRequest: Boolean
|
|
||||||
|
|
||||||
synchronized(getAllMembersCallbacks) {
|
|
||||||
getAllMembersCallbacks.add(callback)
|
|
||||||
|
|
||||||
doTheRequest = getAllMembersCallbacks.size == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doTheRequest) {
|
|
||||||
// Load members from server
|
|
||||||
dataHandler.getMembersAsync(roomId, object : SimpleApiCallback<List<RoomMember>>(callback) {
|
|
||||||
override fun onSuccess(info: List<RoomMember>) {
|
|
||||||
Timber.d("getMembers has returned " + info.size + " users.")
|
|
||||||
|
|
||||||
val store = (dataHandler as MXDataHandler).store
|
|
||||||
var res: List<RoomMember>
|
|
||||||
|
|
||||||
for (member in info) {
|
|
||||||
// Do not erase already known members form the sync
|
|
||||||
if (getMember(member.userId) == null) {
|
|
||||||
setMember(member.userId, member)
|
|
||||||
|
|
||||||
// Also create a User
|
|
||||||
store?.updateUserWithRoomMemberEvent(member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(getAllMembersCallbacks) {
|
|
||||||
for (apiCallback in getAllMembersCallbacks) {
|
|
||||||
// make a copy to avoid concurrency modifications
|
|
||||||
res = ArrayList(members.values)
|
|
||||||
|
|
||||||
apiCallback.onSuccess(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllMembersCallbacks.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
allMembersAreLoaded = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell if all members has been loaded
|
|
||||||
*
|
|
||||||
* @return true if LazyLoading is Off, or if all members has been loaded
|
|
||||||
*/
|
|
||||||
private fun areAllMembersLoaded(): Boolean {
|
|
||||||
return !dataHandler.isLazyLoadingEnabled || allMembersAreLoaded
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force a fetch of the loaded members the next time they will be requested
|
|
||||||
*/
|
|
||||||
fun forceMembersRequest() {
|
|
||||||
allMembersAreLoaded = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the loaded states event list.
|
|
||||||
* The room member events are NOT included.
|
|
||||||
*
|
|
||||||
* @param types the allowed event types.
|
|
||||||
* @return the filtered state events list.
|
|
||||||
*/
|
|
||||||
fun getStateEvents(types: Set<String>?): List<Event> {
|
|
||||||
val filteredStateEvents = ArrayList<Event>()
|
|
||||||
val stateEvents = ArrayList<Event>()
|
|
||||||
|
|
||||||
// merge the values lists
|
|
||||||
val currentStateEvents = this.stateEvents.values
|
|
||||||
for (eventsList in currentStateEvents) {
|
|
||||||
stateEvents.addAll(eventsList)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != types && !types.isEmpty()) {
|
|
||||||
for (stateEvent in stateEvents) {
|
|
||||||
if (types.contains(stateEvent.type)) {
|
|
||||||
filteredStateEvents.add(stateEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filteredStateEvents.addAll(stateEvents)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredStateEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the state events list.
|
|
||||||
* It includes the room member creation events (they are not loaded in memory by default).
|
|
||||||
*
|
|
||||||
* @param store the store in which the state events must be retrieved
|
|
||||||
* @param types the allowed event types.
|
|
||||||
* @param callback the asynchronous callback.
|
|
||||||
*/
|
|
||||||
fun getStateEvents(store: IMXStore?, types: Set<String>?, callback: ApiCallback<List<Event>>) {
|
|
||||||
if (null != store) {
|
|
||||||
val stateEvents = ArrayList<Event>()
|
|
||||||
|
|
||||||
val currentStateEvents = this.stateEvents.values
|
|
||||||
|
|
||||||
for (eventsList in currentStateEvents) {
|
|
||||||
stateEvents.addAll(eventsList)
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve the roomMember creation events
|
|
||||||
store.getRoomStateEvents(roomId, object : SimpleApiCallback<List<Event>>() {
|
|
||||||
override fun onSuccess(events: List<Event>) {
|
|
||||||
stateEvents.addAll(events)
|
|
||||||
|
|
||||||
val filteredStateEvents = ArrayList<Event>()
|
|
||||||
|
|
||||||
if (null != types && !types.isEmpty()) {
|
|
||||||
for (stateEvent in stateEvents) {
|
|
||||||
if (types.contains(stateEvent.type)) {
|
|
||||||
filteredStateEvents.add(stateEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filteredStateEvents.addAll(stateEvents)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.onSuccess(filteredStateEvents)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a list of displayable members.
|
|
||||||
* Some dummy members are created to internal stuff.
|
|
||||||
*
|
|
||||||
* @param callback The callback to get a copy of the displayable room members list.
|
|
||||||
*/
|
|
||||||
fun getDisplayableMembersAsync(callback: ApiCallback<List<RoomMember>>) {
|
|
||||||
getMembersAsync(object : SimpleApiCallback<List<RoomMember>>(callback) {
|
|
||||||
override fun onSuccess(members: List<RoomMember>) {
|
|
||||||
val conferenceUserId = getMember(MXCallsManager.getConferenceUserId(roomId))
|
|
||||||
|
|
||||||
if (null != conferenceUserId) {
|
|
||||||
val membersList = ArrayList(members)
|
|
||||||
membersList.remove(conferenceUserId)
|
|
||||||
callback.onSuccess(membersList)
|
|
||||||
} else {
|
|
||||||
callback.onSuccess(members)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the room member from its user id.
|
|
||||||
*
|
|
||||||
* @param userId the user id.
|
|
||||||
* @param member the new member value.
|
|
||||||
*/
|
|
||||||
private fun setMember(userId: String, member: RoomMember) {
|
|
||||||
// Populate a basic user object if there is none
|
|
||||||
if (member.userId == null) {
|
|
||||||
member.userId = userId
|
|
||||||
}
|
|
||||||
synchronized(this) {
|
|
||||||
if (null != memberDisplayNameByUserId) {
|
|
||||||
memberDisplayNameByUserId!!.remove(userId)
|
|
||||||
}
|
|
||||||
members.put(userId, member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a room member from its user id.
|
|
||||||
*
|
|
||||||
* @param userId the user id.
|
|
||||||
* @return the linked member it exists.
|
|
||||||
*/
|
|
||||||
// TODO Change this? Can return null if all members are not loaded yet
|
|
||||||
fun getMember(userId: String): RoomMember? {
|
|
||||||
val member: RoomMember?
|
|
||||||
|
|
||||||
synchronized(this) {
|
|
||||||
member = members[userId]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member == null) {
|
|
||||||
// TODO LazyLoading
|
|
||||||
Log.e(LOG_TAG, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Null member '$userId' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
|
||||||
|
|
||||||
if (TextUtils.equals(dataHandler.userId, userId)) {
|
|
||||||
// This should never happen
|
|
||||||
Log.e(LOG_TAG, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Null current user '$userId' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return member
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a room member from its original event id.
|
|
||||||
* It can return null if the lazy loading is enabled and if the member is not loaded yet.
|
|
||||||
*
|
|
||||||
* @param eventId the event id.
|
|
||||||
* @return the linked member if it exists and if it is loaded.
|
|
||||||
*/
|
|
||||||
fun getMemberByEventId(eventId: String): RoomMember? {
|
|
||||||
var member: RoomMember? = null
|
|
||||||
|
|
||||||
synchronized(this) {
|
|
||||||
for (aMember in members.values) {
|
|
||||||
if (aMember.originalEventId == eventId) {
|
|
||||||
member = aMember
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return member
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a member defines by its user id.
|
|
||||||
*
|
|
||||||
* @param userId the user id.
|
|
||||||
*/
|
|
||||||
fun removeMember(userId: String) {
|
|
||||||
synchronized(this) {
|
|
||||||
members.remove(userId)
|
|
||||||
// remove the cached display name
|
|
||||||
if (null != memberDisplayNameByUserId) {
|
|
||||||
memberDisplayNameByUserId!!.remove(userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a member from an invitation token.
|
|
||||||
*
|
|
||||||
* @param thirdPartyInviteToken the third party invitation token.
|
|
||||||
* @return the member it exists.
|
|
||||||
*/
|
|
||||||
fun memberWithThirdPartyInviteToken(thirdPartyInviteToken: String): RoomMember? {
|
|
||||||
return membersWithThirdPartyInviteTokenCache[thirdPartyInviteToken]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a RoomThirdPartyInvite from its token.
|
|
||||||
*
|
|
||||||
* @param thirdPartyInviteToken the third party invitation token.
|
|
||||||
* @return the linked RoomThirdPartyInvite if it exists
|
|
||||||
*/
|
|
||||||
fun thirdPartyInviteWithToken(thirdPartyInviteToken: String): RoomThirdPartyInvite? {
|
|
||||||
return thirdPartyInvites[thirdPartyInviteToken]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the third party invite list.
|
|
||||||
*/
|
|
||||||
fun thirdPartyInvites(): Collection<RoomThirdPartyInvite> {
|
|
||||||
return thirdPartyInvites.values
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the user userId can back paginate.
|
|
||||||
*
|
|
||||||
* @param isJoined true is user is in the room
|
|
||||||
* @param isInvited true is user is invited to the room
|
|
||||||
* @return true if the user can back paginate.
|
|
||||||
*/
|
|
||||||
fun canBackPaginate(isJoined: Boolean, isInvited: Boolean): Boolean {
|
|
||||||
val visibility = if (TextUtils.isEmpty(historyVisibility)) HISTORY_VISIBILITY_SHARED else historyVisibility
|
|
||||||
return (isJoined
|
|
||||||
|| visibility == HISTORY_VISIBILITY_WORLD_READABLE
|
|
||||||
|| visibility == HISTORY_VISIBILITY_SHARED
|
|
||||||
|| visibility == HISTORY_VISIBILITY_INVITED && isInvited)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the currentAliases for any known domains
|
|
||||||
*
|
|
||||||
* @return the currentAliases list
|
|
||||||
*/
|
|
||||||
fun getAliases(): List<String> {
|
|
||||||
if (mergedAliasesList != null) {
|
|
||||||
return mergedAliasesList as List<String>
|
|
||||||
}
|
|
||||||
val merged = ArrayList<String>()
|
|
||||||
for (url in aliasesByDomain.keys) {
|
|
||||||
merged.addAll(aliasesByDomain[url] ?: emptyList())
|
|
||||||
}
|
|
||||||
// ensure that the current currentAliases have been added.
|
|
||||||
// for example for the public rooms because there is no applystate call.
|
|
||||||
for (anAlias in currentAliases) {
|
|
||||||
if (merged.indexOf(anAlias) < 0) {
|
|
||||||
merged.add(anAlias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mergedAliasesList = merged
|
|
||||||
return merged
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an alias.
|
|
||||||
*
|
|
||||||
* @param alias the alias to remove
|
|
||||||
*/
|
|
||||||
fun removeAlias(alias: String) {
|
|
||||||
if (getAliases().indexOf(alias) >= 0) {
|
|
||||||
currentAliases.remove(alias)
|
|
||||||
for (host in aliasesByDomain.keys) {
|
|
||||||
aliasesByDomain_[host]?.remove(alias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mergedAliasesList = null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an alias.
|
|
||||||
*
|
|
||||||
* @param alias the alias to add
|
|
||||||
*/
|
|
||||||
fun addAlias(alias: String) {
|
|
||||||
if (getAliases().indexOf(alias) < 0) {
|
|
||||||
// patch until the server echoes the alias addition.
|
|
||||||
mergedAliasesList?.add(alias)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the room has a predecessor
|
|
||||||
*/
|
|
||||||
fun hasPredecessor(): Boolean {
|
|
||||||
return roomCreateContent != null && roomCreateContent!!.hasPredecessor()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the encryption algorithm
|
|
||||||
*/
|
|
||||||
fun encryptionAlgorithm(): String? {
|
|
||||||
return if (TextUtils.isEmpty(algorithm)) null else algorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the given event (relevant for state changes) to our state.
|
|
||||||
*
|
|
||||||
* @param store the store to use
|
|
||||||
* @param event the event
|
|
||||||
* @param direction how the event should affect the state: Forwards for applying, backwards for un-applying (applying the previous state)
|
|
||||||
* @return true if the event is managed
|
|
||||||
*/
|
|
||||||
fun applyState(store: IMXStore?, event: Event, direction: EventTimeline.Direction): Boolean {
|
|
||||||
if (event.stateKey == null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val contentToConsider = if (direction == EventTimeline.Direction.FORWARDS) event.contentAsJsonObject else event.prevContentAsJsonObject
|
|
||||||
val dataToConsider = if (direction == EventTimeline.Direction.FORWARDS) event.content else event.prevContent
|
|
||||||
|
|
||||||
|
|
||||||
val eventType = event.type
|
|
||||||
try {
|
|
||||||
if (EventType.STATE_ROOM_NAME == eventType) {
|
|
||||||
name = JsonUtils.toStateEvent(contentToConsider).name
|
|
||||||
} else if (EventType.STATE_ROOM_TOPIC == eventType) {
|
|
||||||
topic = JsonUtils.toStateEvent(contentToConsider).topic
|
|
||||||
} else if (EventType.STATE_ROOM_CREATE == eventType) {
|
|
||||||
roomCreateContent = JsonUtils.toRoomCreateContent(contentToConsider)
|
|
||||||
} else if (EventType.STATE_ROOM_JOIN_RULES == eventType) {
|
|
||||||
joinRule = JsonUtils.toStateEvent(contentToConsider).joinRule
|
|
||||||
} else if (EventType.STATE_ROOM_GUEST_ACCESS == eventType) {
|
|
||||||
guestAccess = JsonUtils.toStateEvent(contentToConsider).guestAccess
|
|
||||||
} else if (EventType.STATE_ROOM_ALIASES == eventType) {
|
|
||||||
if (!TextUtils.isEmpty(event.stateKey)) {
|
|
||||||
// backward compatibility
|
|
||||||
currentAliases = JsonUtils.toStateEvent(contentToConsider).aliases
|
|
||||||
// sanity check
|
|
||||||
if (null != currentAliases) {
|
|
||||||
aliasesByDomain_[event.stateKey] = currentAliases
|
|
||||||
roomAliases[event.stateKey] = event
|
|
||||||
} else {
|
|
||||||
aliasesByDomain_[event.stateKey] = ArrayList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (EventType.ENCRYPTION == eventType) {
|
|
||||||
algorithm = JsonUtils.toStateEvent(contentToConsider).algorithm
|
|
||||||
// When a client receives an m.room.encryption event as above, it should set a flag to indicate that messages sent
|
|
||||||
// in the room should be encrypted.
|
|
||||||
// This flag should not be cleared if a later m.room.encryption event changes the configuration. This is to avoid
|
|
||||||
// a situation where a MITM can simply ask participants to disable encryption. In short: once encryption is enabled
|
|
||||||
// in a room, it can never be disabled.
|
|
||||||
if (algorithm == null) {
|
|
||||||
algorithm = ""
|
|
||||||
}
|
|
||||||
} else if (EventType.STATE_CANONICAL_ALIAS == eventType) {
|
|
||||||
// SPEC-125
|
|
||||||
canonicalAlias = JsonUtils.toStateEvent(contentToConsider).canonicalAlias
|
|
||||||
} else if (EventType.STATE_HISTORY_VISIBILITY == eventType) {
|
|
||||||
// SPEC-134
|
|
||||||
historyVisibility = JsonUtils.toStateEvent(contentToConsider).historyVisibility
|
|
||||||
} else if (EventType.STATE_ROOM_AVATAR == eventType) {
|
|
||||||
url = JsonUtils.toStateEvent(contentToConsider).url
|
|
||||||
} else if (EventType.STATE_RELATED_GROUPS == eventType) {
|
|
||||||
groups = JsonUtils.toStateEvent(contentToConsider).groups
|
|
||||||
} else if (EventType.STATE_ROOM_MEMBER == eventType) {
|
|
||||||
val member = JsonUtils.toRoomMember(contentToConsider)
|
|
||||||
val userId = event.stateKey
|
|
||||||
if (member == null) {
|
|
||||||
// the member has already been removed
|
|
||||||
if (getMember(userId) == null) {
|
|
||||||
Log.e(LOG_TAG, "## applyState() : the user $userId is not anymore a member of $roomId")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
removeMember(userId)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
member.userId = userId
|
|
||||||
member.originServerTs = event.originServerTs ?: -1
|
|
||||||
member.originalEventId = event.eventId
|
|
||||||
member.mSender = event.sender
|
|
||||||
if (null != store && direction == EventTimeline.Direction.FORWARDS) {
|
|
||||||
store.storeRoomStateEvent(roomId, event)
|
|
||||||
}
|
|
||||||
val currentMember = getMember(userId)
|
|
||||||
// check if the member is the same
|
|
||||||
// duplicated message ?
|
|
||||||
if (member.equals(currentMember)) {
|
|
||||||
Log.e(LOG_TAG, "## applyState() : seems being a duplicated event for $userId in room $roomId")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// when a member leaves a room, his avatar / display name is not anymore provided
|
|
||||||
if (currentMember != null && (TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE) || TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_BAN))) {
|
|
||||||
if (member.getAvatarUrl() == null) {
|
|
||||||
member.setAvatarUrl(currentMember.getAvatarUrl())
|
|
||||||
}
|
|
||||||
if (member.displayname == null) {
|
|
||||||
member.displayname = currentMember.displayname
|
|
||||||
}
|
|
||||||
// remove the cached display name
|
|
||||||
memberDisplayNameByUserId.remove(userId)
|
|
||||||
|
|
||||||
// test if the user has been kicked
|
|
||||||
if (!TextUtils.equals(event.sender, event.stateKey)
|
|
||||||
&& TextUtils.equals(currentMember.membership, RoomMember.MEMBERSHIP_JOIN)
|
|
||||||
&& TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE)) {
|
|
||||||
member.membership = RoomMember.MEMBERSHIP_KICK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction == EventTimeline.Direction.FORWARDS && null != store) {
|
|
||||||
store.updateUserWithRoomMemberEvent(member)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache room member event that is successor of a third party invite event
|
|
||||||
if (!TextUtils.isEmpty(member.thirdPartyInviteToken)) {
|
|
||||||
membersWithThirdPartyInviteTokenCache[member.thirdPartyInviteToken] = member
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(LOG_TAG, "## applyState() - EVENT_TYPE_STATE_ROOM_MEMBER failed " + e.message, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
setMember(userId, member)
|
|
||||||
}
|
|
||||||
} else if (EventType.STATE_ROOM_POWER_LEVELS == eventType) {
|
|
||||||
powerLevels = event.toModel(dataToConsider)
|
|
||||||
} else if (EventType.STATE_ROOM_THIRD_PARTY_INVITE == eventType) {
|
|
||||||
val thirdPartyInvite = JsonUtils.toRoomThirdPartyInvite(contentToConsider)
|
|
||||||
thirdPartyInvite.token = event.stateKey
|
|
||||||
if (direction == EventTimeline.Direction.FORWARDS && null != store) {
|
|
||||||
store.storeRoomStateEvent(roomId, event)
|
|
||||||
}
|
|
||||||
if (!TextUtils.isEmpty(thirdPartyInvite.token)) {
|
|
||||||
thirdPartyInvites[thirdPartyInvite.token] = thirdPartyInvite
|
|
||||||
}
|
|
||||||
} else if (EventType.STATE_ROOM_TOMBSTONE == eventType) {
|
|
||||||
roomTombstoneContent = JsonUtils.toRoomTombstoneContent(contentToConsider)
|
|
||||||
} else if (EventType.STATE_PINNED_EVENT == eventType) {
|
|
||||||
roomPinnedEventsContent = JsonUtils.toRoomPinnedEventsContent(contentToConsider)
|
|
||||||
}
|
|
||||||
// same the latest room state events
|
|
||||||
// excepts the membership ones
|
|
||||||
// they are saved elsewhere
|
|
||||||
if (!TextUtils.isEmpty(eventType) && EventType.STATE_ROOM_MEMBER != eventType) {
|
|
||||||
var eventsList: MutableList<Event>? = stateEvents[eventType]
|
|
||||||
if (eventsList == null) {
|
|
||||||
eventsList = ArrayList()
|
|
||||||
stateEvents[eventType] = eventsList
|
|
||||||
}
|
|
||||||
eventsList.add(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(LOG_TAG, "applyState failed with error " + e.message, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an unique display name of the member userId.
|
|
||||||
*
|
|
||||||
* @param userId the user id
|
|
||||||
* @return unique display name
|
|
||||||
*/
|
|
||||||
fun getMemberName(userId: String?): String? {
|
|
||||||
// sanity check
|
|
||||||
if (userId == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
var displayName: String?
|
|
||||||
synchronized(this) {
|
|
||||||
displayName = memberDisplayNameByUserId[userId]
|
|
||||||
}
|
|
||||||
if (displayName != null) {
|
|
||||||
return displayName
|
|
||||||
}
|
|
||||||
// Get the user display name from the member list of the room
|
|
||||||
val member = getMember(userId)
|
|
||||||
// Do not consider null display name
|
|
||||||
if (null != member && !TextUtils.isEmpty(member.displayname)) {
|
|
||||||
displayName = member.displayname
|
|
||||||
synchronized(this) {
|
|
||||||
val matrixIds = ArrayList<String>()
|
|
||||||
// Disambiguate users who have the same display name in the room
|
|
||||||
for (aMember in members.values) {
|
|
||||||
if (displayName == aMember.displayname) {
|
|
||||||
matrixIds.add(aMember.userId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if several users have the same display name
|
|
||||||
// index it i.e bob (<Matrix id>)
|
|
||||||
if (matrixIds.size > 1) {
|
|
||||||
displayName += " ($userId)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (null != member && TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_INVITE)) {
|
|
||||||
val user = dataHandler.getUser(userId)
|
|
||||||
if (null != user) {
|
|
||||||
displayName = user.displayname
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (displayName == null) {
|
|
||||||
// By default, use the user ID
|
|
||||||
displayName = userId
|
|
||||||
}
|
|
||||||
displayName?.let {
|
|
||||||
memberDisplayNameByUserId[userId] = it
|
|
||||||
}
|
|
||||||
return displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val LOG_TAG = RoomState::class.java.simpleName
|
|
||||||
private val serialVersionUID = -6019932024524988201L
|
|
||||||
|
|
||||||
val JOIN_RULE_PUBLIC = "public"
|
|
||||||
val JOIN_RULE_INVITE = "invite"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* room access is granted to guests
|
|
||||||
*/
|
|
||||||
val GUEST_ACCESS_CAN_JOIN = "can_join"
|
|
||||||
/**
|
|
||||||
* room access is denied to guests
|
|
||||||
*/
|
|
||||||
val GUEST_ACCESS_FORBIDDEN = "forbidden"
|
|
||||||
|
|
||||||
val HISTORY_VISIBILITY_SHARED = "shared"
|
|
||||||
val HISTORY_VISIBILITY_INVITED = "invited"
|
|
||||||
val HISTORY_VISIBILITY_JOINED = "joined"
|
|
||||||
val HISTORY_VISIBILITY_WORLD_READABLE = "world_readable"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,517 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
|
||||||
|
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import im.vector.matrix.android.api.events.Event
|
|
||||||
import im.vector.matrix.android.api.events.EventContent
|
|
||||||
import im.vector.matrix.android.api.events.EventType
|
|
||||||
import im.vector.matrix.android.internal.legacy.call.MXCallsManager
|
|
||||||
import im.vector.matrix.android.internal.legacy.data.RoomState
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.RoomMember
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.message.Message
|
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.RoomSyncSummary
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores summarised information about the room.
|
|
||||||
*/
|
|
||||||
class RoomSummary() {
|
|
||||||
|
|
||||||
private var mRoomId: String? = null
|
|
||||||
/**
|
|
||||||
* @return the topic.
|
|
||||||
*/
|
|
||||||
var roomTopic: String? = null
|
|
||||||
private set
|
|
||||||
private var mLatestReceivedEvent: Event? = null
|
|
||||||
|
|
||||||
// the room state is only used to check
|
|
||||||
// 1- the invitation status
|
|
||||||
// 2- the members display name
|
|
||||||
@Transient private var mLatestRoomState: RoomState? = null
|
|
||||||
|
|
||||||
// defines the latest read message
|
|
||||||
/**
|
|
||||||
* @return the read receipt event id
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Set the read receipt event Id
|
|
||||||
*
|
|
||||||
* @param eventId the read receipt event id.
|
|
||||||
*/
|
|
||||||
var readReceiptEventId: String? = null
|
|
||||||
set(eventId) {
|
|
||||||
Timber.d("## setReadReceiptEventId() : " + eventId + " roomId " + getRoomId())
|
|
||||||
field = eventId
|
|
||||||
}
|
|
||||||
|
|
||||||
// the read marker event id
|
|
||||||
private var mReadMarkerEventId: String? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the room tags
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the room tags
|
|
||||||
*
|
|
||||||
* @param roomTags the room tags
|
|
||||||
*/
|
|
||||||
// wraps the set into a serializable one
|
|
||||||
var roomTags: Set<String>? = null
|
|
||||||
set(roomTags) = if (roomTags != null) {
|
|
||||||
field = HashSet(roomTags)
|
|
||||||
} else {
|
|
||||||
field = HashSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
// counters
|
|
||||||
var mUnreadEventsCount: Int = 0
|
|
||||||
var mNotificationCount: Int = 0
|
|
||||||
var mHighlightsCount: Int = 0
|
|
||||||
|
|
||||||
// invitation status
|
|
||||||
// retrieved at initial sync
|
|
||||||
// the roomstate is not always known
|
|
||||||
/**
|
|
||||||
* @return the inviter user id.
|
|
||||||
*/
|
|
||||||
var inviterUserId: String? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
// retrieved from the roomState
|
|
||||||
private var mInviterName: String? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the user id
|
|
||||||
*/
|
|
||||||
var userId: String? = null
|
|
||||||
|
|
||||||
// Info from sync, depending on the room position in the sync
|
|
||||||
private var mUserMembership: String? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell if the room is a user conference user one
|
|
||||||
*/
|
|
||||||
private var mIsConferenceUserRoom: Boolean? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data from RoomSyncSummary
|
|
||||||
*/
|
|
||||||
private val mHeroes = ArrayList<String>()
|
|
||||||
|
|
||||||
var numberOfJoinedMembers: Int = 0
|
|
||||||
private set
|
|
||||||
|
|
||||||
var numberOfInvitedMembers: Int = 0
|
|
||||||
private set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the current user is invited
|
|
||||||
*/
|
|
||||||
val isInvited: Boolean
|
|
||||||
get() = RoomMember.MEMBERSHIP_INVITE == mUserMembership
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the current user is invited
|
|
||||||
*/
|
|
||||||
val isJoined: Boolean
|
|
||||||
get() = RoomMember.MEMBERSHIP_JOIN == mUserMembership
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the read receipt event id
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Set the read marker event Id
|
|
||||||
*
|
|
||||||
* @param eventId the read marker event id.
|
|
||||||
*/
|
|
||||||
var readMarkerEventId: String?
|
|
||||||
get() {
|
|
||||||
if (TextUtils.isEmpty(mReadMarkerEventId)) {
|
|
||||||
Timber.e("## getReadMarkerEventId') : null mReadMarkerEventId, in " + getRoomId()!!)
|
|
||||||
mReadMarkerEventId = readReceiptEventId
|
|
||||||
}
|
|
||||||
|
|
||||||
return mReadMarkerEventId
|
|
||||||
}
|
|
||||||
set(eventId) {
|
|
||||||
Timber.d("## setReadMarkerEventId() : " + eventId + " roomId " + getRoomId())
|
|
||||||
|
|
||||||
if (TextUtils.isEmpty(eventId)) {
|
|
||||||
Timber.e("## setReadMarkerEventId') : null mReadMarkerEventId, in " + getRoomId()!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
mReadMarkerEventId = eventId
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the unread events count
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the unread message counter
|
|
||||||
*
|
|
||||||
* @param count the unread events count.
|
|
||||||
*/
|
|
||||||
var unreadEventsCount: Int
|
|
||||||
get() = mUnreadEventsCount
|
|
||||||
set(count) {
|
|
||||||
Timber.d("## setUnreadEventsCount() : " + count + " roomId " + getRoomId())
|
|
||||||
mUnreadEventsCount = count
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the notification count
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the notification counter
|
|
||||||
*
|
|
||||||
* @param count the notification counter
|
|
||||||
*/
|
|
||||||
var notificationCount: Int
|
|
||||||
get() = mNotificationCount
|
|
||||||
set(count) {
|
|
||||||
Timber.d("## setNotificationCount() : " + count + " roomId " + getRoomId())
|
|
||||||
mNotificationCount = count
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the highlight count
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Update the highlight counter
|
|
||||||
*
|
|
||||||
* @param count the highlight counter
|
|
||||||
*/
|
|
||||||
var highlightCount: Int
|
|
||||||
get() = mHighlightsCount
|
|
||||||
set(count) {
|
|
||||||
Timber.d("## setHighlightCount() : " + count + " roomId " + getRoomId())
|
|
||||||
mHighlightsCount = count
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if it is not yet initialized
|
|
||||||
// FIXME LazyLoading Heroes does not contains me
|
|
||||||
// FIXME I'ms not sure this code will work anymore
|
|
||||||
// works only with 1:1 room
|
|
||||||
var isConferenceUserRoom: Boolean
|
|
||||||
get() {
|
|
||||||
if (null == mIsConferenceUserRoom) {
|
|
||||||
|
|
||||||
mIsConferenceUserRoom = false
|
|
||||||
|
|
||||||
val membersId = heroes
|
|
||||||
if (2 == membersId.size) {
|
|
||||||
for (userId in membersId) {
|
|
||||||
if (MXCallsManager.isConferenceUserId(userId)) {
|
|
||||||
mIsConferenceUserRoom = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mIsConferenceUserRoom!!
|
|
||||||
}
|
|
||||||
set(isConferenceUserRoom) {
|
|
||||||
mIsConferenceUserRoom = isConferenceUserRoom
|
|
||||||
}
|
|
||||||
|
|
||||||
val heroes: List<String>
|
|
||||||
get() = mHeroes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a room summary
|
|
||||||
*
|
|
||||||
* @param fromSummary the summary source
|
|
||||||
* @param event the latest event of the room
|
|
||||||
* @param roomState the room state - used to display the event
|
|
||||||
* @param userId our own user id - used to display the room name
|
|
||||||
*/
|
|
||||||
constructor(fromSummary: RoomSummary?,
|
|
||||||
event: Event?,
|
|
||||||
roomState: RoomState?,
|
|
||||||
userId: String) : this() {
|
|
||||||
this.userId = userId
|
|
||||||
if (roomState != null) {
|
|
||||||
setRoomId(roomState.roomId)
|
|
||||||
}
|
|
||||||
if (mRoomId == null) {
|
|
||||||
event?.roomId?.let { setRoomId(it) }
|
|
||||||
}
|
|
||||||
setLatestReceivedEvent(event, roomState)
|
|
||||||
|
|
||||||
// if no summary is provided
|
|
||||||
if (fromSummary == null) {
|
|
||||||
event?.let {
|
|
||||||
readMarkerEventId = it.eventId
|
|
||||||
readReceiptEventId = it.eventId
|
|
||||||
}
|
|
||||||
roomState?.let {
|
|
||||||
highlightCount = it.highlightCount
|
|
||||||
notificationCount = it.highlightCount
|
|
||||||
}
|
|
||||||
unreadEventsCount = Math.max(highlightCount, notificationCount)
|
|
||||||
} else {
|
|
||||||
// else use the provided summary data
|
|
||||||
readMarkerEventId = fromSummary.readMarkerEventId
|
|
||||||
readReceiptEventId = fromSummary.readReceiptEventId
|
|
||||||
unreadEventsCount = fromSummary.unreadEventsCount
|
|
||||||
highlightCount = fromSummary.highlightCount
|
|
||||||
notificationCount = fromSummary.notificationCount
|
|
||||||
mHeroes.addAll(fromSummary.mHeroes)
|
|
||||||
numberOfJoinedMembers = fromSummary.numberOfJoinedMembers
|
|
||||||
numberOfInvitedMembers = fromSummary.numberOfInvitedMembers
|
|
||||||
mUserMembership = fromSummary.mUserMembership
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the room id
|
|
||||||
*/
|
|
||||||
fun getRoomId(): String? {
|
|
||||||
return mRoomId
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the room summary event.
|
|
||||||
*/
|
|
||||||
fun getLatestReceivedEvent(): Event? {
|
|
||||||
return mLatestReceivedEvent
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dedicated room state.
|
|
||||||
*/
|
|
||||||
fun getLatestRoomState(): RoomState? {
|
|
||||||
return mLatestRoomState
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To call when the room is in the invited section of the sync response
|
|
||||||
*/
|
|
||||||
fun setIsInvited() {
|
|
||||||
mUserMembership = RoomMember.MEMBERSHIP_INVITE
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To call when the room is in the joined section of the sync response
|
|
||||||
*/
|
|
||||||
fun setIsJoined() {
|
|
||||||
mUserMembership = RoomMember.MEMBERSHIP_JOIN
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the room's [org.matrix.androidsdk.rest.model.Event.EVENT_TYPE_STATE_ROOM_TOPIC].
|
|
||||||
*
|
|
||||||
* @param topic The topic
|
|
||||||
* @return This summary for chaining calls.
|
|
||||||
*/
|
|
||||||
fun setTopic(topic: String): RoomSummary {
|
|
||||||
roomTopic = topic
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the room's ID..
|
|
||||||
*
|
|
||||||
* @param roomId The room ID
|
|
||||||
* @return This summary for chaining calls.
|
|
||||||
*/
|
|
||||||
fun setRoomId(roomId: String): RoomSummary {
|
|
||||||
mRoomId = roomId
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the latest tracked event (e.g. the latest m.room.message)
|
|
||||||
*
|
|
||||||
* @param event The most-recent event.
|
|
||||||
* @param roomState The room state
|
|
||||||
* @return This summary for chaining calls.
|
|
||||||
*/
|
|
||||||
fun setLatestReceivedEvent(event: Event?, roomState: RoomState?): RoomSummary {
|
|
||||||
setLatestReceivedEvent(event)
|
|
||||||
setLatestRoomState(roomState)
|
|
||||||
|
|
||||||
if (null != roomState) {
|
|
||||||
setTopic(roomState.topic)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the latest tracked event (e.g. the latest m.room.message)
|
|
||||||
*
|
|
||||||
* @param event The most-recent event.
|
|
||||||
* @return This summary for chaining calls.
|
|
||||||
*/
|
|
||||||
fun setLatestReceivedEvent(event: Event?): RoomSummary {
|
|
||||||
mLatestReceivedEvent = event
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the latest RoomState
|
|
||||||
*
|
|
||||||
* @param roomState The room state of the latest event.
|
|
||||||
* @return This summary for chaining calls.
|
|
||||||
*/
|
|
||||||
fun setLatestRoomState(roomState: RoomState?): RoomSummary {
|
|
||||||
mLatestRoomState = roomState
|
|
||||||
|
|
||||||
// Keep this code for compatibility?
|
|
||||||
var isInvited = false
|
|
||||||
|
|
||||||
// check for the invitation status
|
|
||||||
if (null != mLatestRoomState) {
|
|
||||||
val member = mLatestRoomState!!.getMember(userId)
|
|
||||||
isInvited = null != member && RoomMember.MEMBERSHIP_INVITE == member.membership
|
|
||||||
}
|
|
||||||
// when invited, the only received message should be the invitation one
|
|
||||||
if (isInvited) {
|
|
||||||
mInviterName = null
|
|
||||||
|
|
||||||
if (null != mLatestReceivedEvent) {
|
|
||||||
inviterUserId = mLatestReceivedEvent!!.sender
|
|
||||||
mInviterName = inviterUserId
|
|
||||||
|
|
||||||
// try to retrieve a display name
|
|
||||||
if (null != mLatestRoomState) {
|
|
||||||
mInviterName = mLatestRoomState!!.getMemberName(mLatestReceivedEvent!!.sender)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mInviterName = null
|
|
||||||
inviterUserId = mInviterName
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setRoomSyncSummary(roomSyncSummary: RoomSyncSummary) {
|
|
||||||
if (roomSyncSummary.heroes != null) {
|
|
||||||
mHeroes.clear()
|
|
||||||
mHeroes.addAll(roomSyncSummary.heroes)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roomSyncSummary.joinedMembersCount != null) {
|
|
||||||
// Update the value
|
|
||||||
numberOfJoinedMembers = roomSyncSummary.joinedMembersCount
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roomSyncSummary.invitedMembersCount != null) {
|
|
||||||
// Update the value
|
|
||||||
numberOfInvitedMembers = roomSyncSummary.invitedMembersCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val serialVersionUID = -3683013938626566489L
|
|
||||||
|
|
||||||
// list of supported types
|
|
||||||
private val supportedType = Arrays.asList(
|
|
||||||
EventType.STATE_ROOM_TOPIC,
|
|
||||||
EventType.ENCRYPTED,
|
|
||||||
EventType.ENCRYPTION,
|
|
||||||
EventType.STATE_ROOM_NAME,
|
|
||||||
EventType.STATE_ROOM_MEMBER,
|
|
||||||
EventType.STATE_ROOM_CREATE,
|
|
||||||
EventType.STATE_HISTORY_VISIBILITY,
|
|
||||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
|
||||||
EventType.STICKER)
|
|
||||||
|
|
||||||
// List of known unsupported types
|
|
||||||
private val knownUnsupportedType = Arrays.asList(
|
|
||||||
EventType.TYPING,
|
|
||||||
EventType.STATE_ROOM_POWER_LEVELS,
|
|
||||||
EventType.STATE_ROOM_JOIN_RULES,
|
|
||||||
EventType.STATE_CANONICAL_ALIAS,
|
|
||||||
EventType.STATE_ROOM_ALIASES,
|
|
||||||
EventType.PREVIEW_URLS,
|
|
||||||
EventType.STATE_RELATED_GROUPS,
|
|
||||||
EventType.STATE_ROOM_GUEST_ACCESS,
|
|
||||||
EventType.REDACTION)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if the event can be summarized.
|
|
||||||
* Some event types are not yet supported.
|
|
||||||
*
|
|
||||||
* @param event the event to test.
|
|
||||||
* @return true if the event can be summarized
|
|
||||||
*/
|
|
||||||
fun isSupportedEvent(event: Event): Boolean {
|
|
||||||
val type = event.type
|
|
||||||
var isSupported = false
|
|
||||||
|
|
||||||
// check if the msgtype is supported
|
|
||||||
if (TextUtils.equals(EventType.MESSAGE, type)) {
|
|
||||||
try {
|
|
||||||
val eventContent = event.contentAsJsonObject
|
|
||||||
var msgType = ""
|
|
||||||
|
|
||||||
val element = eventContent!!.get("msgtype")
|
|
||||||
|
|
||||||
if (null != element) {
|
|
||||||
msgType = element.asString
|
|
||||||
}
|
|
||||||
|
|
||||||
isSupported = (TextUtils.equals(msgType, Message.MSGTYPE_TEXT)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_EMOTE)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_NOTICE)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_IMAGE)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_AUDIO)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_VIDEO)
|
|
||||||
|| TextUtils.equals(msgType, Message.MSGTYPE_FILE))
|
|
||||||
|
|
||||||
if (!isSupported && !TextUtils.isEmpty(msgType)) {
|
|
||||||
Timber.e("isSupportedEvent : Unsupported msg type $msgType")
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e, "isSupportedEvent failed " + e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (EventType.ENCRYPTED == type) {
|
|
||||||
isSupported = event.content?.isNotEmpty() ?: false
|
|
||||||
} else if (EventType.STATE_ROOM_MEMBER == type) {
|
|
||||||
val eventContentAsJsonObject = event.contentAsJsonObject
|
|
||||||
if (eventContentAsJsonObject != null) {
|
|
||||||
if (eventContentAsJsonObject.entrySet().isEmpty()) {
|
|
||||||
Timber.d("isSupportedEvent : room member with no content is not supported")
|
|
||||||
} else {
|
|
||||||
// do not display the avatar / display name update
|
|
||||||
val prevEventContent = event.prevContent<EventContent>()
|
|
||||||
val eventContent = event.content<EventContent>()
|
|
||||||
var membership: String? = null
|
|
||||||
var preMembership: String? = null
|
|
||||||
if (eventContent != null) {
|
|
||||||
membership = eventContent.membership
|
|
||||||
}
|
|
||||||
if (prevEventContent != null) {
|
|
||||||
preMembership = prevEventContent.membership
|
|
||||||
}
|
|
||||||
|
|
||||||
isSupported = !TextUtils.equals(membership, preMembership)
|
|
||||||
|
|
||||||
if (!isSupported) {
|
|
||||||
Timber.d("isSupportedEvent : do not support avatar display name update")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
isSupported = supportedType.contains(type) || event.isCallEvent && !TextUtils.isEmpty(type) && EventType.CALL_CANDIDATES != type
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isSupported) {
|
|
||||||
// some events are known to be never traced
|
|
||||||
// avoid warning when it is not required.
|
|
||||||
if (!knownUnsupportedType.contains(type)) {
|
|
||||||
Timber.e("isSupportedEvent : Unsupported event type $type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return isSupported
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package im.vector.matrix.android.api.rooms.timeline;
|
|
||||||
|
|
||||||
import im.vector.matrix.android.api.events.Event;
|
|
||||||
import im.vector.matrix.android.api.rooms.RoomState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `EventTimeline` instance represents a contiguous sequence of events in a room.
|
|
||||||
* <p>
|
|
||||||
* There are two kinds of timeline:
|
|
||||||
* <p>
|
|
||||||
* - live timelines: they receive live events from the events stream. You can paginate
|
|
||||||
* backwards but not forwards.
|
|
||||||
* <p>
|
|
||||||
* - past timelines: they start in the past from an `initialEventId`. They are filled
|
|
||||||
* with events on calls of [MXEventTimeline paginate] in backwards or forwards direction.
|
|
||||||
*/
|
|
||||||
public interface EventTimeline {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The state of the room at the top most recent event of the timeline.
|
|
||||||
*/
|
|
||||||
RoomState getState();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The direction from which an incoming event is considered.
|
|
||||||
*/
|
|
||||||
enum Direction {
|
|
||||||
/**
|
|
||||||
* Forwards when the event is added to the end of the timeline.
|
|
||||||
* These events come from the /sync stream or from forwards pagination.
|
|
||||||
*/
|
|
||||||
FORWARDS,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backwards when the event is added to the start of the timeline.
|
|
||||||
* These events come from a back pagination.
|
|
||||||
*/
|
|
||||||
BACKWARDS
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Listener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call when an event has been handled in the timeline.
|
|
||||||
*
|
|
||||||
* @param event the event.
|
|
||||||
* @param direction the direction.
|
|
||||||
* @param roomState the room state
|
|
||||||
*/
|
|
||||||
void onEvent(Event event, Direction direction, RoomState roomState);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,21 @@
|
|||||||
package im.vector.matrix.android.api.session
|
package im.vector.matrix.android.api.session
|
||||||
|
|
||||||
import android.support.annotation.MainThread
|
import android.support.annotation.MainThread
|
||||||
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
||||||
import im.vector.matrix.android.internal.events.sync.job.SyncThread
|
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||||
|
|
||||||
interface Session {
|
interface Session : RoomService {
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
fun open()
|
fun open()
|
||||||
|
|
||||||
|
@MainThread
|
||||||
|
fun close()
|
||||||
|
|
||||||
fun syncThread(): SyncThread
|
fun syncThread(): SyncThread
|
||||||
|
|
||||||
// Visible for testing request directly. Will be deleted
|
// Visible for testing request directly. Will be deleted
|
||||||
fun realmHolder(): SessionRealmHolder
|
fun realmHolder(): SessionRealmHolder
|
||||||
|
|
||||||
@MainThread
|
|
||||||
fun close()
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.events
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
@ -51,5 +51,3 @@ data class Event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.events
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
|
|
||||||
object EventType {
|
object EventType {
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.events
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -0,0 +1,7 @@
|
|||||||
|
package im.vector.matrix.android.api.session.room
|
||||||
|
|
||||||
|
interface Room {
|
||||||
|
|
||||||
|
val roomId: String
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package im.vector.matrix.android.api.session.room
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
|
|
||||||
|
interface RoomService {
|
||||||
|
|
||||||
|
fun getRoom(roomId: String): Room?
|
||||||
|
|
||||||
|
fun getAllRooms(): List<Room>
|
||||||
|
|
||||||
|
fun observeAllRooms(): LiveData<List<Room>>
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.session.room.Signed
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class Invite(
|
data class Invite(
|
||||||
@Json(name = "display_name") val displayName: String,
|
@Json(name = "display_name") val displayName: String,
|
||||||
@Json(name = "signed") val signed: Signed
|
@Json(name = "signed") val signed: Signed
|
||||||
|
|
||||||
)
|
)
|
@ -1,11 +1,13 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
||||||
enum class Membership {
|
enum class Membership {
|
||||||
|
|
||||||
@Json(name = "invite") INVITE,
|
@Json(name = "invite") INVITE,
|
||||||
@Json(name = "join") JOIN,
|
@Json(name = "join") JOIN,
|
||||||
@Json(name = "knock") KNOCK,
|
@Json(name = "knock") KNOCK,
|
||||||
@Json(name = "leave") LEAVE,
|
@Json(name = "leave") LEAVE,
|
||||||
@Json(name = "ban") BAN
|
@Json(name = "ban") BAN;
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
@ -19,13 +19,14 @@ data class PowerLevels(
|
|||||||
@Json(name = "state_default") val stateDefault: Int = 50,
|
@Json(name = "state_default") val stateDefault: Int = 50,
|
||||||
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the user power level of a dedicated user Id
|
* Returns the user power level of a dedicated user Id
|
||||||
*
|
*
|
||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return the power level
|
* @return the power level
|
||||||
*/
|
*/
|
||||||
fun getUserPowerLevel(userId: String): Int {
|
fun getUserPowerLevel(userId: String): Int {
|
||||||
// sanity check
|
// sanity check
|
||||||
if (!TextUtils.isEmpty(userId)) {
|
if (!TextUtils.isEmpty(userId)) {
|
||||||
val powerLevel = users[userId]
|
val powerLevel = users[userId]
|
||||||
@ -41,7 +42,7 @@ data class PowerLevels(
|
|||||||
* @param userId the user
|
* @param userId the user
|
||||||
* @param powerLevel the new power level
|
* @param powerLevel the new power level
|
||||||
*/
|
*/
|
||||||
fun setUserPowerLevel(userId: String?, powerLevel: Int) {
|
fun setUserPowerLevel(userId: String?, powerLevel: Int) {
|
||||||
if (null != userId) {
|
if (null != userId) {
|
||||||
users[userId] = Integer.valueOf(powerLevel)
|
users[userId] = Integer.valueOf(powerLevel)
|
||||||
}
|
}
|
||||||
@ -54,7 +55,7 @@ data class PowerLevels(
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return true if the user can send the event
|
* @return true if the user can send the event
|
||||||
*/
|
*/
|
||||||
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
||||||
return if (!TextUtils.isEmpty(eventTypeString) && !TextUtils.isEmpty(userId)) {
|
return if (!TextUtils.isEmpty(eventTypeString) && !TextUtils.isEmpty(userId)) {
|
||||||
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
||||||
} else false
|
} else false
|
||||||
@ -67,7 +68,7 @@ data class PowerLevels(
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return true if the user can send a room message
|
* @return true if the user can send a room message
|
||||||
*/
|
*/
|
||||||
fun maySendMessage(userId: String): Boolean {
|
fun maySendMessage(userId: String): Boolean {
|
||||||
return maySendEventOfType(EventType.MESSAGE, userId)
|
return maySendEventOfType(EventType.MESSAGE, userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ data class PowerLevels(
|
|||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
||||||
* @return the required minimum power level.
|
* @return the required minimum power level.
|
||||||
*/
|
*/
|
||||||
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
||||||
return events[eventTypeString] ?: eventsDefault
|
return events[eventTypeString] ?: eventsDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ data class PowerLevels(
|
|||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
||||||
* @return the required minimum power level.
|
* @return the required minimum power level.
|
||||||
*/
|
*/
|
||||||
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
||||||
return events[eventTypeString] ?: stateDefault
|
return events[eventTypeString] ?: stateDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ data class PowerLevels(
|
|||||||
* @param key the notification key
|
* @param key the notification key
|
||||||
* @return the level
|
* @return the level
|
||||||
*/
|
*/
|
||||||
fun notificationLevel(key: String?): Int {
|
fun notificationLevel(key: String?): Int {
|
||||||
if (null != key && notifications.containsKey(key)) {
|
if (null != key && notifications.containsKey(key)) {
|
||||||
val valAsVoid = notifications[key]
|
val valAsVoid = notifications[key]
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
@ -1,8 +1,8 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.UnsignedData
|
import im.vector.matrix.android.api.session.events.model.UnsignedData
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomMember(
|
data class RoomMember(
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.api.rooms
|
package im.vector.matrix.android.api.session.room
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
package im.vector.matrix.android.internal.database
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
|
import io.realm.RealmChangeListener
|
||||||
|
import io.realm.RealmModel
|
||||||
|
import io.realm.RealmResults
|
||||||
|
|
||||||
|
class RealmLiveData<T : RealmModel, U>(private val realmResults: RealmResults<T>,
|
||||||
|
private val mapper: (T) -> U) : LiveData<List<U>>() {
|
||||||
|
|
||||||
|
private val listener = RealmChangeListener<RealmResults<T>> { results ->
|
||||||
|
value = results.map { mapper.invoke(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActive() {
|
||||||
|
realmResults.addChangeListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInactive() {
|
||||||
|
realmResults.removeChangeListener(listener)
|
||||||
|
}
|
||||||
|
}
|
@ -3,21 +3,27 @@ package im.vector.matrix.android.internal.database
|
|||||||
import android.support.annotation.MainThread
|
import android.support.annotation.MainThread
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
class SessionRealmHolder(private val realmConfiguration: RealmConfiguration
|
class SessionRealmHolder(private val realmConfiguration: RealmConfiguration
|
||||||
) {
|
) {
|
||||||
|
|
||||||
lateinit var instance: Realm
|
lateinit var instance: Realm
|
||||||
|
private val isOpen = AtomicBoolean(false)
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
fun open() {
|
fun open() {
|
||||||
instance = Realm.getInstance(realmConfiguration)
|
if (isOpen.compareAndSet(false, true)) {
|
||||||
|
instance = Realm.getInstance(realmConfiguration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
fun close() {
|
fun close() {
|
||||||
instance.close()
|
if (isOpen.compareAndSet(true, false)) {
|
||||||
Realm.compactRealm(realmConfiguration)
|
instance.close()
|
||||||
|
Realm.compactRealm(realmConfiguration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package im.vector.matrix.android.internal.database.mapper
|
package im.vector.matrix.android.internal.database.mapper
|
||||||
|
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.UnsignedData
|
||||||
import im.vector.matrix.android.api.events.UnsignedData
|
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
|
|
||||||
object EventMapper {
|
object EventMapper {
|
||||||
|
@ -2,7 +2,7 @@ package im.vector.matrix.android.internal.database.query
|
|||||||
|
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmQuery
|
||||||
|
|
||||||
fun RoomEntity.Companion.getForId(realm: Realm, roomId: String): RoomEntity? {
|
fun RoomEntity.Companion.getForId(realm: Realm, roomId: String): RoomEntity? {
|
||||||
return realm.where<RoomEntity>(RoomEntity::class.java)
|
return realm.where<RoomEntity>(RoomEntity::class.java)
|
||||||
@ -10,10 +10,10 @@ fun RoomEntity.Companion.getForId(realm: Realm, roomId: String): RoomEntity? {
|
|||||||
.findFirst()
|
.findFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RoomEntity.Companion.getAllAsync(realm: Realm, membership: RoomEntity.Membership? = null): RealmResults<RoomEntity> {
|
fun RoomEntity.Companion.getAll(realm: Realm, membership: RoomEntity.Membership? = null): RealmQuery<RoomEntity> {
|
||||||
val query = realm.where(RoomEntity::class.java)
|
val query = realm.where(RoomEntity::class.java)
|
||||||
if (membership != null) {
|
if (membership != null) {
|
||||||
query.equalTo("membership", membership.name)
|
query.equalTo("membership", membership.name)
|
||||||
}
|
}
|
||||||
return query.findAllAsync()
|
return query
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ import im.vector.matrix.android.internal.legacy.rest.model.crypto.KeysUploadResp
|
|||||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyContent;
|
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyContent;
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyRequest;
|
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyRequest;
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyRequestBody;
|
import im.vector.matrix.android.internal.legacy.rest.model.crypto.RoomKeyRequestBody;
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.sync.SyncResponse;
|
|
||||||
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
import im.vector.matrix.android.internal.legacy.util.JsonUtils;
|
||||||
import im.vector.matrix.android.internal.legacy.util.Log;
|
import im.vector.matrix.android.internal.legacy.util.Log;
|
||||||
|
|
||||||
@ -600,7 +599,7 @@ public class MXCrypto {
|
|||||||
* @param fromToken the start sync token
|
* @param fromToken the start sync token
|
||||||
* @param isCatchingUp true if there is a catch-up in progress.
|
* @param isCatchingUp true if there is a catch-up in progress.
|
||||||
*/
|
*/
|
||||||
public void onSyncCompleted(final im.vector.matrix.android.internal.events.sync.data.SyncResponse syncResponse, final String fromToken, final boolean isCatchingUp) {
|
public void onSyncCompleted(final im.vector.matrix.android.internal.session.sync.model.SyncResponse syncResponse, final String fromToken, final boolean isCatchingUp) {
|
||||||
getEncryptingThreadHandler().post(new Runnable() {
|
getEncryptingThreadHandler().post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -430,7 +430,7 @@ public interface IMXStore {
|
|||||||
* @param roomId the room id
|
* @param roomId the room id
|
||||||
* @param event the event
|
* @param event the event
|
||||||
*/
|
*/
|
||||||
void storeRoomStateEvent(String roomId, im.vector.matrix.android.api.events.Event event);
|
void storeRoomStateEvent(String roomId, im.vector.matrix.android.api.session.events.model.Event event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the room state creation events
|
* Retrieve the room state creation events
|
||||||
@ -438,7 +438,7 @@ public interface IMXStore {
|
|||||||
* @param roomId the room id
|
* @param roomId the room id
|
||||||
* @param callback the asynchronous callback
|
* @param callback the asynchronous callback
|
||||||
*/
|
*/
|
||||||
void getRoomStateEvents(String roomId, ApiCallback<List<im.vector.matrix.android.api.events.Event>> callback);
|
void getRoomStateEvents(String roomId, ApiCallback<List<im.vector.matrix.android.api.session.events.model.Event>> callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the list of latest unsent events.
|
* Return the list of latest unsent events.
|
||||||
|
@ -1369,7 +1369,7 @@ public class MXFileStore extends MXMemoryStore {
|
|||||||
private Map<String, List<Event>> mPendingRoomStateEvents = new HashMap<>();
|
private Map<String, List<Event>> mPendingRoomStateEvents = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeRoomStateEvent(final String roomId, final im.vector.matrix.android.api.events.Event event) {
|
public void storeRoomStateEvent(final String roomId, final im.vector.matrix.android.api.session.events.model.Event event) {
|
||||||
/*boolean isAlreadyLoaded = true;
|
/*boolean isAlreadyLoaded = true;
|
||||||
|
|
||||||
synchronized (mRoomStateEventsByRoomId) {
|
synchronized (mRoomStateEventsByRoomId) {
|
||||||
@ -1477,7 +1477,7 @@ public class MXFileStore extends MXMemoryStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getRoomStateEvents(final String roomId, final ApiCallback<List<im.vector.matrix.android.api.events.Event>> callback) {
|
public void getRoomStateEvents(final String roomId, final ApiCallback<List<im.vector.matrix.android.api.session.events.model.Event>> callback) {
|
||||||
boolean isAlreadyLoaded = true;
|
boolean isAlreadyLoaded = true;
|
||||||
|
|
||||||
/*synchronized (mRoomStateEventsByRoomId) {
|
/*synchronized (mRoomStateEventsByRoomId) {
|
||||||
|
@ -871,7 +871,7 @@ public class MXMemoryStore implements IMXStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeRoomStateEvent(String roomId, im.vector.matrix.android.api.events.Event event) {
|
public void storeRoomStateEvent(String roomId, im.vector.matrix.android.api.session.events.model.Event event) {
|
||||||
/*synchronized (mRoomStateEventsByRoomId) {
|
/*synchronized (mRoomStateEventsByRoomId) {
|
||||||
Map<String, Event> events = mRoomStateEventsByRoomId.get(roomId);
|
Map<String, Event> events = mRoomStateEventsByRoomId.get(roomId);
|
||||||
|
|
||||||
@ -888,8 +888,8 @@ public class MXMemoryStore implements IMXStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getRoomStateEvents(final String roomId, final ApiCallback<List<im.vector.matrix.android.api.events.Event>> callback) {
|
public void getRoomStateEvents(final String roomId, final ApiCallback<List<im.vector.matrix.android.api.session.events.model.Event>> callback) {
|
||||||
final List<im.vector.matrix.android.api.events.Event> events = new ArrayList<>();
|
final List<im.vector.matrix.android.api.session.events.model.Event> events = new ArrayList<>();
|
||||||
|
|
||||||
/*synchronized (mRoomStateEventsByRoomId) {
|
/*synchronized (mRoomStateEventsByRoomId) {
|
||||||
if (mRoomStateEventsByRoomId.containsKey(roomId)) {
|
if (mRoomStateEventsByRoomId.containsKey(roomId)) {
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package im.vector.matrix.android.internal.session
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.support.annotation.MainThread
|
import android.support.annotation.MainThread
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
||||||
import im.vector.matrix.android.internal.di.SessionModule
|
import im.vector.matrix.android.internal.session.room.RoomSummaryObserver
|
||||||
import im.vector.matrix.android.internal.events.sync.SyncModule
|
import im.vector.matrix.android.internal.session.sync.SyncModule
|
||||||
import im.vector.matrix.android.internal.events.sync.job.SyncThread
|
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||||
import org.koin.core.scope.Scope
|
import org.koin.core.scope.Scope
|
||||||
import org.koin.standalone.KoinComponent
|
import org.koin.standalone.KoinComponent
|
||||||
import org.koin.standalone.StandAloneContext
|
import org.koin.standalone.StandAloneContext
|
||||||
@ -15,7 +18,8 @@ import org.koin.standalone.getKoin
|
|||||||
import org.koin.standalone.inject
|
import org.koin.standalone.inject
|
||||||
|
|
||||||
|
|
||||||
class DefaultSession(private val sessionParams: SessionParams) : Session, KoinComponent {
|
class DefaultSession(private val sessionParams: SessionParams
|
||||||
|
) : Session, KoinComponent, RoomService {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SCOPE: String = "session"
|
const val SCOPE: String = "session"
|
||||||
@ -25,6 +29,7 @@ class DefaultSession(private val sessionParams: SessionParams) : Session, KoinCo
|
|||||||
|
|
||||||
private val realmInstanceHolder by inject<SessionRealmHolder>()
|
private val realmInstanceHolder by inject<SessionRealmHolder>()
|
||||||
private val roomSummaryObserver by inject<RoomSummaryObserver>()
|
private val roomSummaryObserver by inject<RoomSummaryObserver>()
|
||||||
|
private val roomService by inject<RoomService>()
|
||||||
private val syncThread by inject<SyncThread>()
|
private val syncThread by inject<SyncThread>()
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
@ -63,6 +68,20 @@ class DefaultSession(private val sessionParams: SessionParams) : Session, KoinCo
|
|||||||
isOpen = false
|
isOpen = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ROOM SERVICE
|
||||||
|
|
||||||
|
override fun getRoom(roomId: String): Room? {
|
||||||
|
return roomService.getRoom(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllRooms(): List<Room> {
|
||||||
|
return roomService.getAllRooms()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun observeAllRooms(): LiveData<List<Room>> {
|
||||||
|
return roomService.observeAllRooms()
|
||||||
|
}
|
||||||
|
|
||||||
// Private methods *****************************************************************************
|
// Private methods *****************************************************************************
|
||||||
|
|
||||||
private fun checkIsMainThread() {
|
private fun checkIsMainThread() {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package im.vector.matrix.android.internal.di
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
||||||
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
||||||
import im.vector.matrix.android.internal.legacy.MXSession
|
import im.vector.matrix.android.internal.legacy.MXSession
|
||||||
import im.vector.matrix.android.internal.legacy.data.store.MXFileStore
|
import im.vector.matrix.android.internal.legacy.data.store.MXFileStore
|
||||||
import im.vector.matrix.android.internal.session.DefaultSession
|
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
||||||
import im.vector.matrix.android.internal.session.RoomSummaryObserver
|
import im.vector.matrix.android.internal.session.room.RoomSummaryObserver
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import org.koin.dsl.context.ModuleDefinition
|
import org.koin.dsl.context.ModuleDefinition
|
||||||
import org.koin.dsl.module.Module
|
import org.koin.dsl.module.Module
|
||||||
@ -36,6 +37,10 @@ class SessionModule(private val sessionParams: SessionParams) : Module {
|
|||||||
RoomSummaryObserver(get(), get(), get())
|
RoomSummaryObserver(get(), get(), get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
DefaultRoomService(get(), get()) as RoomService
|
||||||
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
val store = MXFileStore(sessionParams.credentials, false, get())
|
val store = MXFileStore(sessionParams.credentials, false, get())
|
||||||
val dataHandler = MXDataHandler(store, sessionParams.credentials)
|
val dataHandler = MXDataHandler(store, sessionParams.credentials)
|
@ -0,0 +1,7 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
|
|
||||||
|
data class DefaultRoom(
|
||||||
|
override val roomId: String
|
||||||
|
) : Room
|
@ -0,0 +1,38 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
|
import im.vector.matrix.android.internal.database.RealmLiveData
|
||||||
|
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
||||||
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.getAll
|
||||||
|
import im.vector.matrix.android.internal.database.query.getForId
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
|
|
||||||
|
class DefaultRoomService(private val realmConfiguration: RealmConfiguration,
|
||||||
|
val mainThreadRealm: SessionRealmHolder)
|
||||||
|
: RoomService {
|
||||||
|
|
||||||
|
override fun getAllRooms(): List<Room> {
|
||||||
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
|
val rooms = RoomEntity.getAll(realm).findAll().map { DefaultRoom(it.roomId) }
|
||||||
|
realm.close()
|
||||||
|
return rooms
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRoom(roomId: String): Room? {
|
||||||
|
val realm = Realm.getInstance(realmConfiguration)
|
||||||
|
val room = RoomEntity.getForId(realm, roomId)?.let { DefaultRoom(it.roomId) }
|
||||||
|
realm.close()
|
||||||
|
return room
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun observeAllRooms(): LiveData<List<Room>> {
|
||||||
|
val roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync()
|
||||||
|
return RealmLiveData(roomResults) { DefaultRoom(it.roomId) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
package im.vector.matrix.android.internal.session
|
package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import im.vector.matrix.android.api.events.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.rooms.RoomNameContent
|
import im.vector.matrix.android.api.session.room.model.RoomNameContent
|
||||||
import im.vector.matrix.android.api.rooms.RoomTopicContent
|
import im.vector.matrix.android.api.session.room.model.RoomTopicContent
|
||||||
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
import im.vector.matrix.android.internal.database.SessionRealmHolder
|
||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.query.getAllAsync
|
import im.vector.matrix.android.internal.database.query.getAll
|
||||||
import im.vector.matrix.android.internal.database.query.getAllFromRoom
|
import im.vector.matrix.android.internal.database.query.getAllFromRoom
|
||||||
import im.vector.matrix.android.internal.database.query.getLast
|
import im.vector.matrix.android.internal.database.query.getLast
|
||||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
@ -29,7 +29,7 @@ internal class RoomSummaryObserver(private val mainThreadRealm: SessionRealmHold
|
|||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
if (isStarted.compareAndSet(false, true)) {
|
if (isStarted.compareAndSet(false, true)) {
|
||||||
roomResults = RoomEntity.getAllAsync(mainThreadRealm.instance)
|
roomResults = RoomEntity.getAll(mainThreadRealm.instance).findAllAsync()
|
||||||
roomResults.addChangeListener { rooms, changeSet ->
|
roomResults.addChangeListener { rooms, changeSet ->
|
||||||
manageRoomResults(rooms, changeSet.changes)
|
manageRoomResults(rooms, changeSet.changes)
|
||||||
manageRoomResults(rooms, changeSet.insertions)
|
manageRoomResults(rooms, changeSet.insertions)
|
@ -1,14 +1,14 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.internal.database.mapper.asEntity
|
import im.vector.matrix.android.internal.database.mapper.asEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||||
import im.vector.matrix.android.internal.database.query.getChunkIncludingEvents
|
import im.vector.matrix.android.internal.database.query.getChunkIncludingEvents
|
||||||
import im.vector.matrix.android.internal.database.query.getForId
|
import im.vector.matrix.android.internal.database.query.getForId
|
||||||
import im.vector.matrix.android.internal.database.query.getLastChunkFromRoom
|
import im.vector.matrix.android.internal.database.query.getLastChunkFromRoom
|
||||||
import im.vector.matrix.android.internal.events.sync.data.InvitedRoomSync
|
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
|
||||||
import im.vector.matrix.android.internal.events.sync.data.RoomSync
|
import im.vector.matrix.android.internal.session.sync.model.RoomSync
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.network.NetworkConstants
|
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
@ -1,6 +1,6 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.events.sync.job.SyncThread
|
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||||
import im.vector.matrix.android.internal.session.DefaultSession
|
import im.vector.matrix.android.internal.session.DefaultSession
|
||||||
import org.koin.dsl.context.ModuleDefinition
|
import org.koin.dsl.context.ModuleDefinition
|
||||||
import org.koin.dsl.module.Module
|
import org.koin.dsl.module.Module
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import arrow.core.Either
|
import arrow.core.Either
|
||||||
import arrow.core.flatMap
|
import arrow.core.flatMap
|
||||||
@ -6,7 +6,7 @@ import arrow.core.leftIfNull
|
|||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody
|
import im.vector.matrix.android.internal.legacy.rest.model.filter.FilterBody
|
||||||
import im.vector.matrix.android.internal.legacy.util.FilterUtil
|
import im.vector.matrix.android.internal.legacy.util.FilterUtil
|
||||||
import im.vector.matrix.android.internal.network.executeRequest
|
import im.vector.matrix.android.internal.network.executeRequest
|
@ -1,8 +1,8 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
import im.vector.matrix.android.internal.legacy.MXDataHandler
|
||||||
import im.vector.matrix.android.internal.legacy.data.Room
|
import im.vector.matrix.android.internal.legacy.data.Room
|
||||||
import im.vector.matrix.android.internal.legacy.data.store.IMXStore
|
import im.vector.matrix.android.internal.legacy.data.store.IMXStore
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.database.model.SyncEntity
|
import im.vector.matrix.android.internal.database.model.SyncEntity
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
@ -1,11 +1,11 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.job
|
package im.vector.matrix.android.internal.session.sync.job
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.failure.Failure
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import im.vector.matrix.android.internal.events.sync.SyncRequest
|
import im.vector.matrix.android.internal.session.sync.SyncRequest
|
||||||
import im.vector.matrix.android.internal.events.sync.SyncTokenStore
|
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||||
import im.vector.matrix.android.internal.events.sync.data.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
import im.vector.matrix.android.internal.network.NetworkConnectivityChecker
|
||||||
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
@ -15,7 +15,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,7 +1,7 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// PresenceSyncResponse represents the updates to the presence status of other users during server sync v2.
|
// PresenceSyncResponse represents the updates to the presence status of other users during server sync v2.
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -13,12 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// RoomInviteState represents the state of a room that the user has been invited to.
|
// RoomInviteState represents the state of a room that the user has been invited to.
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -1,8 +1,8 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing a room from a JSON response from room or global initial sync.
|
* Class representing a room from a JSON response from room or global initial sync.
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,8 +1,8 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomSyncAccountData(
|
data class RoomSyncAccountData(
|
@ -1,9 +1,9 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// RoomSyncEphemeral represents the ephemeral events in the room that aren't recorded in the timeline or state of the room (e.g. typing).
|
// RoomSyncEphemeral represents the ephemeral events in the room that aren't recorded in the timeline or state of the room (e.g. typing).
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -1,9 +1,9 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// RoomSyncState represents the state updates for a room during server sync v2.
|
// RoomSyncState represents the state updates for a room during server sync v2.
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -1,9 +1,9 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// RoomSyncTimeline represents the timeline of messages and state changes for a room during server sync v2.
|
// RoomSyncTimeline represents the timeline of messages and state changes for a room during server sync v2.
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -1,9 +1,9 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `MXRoomSyncUnreadNotifications` represents the unread counts for a room.
|
* `MXRoomSyncUnreadNotifications` represents the unread counts for a room.
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
@ -1,8 +1,8 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.events.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
// ToDeviceSyncResponse represents the data directly sent to one of user's devices.
|
// ToDeviceSyncResponse represents the data directly sent to one of user's devices.
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
@ -1,4 +1,4 @@
|
|||||||
package im.vector.matrix.android.internal.events.sync.data
|
package im.vector.matrix.android.internal.session.sync.model
|
||||||
|
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
Loading…
Reference in New Issue
Block a user