Merge pull request #1049 from vector-im/feature/fix_invites
Feature/fix invites
This commit is contained in:
commit
68400cce03
|
@ -19,6 +19,7 @@ Bugfix 🐛:
|
|||
- Fix rotation of full-size image (#647)
|
||||
- Fix joining rooms from directory via federation isn't working. (#808)
|
||||
- Leaving a room creates a stuck "leaving room" loading screen. (#1041)
|
||||
- Fix some invitation handling issues (#1013)
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.UUID
|
|||
|
||||
object LocalEcho {
|
||||
|
||||
private const val PREFIX = "local."
|
||||
private const val PREFIX = "\$local."
|
||||
|
||||
fun isLocalEchoId(eventId: String) = eventId.startsWith(PREFIX)
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ data class RoomSummary constructor(
|
|||
val versioningState: VersioningState = VersioningState.NONE,
|
||||
val readMarkerId: String? = null,
|
||||
val userDrafts: List<UserDraft> = emptyList(),
|
||||
var isEncrypted: Boolean,
|
||||
val isEncrypted: Boolean,
|
||||
val inviterId: String? = null,
|
||||
val typingRoomMemberIds: List<String> = emptyList(),
|
||||
val breadcrumbsIndex: Int = NOT_IN_BREADCRUMBS,
|
||||
// TODO Plug it
|
||||
|
|
|
@ -32,7 +32,8 @@ internal object EventMapper {
|
|||
val uds = if (event.unsignedData == null) null
|
||||
else MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(event.unsignedData)
|
||||
val eventEntity = EventEntity()
|
||||
eventEntity.eventId = event.eventId ?: ""
|
||||
// TODO change this as we shouldn't use event everywhere
|
||||
eventEntity.eventId = event.eventId ?: "$$roomId-${System.currentTimeMillis()}-${event.hashCode()}"
|
||||
eventEntity.roomId = event.roomId ?: roomId
|
||||
eventEntity.content = ContentMapper.map(event.content)
|
||||
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent
|
||||
|
|
|
@ -77,7 +77,8 @@ internal class RoomSummaryMapper @Inject constructor(
|
|||
isEncrypted = roomSummaryEntity.isEncrypted,
|
||||
typingRoomMemberIds = roomSummaryEntity.typingUserIds.toList(),
|
||||
breadcrumbsIndex = roomSummaryEntity.breadcrumbsIndex,
|
||||
roomEncryptionTrustLevel = roomSummaryEntity.roomEncryptionTrustLevel
|
||||
roomEncryptionTrustLevel = roomSummaryEntity.roomEncryptionTrustLevel,
|
||||
inviterId = roomSummaryEntity.inviterId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,8 @@ import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResu
|
|||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.Index
|
||||
import io.realm.annotations.PrimaryKey
|
||||
|
||||
internal open class EventEntity(@PrimaryKey var eventId: String = "",
|
||||
internal open class EventEntity(@Index var eventId: String = "",
|
||||
@Index var roomId: String = "",
|
||||
@Index var type: String = "",
|
||||
var content: String? = null,
|
||||
|
|
|
@ -49,7 +49,8 @@ internal open class RoomSummaryEntity(
|
|||
var flatAliases: String = "",
|
||||
var isEncrypted: Boolean = false,
|
||||
var typingUserIds: RealmList<String> = RealmList(),
|
||||
var roomEncryptionTrustLevelStr: String? = null
|
||||
var roomEncryptionTrustLevelStr: String? = null,
|
||||
var inviterId: String? = null
|
||||
) : RealmObject() {
|
||||
|
||||
private var membershipStr: String = Membership.NONE.name
|
||||
|
|
|
@ -23,6 +23,13 @@ import io.realm.RealmList
|
|||
import io.realm.RealmQuery
|
||||
import io.realm.kotlin.where
|
||||
|
||||
internal fun EventEntity.copyToRealmOrIgnore(realm: Realm): EventEntity {
|
||||
return realm.where<EventEntity>()
|
||||
.equalTo(EventEntityFields.EVENT_ID, eventId)
|
||||
.equalTo(EventEntityFields.ROOM_ID, roomId)
|
||||
.findFirst() ?: realm.copyToRealm(this)
|
||||
}
|
||||
|
||||
internal fun EventEntity.Companion.where(realm: Realm, eventId: String): RealmQuery<EventEntity> {
|
||||
return realm.where<EventEntity>()
|
||||
.equalTo(EventEntityFields.EVENT_ID, eventId)
|
||||
|
|
|
@ -81,7 +81,8 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
roomSummary: RoomSyncSummary? = null,
|
||||
unreadNotifications: RoomSyncUnreadNotifications? = null,
|
||||
updateMembers: Boolean = false,
|
||||
ephemeralResult: RoomSyncHandler.EphemeralResult? = null) {
|
||||
ephemeralResult: RoomSyncHandler.EphemeralResult? = null,
|
||||
inviterId: String? = null) {
|
||||
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
|
||||
if (roomSummary != null) {
|
||||
if (roomSummary.heroes.isNotEmpty()) {
|
||||
|
@ -134,6 +135,12 @@ internal class RoomSummaryUpdater @Inject constructor(
|
|||
roomSummaryEntity.typingUserIds.clear()
|
||||
roomSummaryEntity.typingUserIds.addAll(ephemeralResult?.typingUserIds.orEmpty())
|
||||
|
||||
if (roomSummaryEntity.membership == Membership.INVITE && inviterId != null) {
|
||||
roomSummaryEntity.inviterId = inviterId
|
||||
} else if (roomSummaryEntity.membership != Membership.INVITE) {
|
||||
roomSummaryEntity.inviterId = null
|
||||
}
|
||||
|
||||
if (updateMembers) {
|
||||
val otherRoomMembers = RoomMemberHelper(realm, roomId)
|
||||
.queryRoomMembersEvent()
|
||||
|
|
|
@ -22,6 +22,7 @@ import im.vector.matrix.android.api.session.room.send.SendState
|
|||
import im.vector.matrix.android.internal.database.mapper.toEntity
|
||||
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.query.copyToRealmOrIgnore
|
||||
import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||
import im.vector.matrix.android.internal.database.query.where
|
||||
import im.vector.matrix.android.internal.network.executeRequest
|
||||
|
@ -73,9 +74,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
|
|||
if (roomMemberEvent.eventId == null || roomMemberEvent.stateKey == null) {
|
||||
continue
|
||||
}
|
||||
val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
val eventEntity = roomMemberEvent.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, roomMemberEvent.stateKey, roomMemberEvent.type).apply {
|
||||
eventId = roomMemberEvent.eventId
|
||||
root = eventEntity
|
||||
|
|
|
@ -31,6 +31,7 @@ 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.RoomSummaryEntity
|
||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||
import im.vector.matrix.android.internal.database.query.copyToRealmOrIgnore
|
||||
import im.vector.matrix.android.internal.database.query.create
|
||||
import im.vector.matrix.android.internal.database.query.find
|
||||
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
|
||||
|
@ -199,9 +200,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||
val stateEvents = receivedChunk.stateEvents
|
||||
|
||||
for (stateEvent in stateEvents) {
|
||||
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
currentChunk.addStateEvent(roomId, stateEventEntity, direction)
|
||||
if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null) {
|
||||
roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel<RoomMemberContent>()
|
||||
|
@ -213,9 +212,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||
continue
|
||||
}
|
||||
eventIds.add(event.eventId)
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null) {
|
||||
val contentToUse = if (direction == PaginationDirection.BACKWARDS) {
|
||||
event.prevContent
|
||||
|
|
|
@ -32,6 +32,7 @@ import im.vector.matrix.android.internal.database.mapper.toEntity
|
|||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
|
||||
import im.vector.matrix.android.internal.database.model.RoomEntity
|
||||
import im.vector.matrix.android.internal.database.query.copyToRealmOrIgnore
|
||||
import im.vector.matrix.android.internal.database.query.find
|
||||
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
|
||||
import im.vector.matrix.android.internal.database.query.getOrCreate
|
||||
|
@ -93,7 +94,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
|||
}
|
||||
is HandlingStrategy.INVITED ->
|
||||
handlingStrategy.data.mapWithProgress(reporter, R.string.initial_sync_start_importing_account_invited_rooms, 0.1f) {
|
||||
handleInvitedRoom(realm, it.key, it.value, syncLocalTimeStampMillis)
|
||||
handleInvitedRoom(realm, it.key, it.value)
|
||||
}
|
||||
|
||||
is HandlingStrategy.LEFT -> {
|
||||
|
@ -134,9 +135,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
|||
if (event.eventId == null || event.stateKey == null) {
|
||||
continue
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply {
|
||||
eventId = event.eventId
|
||||
root = eventEntity
|
||||
|
@ -177,19 +176,27 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
|||
|
||||
private fun handleInvitedRoom(realm: Realm,
|
||||
roomId: String,
|
||||
roomSync: InvitedRoomSync,
|
||||
syncLocalTimestampMillis: Long): RoomEntity {
|
||||
roomSync: InvitedRoomSync): RoomEntity {
|
||||
Timber.v("Handle invited sync for room $roomId")
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||
roomEntity.membership = Membership.INVITE
|
||||
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
|
||||
val chunkEntity = handleTimelineEvents(realm, roomId, roomEntity, roomSync.inviteState.events, syncLocalTimestampMillis = syncLocalTimestampMillis)
|
||||
roomEntity.addOrUpdate(chunkEntity)
|
||||
roomSync.inviteState.events.forEach {
|
||||
if (it.stateKey == null) {
|
||||
return@forEach
|
||||
}
|
||||
val eventEntity = it.toEntity(roomId, SendState.SYNCED).copyToRealmOrIgnore(realm)
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, it.stateKey, it.type).apply {
|
||||
eventId = eventEntity.eventId
|
||||
root = eventEntity
|
||||
}
|
||||
roomMemberEventHandler.handle(realm, roomId, it)
|
||||
}
|
||||
}
|
||||
val hasRoomMember = roomSync.inviteState?.events?.firstOrNull {
|
||||
val inviterEvent = roomSync.inviteState?.events?.lastOrNull {
|
||||
it.type == EventType.STATE_ROOM_MEMBER
|
||||
} != null
|
||||
roomSummaryUpdater.update(realm, roomId, Membership.INVITE, updateMembers = hasRoomMember)
|
||||
}
|
||||
roomSummaryUpdater.update(realm, roomId, Membership.INVITE, updateMembers = true, inviterId = inviterEvent?.senderId)
|
||||
return roomEntity
|
||||
}
|
||||
|
||||
|
@ -197,7 +204,6 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
|||
roomId: String,
|
||||
roomSync: RoomSync): RoomEntity {
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId)
|
||||
|
||||
roomEntity.membership = Membership.LEAVE
|
||||
roomEntity.chunks.deleteAllFromRealm()
|
||||
roomSummaryUpdater.update(realm, roomId, Membership.LEAVE, roomSync.summary, roomSync.unreadNotifications)
|
||||
|
@ -229,9 +235,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
|
|||
}
|
||||
eventIds.add(event.eventId)
|
||||
val ageLocalTs = event.unsignedData?.age?.let { syncLocalTimestampMillis - it }
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED, ageLocalTs).let {
|
||||
realm.copyToRealmOrUpdate(it)
|
||||
}
|
||||
val eventEntity = event.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm)
|
||||
if (event.isStateEvent() && event.stateKey != null) {
|
||||
CurrentStateEventEntity.getOrCreate(realm, roomId, event.stateKey, event.type).apply {
|
||||
eventId = event.eventId
|
||||
|
|
|
@ -950,8 +950,8 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||
private fun observeSummaryState() {
|
||||
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
|
||||
if (summary.membership == Membership.INVITE) {
|
||||
summary.latestPreviewableEvent?.root?.senderId?.let { senderId ->
|
||||
session.getUser(senderId)
|
||||
summary.inviterId?.let { inviterId ->
|
||||
session.getUser(inviterId)
|
||||
}?.also {
|
||||
setState { copy(asyncInviter = Success(it)) }
|
||||
}
|
||||
|
|
|
@ -101,7 +101,18 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
|||
.observeOn(Schedulers.computation())
|
||||
.map { buildRoomSummaries(it) }
|
||||
.execute { async ->
|
||||
copy(asyncFilteredRooms = async)
|
||||
val invitedRooms = async()?.get(RoomCategory.INVITE)?.map { it.roomId }.orEmpty()
|
||||
val remainingJoining = joiningRoomsIds.intersect(invitedRooms)
|
||||
val remainingJoinErrors = joiningErrorRoomsIds.intersect(invitedRooms)
|
||||
val remainingRejecting = rejectingRoomsIds.intersect(invitedRooms)
|
||||
val remainingRejectErrors = rejectingErrorRoomsIds.intersect(invitedRooms)
|
||||
copy(
|
||||
asyncFilteredRooms = async,
|
||||
joiningRoomsIds = remainingJoining,
|
||||
joiningErrorRoomsIds = remainingJoinErrors,
|
||||
rejectingRoomsIds = remainingRejecting,
|
||||
rejectingErrorRoomsIds = remainingRejectErrors
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +240,6 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
|||
else -> groupRooms.add(room)
|
||||
}
|
||||
}
|
||||
|
||||
return RoomSummaries().apply {
|
||||
put(RoomCategory.INVITE, invites)
|
||||
put(RoomCategory.FAVOURITE, favourites)
|
||||
|
|
|
@ -60,9 +60,9 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
|||
rejectingErrorRoomsIds: Set<String>,
|
||||
listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> {
|
||||
val secondLine = if (roomSummary.isDirect) {
|
||||
roomSummary.latestPreviewableEvent?.root?.senderId
|
||||
roomSummary.inviterId
|
||||
} else {
|
||||
roomSummary.latestPreviewableEvent?.root?.senderId?.let {
|
||||
roomSummary.inviterId?.let {
|
||||
stringProvider.getString(R.string.invited_by, it)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,20 +51,20 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
|
|||
fun resolveEvent(event: Event/*, roomState: RoomState?, bingRule: PushRule?*/, session: Session): NotifiableEvent? {
|
||||
val roomID = event.roomId ?: return null
|
||||
val eventId = event.eventId ?: return null
|
||||
if (event.getClearType() == EventType.STATE_ROOM_MEMBER) {
|
||||
return resolveStateRoomEvent(event, session)
|
||||
}
|
||||
val timelineEvent = session.getRoom(roomID)?.getTimeLineEvent(eventId) ?: return null
|
||||
when (event.getClearType()) {
|
||||
EventType.MESSAGE -> {
|
||||
EventType.MESSAGE -> {
|
||||
return resolveMessageEvent(timelineEvent, session)
|
||||
}
|
||||
EventType.ENCRYPTED -> {
|
||||
EventType.ENCRYPTED -> {
|
||||
val messageEvent = resolveMessageEvent(timelineEvent, session)
|
||||
messageEvent?.lockScreenVisibility = NotificationCompat.VISIBILITY_PRIVATE
|
||||
return messageEvent
|
||||
}
|
||||
EventType.STATE_ROOM_MEMBER -> {
|
||||
return resolveStateRoomEvent(event, session)
|
||||
}
|
||||
else -> {
|
||||
else -> {
|
||||
// If the event can be displayed, display it as is
|
||||
Timber.w("NotifiableEventResolver Received an unsupported event matching a bing rule")
|
||||
// TODO Better event text display
|
||||
|
|
|
@ -130,9 +130,9 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||
|
||||
fun onEventRedacted(eventId: String) {
|
||||
synchronized(eventList) {
|
||||
eventList.filter { it.eventId == eventId }.map { notifiableEvent ->
|
||||
notifiableEvent.isRedacted = true
|
||||
notifiableEvent.hasBeenDisplayed = false
|
||||
eventList.find { it.eventId == eventId }?.apply {
|
||||
isRedacted = true
|
||||
hasBeenDisplayed = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +182,6 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||
e is InviteNotifiableEvent && e.roomId == roomId
|
||||
}
|
||||
}
|
||||
|
||||
notificationUtils.cancelNotificationMessage(roomId, ROOM_INVITATION_NOTIFICATION_ID)
|
||||
}
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
|||
val joinIntent = Intent(context, NotificationBroadcastReceiver::class.java)
|
||||
joinIntent.action = JOIN_ACTION
|
||||
joinIntent.data = Uri.parse("foobar://$roomId&$matrixId")
|
||||
rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
|
||||
joinIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId)
|
||||
val joinIntentPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), joinIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
addAction(
|
||||
|
|
Loading…
Reference in New Issue