mirror of
https://github.com/ouchadam/small-talk.git
synced 2025-02-01 20:16:44 +01:00
adding room join/leaving based on sync status
- means the invitations page should work!
This commit is contained in:
parent
271727dda7
commit
f0a856eb20
@ -29,6 +29,18 @@ internal class OverviewPersistence(
|
||||
.map { it.map { json.decodeFromString(RoomOverview.serializer(), it.blob) } }
|
||||
}
|
||||
|
||||
override suspend fun removeRooms(roomsToRemove: List<RoomId>) {
|
||||
dispatchers.withIoContext {
|
||||
database.transaction {
|
||||
roomsToRemove.forEach {
|
||||
database.inviteStateQueries.remove(it.value)
|
||||
database.overviewStateQueries.remove(it.value)
|
||||
database.roomEventQueries.remove(it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun persistInvites(invites: List<RoomInvite>) {
|
||||
dispatchers.withIoContext {
|
||||
database.inviteStateQueries.transaction {
|
||||
@ -46,6 +58,14 @@ internal class OverviewPersistence(
|
||||
.map { it.map { json.decodeFromString(RoomInvite.serializer(), it.blob) } }
|
||||
}
|
||||
|
||||
override suspend fun removeInvites(invites: List<RoomId>) {
|
||||
dispatchers.withIoContext {
|
||||
database.inviteStateQueries.transaction {
|
||||
invites.forEach { database.inviteStateQueries.remove(it.value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun persist(overviewState: OverviewState) {
|
||||
dispatchers.withIoContext {
|
||||
database.transaction {
|
||||
|
@ -10,4 +10,8 @@ FROM dbInviteState;
|
||||
|
||||
insert:
|
||||
INSERT OR REPLACE INTO dbInviteState(room_id, blob)
|
||||
VALUES (?, ?);
|
||||
VALUES (?, ?);
|
||||
|
||||
remove:
|
||||
DELETE FROM dbInviteState
|
||||
WHERE room_id = ?;
|
@ -18,4 +18,8 @@ WHERE room_id = ?;
|
||||
|
||||
insert:
|
||||
INSERT OR REPLACE INTO dbOverviewState(room_id, latest_activity_timestamp_utc, read_marker, blob)
|
||||
VALUES (?, ?, ?, ?);
|
||||
VALUES (?, ?, ?, ?);
|
||||
|
||||
remove:
|
||||
DELETE FROM dbOverviewState
|
||||
WHERE room_id = ?;
|
@ -33,3 +33,7 @@ FROM dbUnreadEvent
|
||||
INNER JOIN dbRoomEvent ON dbUnreadEvent.event_id = dbRoomEvent.event_id
|
||||
ORDER BY dbRoomEvent.timestamp_utc DESC
|
||||
LIMIT 100;
|
||||
|
||||
remove:
|
||||
DELETE FROM dbRoomEvent
|
||||
WHERE room_id = ?;
|
@ -32,7 +32,8 @@ class NotificationsUseCase(
|
||||
val asRooms = changes.keys
|
||||
val removedRooms = inferredCurrentNotifications.keys - asRooms
|
||||
|
||||
val onlyContainsRemovals = inferredCurrentNotifications.filterKeys { !removedRooms.contains(it) } == changes.filterKeys { !removedRooms.contains(it) }
|
||||
val onlyContainsRemovals =
|
||||
inferredCurrentNotifications.filterKeys { !removedRooms.contains(it) } == changes.filterKeys { !removedRooms.contains(it) }
|
||||
inferredCurrentNotifications.clear()
|
||||
inferredCurrentNotifications.putAll(changes)
|
||||
|
||||
|
@ -28,8 +28,10 @@ class PushAndroidService : FirebaseMessagingService() {
|
||||
}
|
||||
|
||||
override fun onNewToken(token: String) {
|
||||
log(PUSH, "new push token received")
|
||||
GlobalScope.launch {
|
||||
module.pushUseCase().registerPush(token)
|
||||
log(PUSH, "token registered")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,15 +79,15 @@ class ProfileViewModel(
|
||||
}
|
||||
|
||||
fun acceptRoomInvite(roomId: RoomId) {
|
||||
viewModelScope.launch {
|
||||
roomService.joinRoom(roomId)
|
||||
}
|
||||
launchCatching { roomService.joinRoom(roomId) }.fold(
|
||||
onError = {}
|
||||
)
|
||||
}
|
||||
|
||||
fun rejectRoomInvite(roomId: RoomId) {
|
||||
viewModelScope.launch {
|
||||
roomService.rejectJoinRoom(roomId)
|
||||
}
|
||||
launchCatching { roomService.rejectJoinRoom(roomId) }.fold(
|
||||
onError = {}
|
||||
)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
@ -103,3 +103,15 @@ class ProfileViewModel(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun <S, VE, T> DapkViewModel<S, VE>.launchCatching(block: suspend () -> T): LaunchCatching<T> {
|
||||
return object : LaunchCatching<T> {
|
||||
override fun fold(onSuccess: (T) -> Unit, onError: (Throwable) -> Unit) {
|
||||
viewModelScope.launch { runCatching { block() }.fold(onSuccess, onError) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface LaunchCatching<T> {
|
||||
fun fold(onSuccess: (T) -> Unit = {}, onError: (Throwable) -> Unit = {})
|
||||
}
|
@ -28,6 +28,7 @@ interface FilterStore {
|
||||
|
||||
interface OverviewStore {
|
||||
|
||||
suspend fun removeRooms(roomsToRemove: List<RoomId>)
|
||||
suspend fun persistInvites(invite: List<RoomInvite>)
|
||||
suspend fun persist(overviewState: OverviewState)
|
||||
|
||||
@ -35,6 +36,7 @@ interface OverviewStore {
|
||||
|
||||
fun latest(): Flow<OverviewState>
|
||||
fun latestInvites(): Flow<List<RoomInvite>>
|
||||
suspend fun removeInvites(map: List<RoomId>)
|
||||
}
|
||||
|
||||
interface SyncStore {
|
||||
|
@ -214,6 +214,7 @@ sealed class ApiToDeviceEvent {
|
||||
internal data class ApiSyncRooms(
|
||||
@SerialName("join") val join: Map<RoomId, ApiSyncRoom>? = null,
|
||||
@SerialName("invite") val invite: Map<RoomId, ApiSyncRoomInvite>? = null,
|
||||
@SerialName("leave") val leave: Map<RoomId, ApiSyncRoom>? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
@ -20,13 +20,16 @@ internal class SyncReducer(
|
||||
|
||||
data class ReducerResult(
|
||||
val roomState: List<RoomState>,
|
||||
val invites: List<RoomInvite>
|
||||
val invites: List<RoomInvite>,
|
||||
val roomsLeft: List<RoomId>
|
||||
)
|
||||
|
||||
suspend fun reduce(isInitialSync: Boolean, sideEffects: SideEffectResult, response: ApiSyncResponse, userCredentials: UserCredentials): ReducerResult {
|
||||
val directMessages = response.directMessages()
|
||||
|
||||
val invites = response.rooms?.invite?.map { roomInvite(it, userCredentials) } ?: emptyList()
|
||||
val roomsLeft = findRoomsLeft(response, userCredentials)
|
||||
|
||||
val apiUpdatedRooms = response.rooms?.join?.keepRoomsWithChanges()
|
||||
val apiRoomsToProcess = apiUpdatedRooms?.map { (roomId, apiRoom) ->
|
||||
logger.matrixLog(SYNC, "reducing: $roomId")
|
||||
@ -49,9 +52,15 @@ internal class SyncReducer(
|
||||
}
|
||||
}
|
||||
|
||||
return ReducerResult((apiRoomsToProcess + roomsWithSideEffects).awaitAll().filterNotNull(), invites)
|
||||
return ReducerResult((apiRoomsToProcess + roomsWithSideEffects).awaitAll().filterNotNull(), invites, roomsLeft)
|
||||
}
|
||||
|
||||
private fun findRoomsLeft(response: ApiSyncResponse, userCredentials: UserCredentials) = response.rooms?.leave?.filter {
|
||||
it.value.state.stateEvents.filterIsInstance<ApiTimelineEvent.RoomMember>().any {
|
||||
it.content.membership.isLeave() && it.senderId == userCredentials.userId
|
||||
}
|
||||
}?.map { it.key } ?: emptyList()
|
||||
|
||||
private fun roomInvite(entry: Map.Entry<RoomId, ApiSyncRoomInvite>, userCredentials: UserCredentials): RoomInvite {
|
||||
val memberEvents = entry.value.state.events.filterIsInstance<ApiStrippedEvent.RoomMember>()
|
||||
val invitee = memberEvents.first { it.content.membership?.isInvite() ?: false }
|
||||
|
@ -46,13 +46,23 @@ internal class SyncUseCase(
|
||||
val nextState = logger.logP("reducing") { syncReducer.reduce(isInitialSync, sideEffects, response, credentials) }
|
||||
val overview = nextState.roomState.map { it.roomOverview }
|
||||
|
||||
if (nextState.roomsLeft.isNotEmpty()) {
|
||||
persistence.removeRooms(nextState.roomsLeft)
|
||||
}
|
||||
if (nextState.invites.isNotEmpty()) {
|
||||
persistence.persistInvites(nextState.invites)
|
||||
}
|
||||
|
||||
|
||||
when {
|
||||
previousState == overview -> previousState.also { logger.matrixLog(SYNC, "no changes, not persisting new state") }
|
||||
overview.isNotEmpty() -> overview.also { persistence.persist(overview) }
|
||||
overview.isNotEmpty() -> overview.also {
|
||||
val newRooms = overview - (previousState ?: emptyList()).toSet()
|
||||
if (newRooms.isNotEmpty()) {
|
||||
persistence.removeInvites(newRooms.map { it.roomId })
|
||||
}
|
||||
persistence.persist(overview)
|
||||
}
|
||||
else -> previousState.also { logger.matrixLog(SYNC, "nothing to do") }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user