diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 27713e30..ae812afe 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -15,6 +15,7 @@ const Chat = { }, data () { return { + loadingOlderMessages: false, loadingMessages: true, loadingChat: false, editedStatusId: undefined, @@ -270,8 +271,29 @@ const Chat = { return bottomedOut }, + getPosition () { + let scrollHeight = this.$refs.scrollable.scrollTop + let totalHeight = this.$refs.scrollable.scrollHeight - this.$refs.scrollable.offsetHeight + return { scrollHeight, totalHeight } + }, + reachedTop (offset) { + let res = false + + if (this.$refs.scrollable) { + let scrollHeight = this.$refs.scrollable.scrollTop + (offset || 0) + if (scrollHeight <= offset) { + res = true + } + } + + return res + }, handleScroll: throttle(function () { - if (this.bottomedOut(150)) { + if (this.reachedTop(0)) { + this.fetchChat(false, this.currentChat.id, { + maxId: this.currentChatMessageService.minId + }) + } else if (this.bottomedOut(150)) { this.jumpToBottomButtonVisible = false let newMessageCount = this.newMessageCount if (newMessageCount > 0) { @@ -284,16 +306,36 @@ const Chat = { goBack () { this.$router.push({ name: 'chats', params: { username: this.currentUser.screen_name } }) }, - fetchChat (isFirstFetch, chatId) { + fetchChat (isFirstFetch, chatId, opts = {}) { + let maxId = opts.maxId this.chatViewItems = chatService.getView(this.currentChatMessageService) if (isFirstFetch) { this.scrollDown({ forceRead: true }) } - this.backendInteractor.chatMessages({ id: chatId }) + let positionBeforeLoading = null + let previousScrollTop + if (maxId) { + this.loadingOlderMessages = true + positionBeforeLoading = this.getPosition() + previousScrollTop = this.$refs.scrollable.scrollTop + } + this.backendInteractor.chatMessages({ id: chatId, maxId }) .then((messages) => { let bottomedOut = this.bottomedOut() + this.loadingOlderMessages = false this.$store.dispatch('addChatMessages', { chatId, messages }).then(() => { this.chatViewItems = chatService.getView(this.currentChatMessageService) + if (positionBeforeLoading) { + this.$nextTick(() => { + let positionAfterLoading = this.getPosition() + let scrollable = this.$refs.scrollable + scrollable.scrollTo({ + top: previousScrollTop + (positionAfterLoading.totalHeight - positionBeforeLoading.totalHeight), + left: 0 + }) + }) + } + this.newMessageCount = this.currentChatMessageService.newMessageCount if (isFirstFetch) { this.$nextTick(() => { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 9222f94b..3a094bed 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -1150,9 +1150,18 @@ const getOrCreateChat = ({ accountId, credentials }) => { }) } -const chatMessages = ({ id, credentials }) => { +const chatMessages = ({ id, credentials, maxId, sinceId, limit = 20 }) => { + let url = PLEROMA_CHAT_MESSAGES_URL(id) + const args = [ + maxId && `max_id=${maxId}`, + sinceId && `since_id=${sinceId}`, + limit && `limit=${limit}` + ].filter(_ => _).join('&') + + url = url + (args ? '?' + args : '') + return promisedRequest({ - url: PLEROMA_CHAT_MESSAGES_URL(id), + url, method: 'GET', credentials }) diff --git a/src/services/chat_service/chat_service.js b/src/services/chat_service/chat_service.js index b570a065..5f419249 100644 --- a/src/services/chat_service/chat_service.js +++ b/src/services/chat_service/chat_service.js @@ -6,7 +6,8 @@ const empty = (chatId) => { messages: [], newMessageCount: 0, lastSeenTimestamp: 0, - chatId: chatId + chatId: chatId, + minId: undefined } } @@ -18,6 +19,10 @@ const add = (storage, { messages: newMessages }) => { // sanity check if (message.chat_id !== storage.chatId) { return } + if (!storage.minId || message.id < storage.minId) { + storage.minId = message.id + } + if (!storage.idIndex[message.id]) { if (storage.lastSeenTimestamp < message.created_at) { storage.newMessageCount++