diff --git a/src/components/LeftSidebar/LeftSidebar.spec.js b/src/components/LeftSidebar/LeftSidebar.spec.js index deb2047d61a..511e720eee2 100644 --- a/src/components/LeftSidebar/LeftSidebar.spec.js +++ b/src/components/LeftSidebar/LeftSidebar.spec.js @@ -76,7 +76,7 @@ describe('LeftSidebar.vue', () => { // note: need a copy because the Vue modifies it when sorting conversationsListMock = jest.fn() - fetchConversationsAction = jest.fn() + fetchConversationsAction = jest.fn().mockReturnValue({ headers: {} }) addConversationAction = jest.fn() createOneToOneConversationAction = jest.fn() const getUserIdMock = jest.fn().mockReturnValue('current-user') @@ -131,7 +131,7 @@ describe('LeftSidebar.vue', () => { const wrapper = mountComponent() - expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), undefined) + expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), expect.anything()) expect(conversationsListMock).toHaveBeenCalled() const appNavEl = wrapper.findComponent({ name: 'NcAppNavigation' }) @@ -194,7 +194,7 @@ describe('LeftSidebar.vue', () => { expect(fetchConversationsAction).not.toHaveBeenCalled() - EventBus.$emit('should-refresh-conversations') + EventBus.$emit('should-refresh-conversations', {}) // note: debounce was short-circuited so no delay needed expect(fetchConversationsAction).toHaveBeenCalled() @@ -313,7 +313,7 @@ describe('LeftSidebar.vue', () => { const wrapper = mountComponent() - expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), undefined) + expect(fetchConversationsAction).toHaveBeenCalledWith(expect.anything(), expect.anything()) expect(conversationsListMock).toHaveBeenCalled() const appNavEl = wrapper.findComponent({ name: 'NcAppNavigation' }) diff --git a/src/components/LeftSidebar/LeftSidebar.vue b/src/components/LeftSidebar/LeftSidebar.vue index 7933764d0ed..7cf2fd6a87c 100644 --- a/src/components/LeftSidebar/LeftSidebar.vue +++ b/src/components/LeftSidebar/LeftSidebar.vue @@ -178,6 +178,8 @@ export default { unreadNum: 0, firstUnreadPos: 0, preventFindingUnread: false, + roomListModifiedBefore: 0, + forceFullRoomListRefreshAfterXLoops: 0, } }, @@ -439,8 +441,10 @@ export default { return conversation2.lastActivity - conversation1.lastActivity }, - async handleShouldRefreshConversations({ token, properties }) { - if (token && properties) { + async handleShouldRefreshConversations({ token = undefined, properties = undefined, all = undefined }) { + if (all === true) { + this.roomListModifiedBefore = 0 + } else if (token && properties) { await this.$store.dispatch('setConversationProperties', { token, properties }) } @@ -455,13 +459,32 @@ export default { async fetchConversations() { this.isFetchingConversations = true + if (this.forceFullRoomListRefreshAfterXLoops === 0) { + this.roomListModifiedBefore = 0 + this.forceFullRoomListRefreshAfterXLoops = 10 + } else { + this.forceFullRoomListRefreshAfterXLoops-- + } /** * Fetches the conversations from the server and then adds them one by one * to the store. */ try { - await this.$store.dispatch('fetchConversations') + const response = await this.$store.dispatch('fetchConversations', { + modifiedSince: this.roomListModifiedBefore, + }) + + // We can only support this with the HPB as otherwise rooms, + // you are not currently active in, will not be removed anymore, + // as there is no signaling message about it when the internal + // signaling is used. + if (loadState('spreed', 'signaling_mode') !== 'internal') { + if (response?.headers && response.headers['x-nextcloud-talk-modified-before']) { + this.roomListModifiedBefore = response.headers['x-nextcloud-talk-modified-before'] + } + } + this.initialisedConversations = true /** * Emits a global event that is used in App.vue to update the page title once the diff --git a/src/store/conversationsStore.js b/src/store/conversationsStore.js index 9706cfb09f6..c0b5462c0c7 100644 --- a/src/store/conversationsStore.js +++ b/src/store/conversationsStore.js @@ -604,13 +604,25 @@ const actions = { } }, - async fetchConversations({ dispatch }) { + async fetchConversations({ dispatch }, { modifiedSince }) { try { dispatch('clearMaintenanceMode') + modifiedSince = modifiedSince || 0 + + let options = {} + if (modifiedSince !== 0) { + options = { + params: { + modifiedSince, + }, + } + } - const response = await fetchConversations() + const response = await fetchConversations(options) dispatch('updateTalkVersionHash', response) - dispatch('purgeConversationsStore') + if (modifiedSince === 0) { + dispatch('purgeConversationsStore') + } response.data.ocs.data.forEach(conversation => { dispatch('addConversation', conversation) }) diff --git a/src/store/conversationsStore.spec.js b/src/store/conversationsStore.spec.js index fc162330a19..919a84fa701 100644 --- a/src/store/conversationsStore.spec.js +++ b/src/store/conversationsStore.spec.js @@ -259,9 +259,9 @@ describe('conversationsStore', () => { fetchConversations.mockResolvedValue(response) - await store.dispatch('fetchConversations') + await store.dispatch('fetchConversations', {}) - expect(fetchConversations).toHaveBeenCalledWith() + expect(fetchConversations).toHaveBeenCalledWith({}) expect(store.getters.conversationsList).toStrictEqual(testConversations) expect(clearMaintenanceModeAction).toHaveBeenCalled() @@ -281,7 +281,7 @@ describe('conversationsStore', () => { const response = { status: 503 } fetchConversations.mockRejectedValue({ response }) - await expect(store.dispatch('fetchConversations')).rejects.toMatchObject({ response }) + await expect(store.dispatch('fetchConversations', {})).rejects.toMatchObject({ response }) expect(checkMaintenanceModeAction).toHaveBeenCalledWith(expect.anything(), response) }) diff --git a/src/utils/signaling.js b/src/utils/signaling.js index c8070fac2a4..fdb1ff8019c 100644 --- a/src/utils/signaling.js +++ b/src/utils/signaling.js @@ -1302,6 +1302,10 @@ Signaling.Standalone.prototype.processRoomMessageEvent = function(data) { Signaling.Standalone.prototype.processRoomListEvent = function(data) { switch (data.event.type) { + case 'delete': + console.debug('Room list event', data) + EventBus.$emit('should-refresh-conversations', { all: true }) + break case 'update': if (data.event.update.properties['participant-list']) { console.debug('Room list event for participant list', data)