scroll up to unload messages

This commit is contained in:
supertiger1234 2019-08-19 10:20:50 +01:00
parent 9603901214
commit d5dbd19488
8 changed files with 152 additions and 43 deletions

52
package-lock.json generated
View file

@ -2792,7 +2792,8 @@
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true "dev": true,
"optional": true
}, },
"coa": { "coa": {
"version": "2.0.2", "version": "2.0.2",
@ -5026,7 +5027,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -5047,12 +5049,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -5067,17 +5071,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -5194,7 +5201,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -5206,6 +5214,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -5220,6 +5229,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -5227,12 +5237,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -5251,6 +5263,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -5331,7 +5344,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -5343,6 +5357,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -5428,7 +5443,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -5464,6 +5480,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -5483,6 +5500,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -5526,12 +5544,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -6934,6 +6954,7 @@
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"prelude-ls": "~1.1.2", "prelude-ls": "~1.1.2",
"type-check": "~0.3.2" "type-check": "~0.3.2"
@ -9064,7 +9085,8 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
"dev": true "dev": true,
"optional": true
}, },
"prepend-http": { "prepend-http": {
"version": "2.0.0", "version": "2.0.0",
@ -9783,7 +9805,8 @@
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true "dev": true,
"optional": true
}, },
"rx-lite-aggregates": { "rx-lite-aggregates": {
"version": "4.0.8", "version": "4.0.8",
@ -11336,6 +11359,7 @@
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"prelude-ls": "~1.1.2" "prelude-ls": "~1.1.2"
} }

View file

@ -1,9 +1,9 @@
<template> <template>
<div ref="msg-logs" class="message-logs" @scroll="scrollEvent" @resize="onResize"> <div ref="msg-logs" class="message-logs" @scroll.passive="scrollEvent" @resize="onResize">
<div class="load-more-button" v-if="!noMoreLoadMore && selectedChannelMessages.length >= 50"> <div class="load-more-button" v-if="loadMoreTop.show && selectedChannelMessages.length >= 50">
<spinner :size="30" v-if="loadingMore" /> <spinner :size="30" v-if="loadMoreTop.loading" />
<div class="text" v-if="!loadingMore" @click="loadMoreMessages">Load more</div> <div class="text" v-if="!loadMoreTop.loading" @click="loadMoreMessages">Load more</div>
</div> </div>
<message <message
class="message-container" class="message-container"
@ -24,7 +24,10 @@
:timeEdited="msg.timeEdited" :timeEdited="msg.timeEdited"
/> />
<uploadsQueue v-if="uploadQueue !== undefined" :queue="uploadQueue"/> <uploadsQueue v-if="uploadQueue !== undefined" :queue="uploadQueue"/>
<div class="load-more-button" v-if="loadMoreBottom.show && selectedChannelMessages.length >= 50">
<spinner :size="30" v-if="!loadMoreTop.loading" />
<div class="text" v-if="!loadMoreBottom.loading">Load more</div>
</div>
</div> </div>
</template> </template>
@ -51,9 +54,14 @@ export default {
scrolledDown: true, scrolledDown: true,
scrolledTop: false, scrolledTop: false,
//load more messages loadMoreTop: {
loadingMore: false, show: true,
noMoreLoadMore: false, loading: false
},
loadMoreBottom: {
show: false,
loading: false,
},
selectedChannelID: null, selectedChannelID: null,
currentScrollTopPos: null currentScrollTopPos: null
}; };
@ -73,40 +81,89 @@ export default {
if (!element) return; if (!element) return;
element.scrollTop = pos || element.scrollHeight; element.scrollTop = pos || element.scrollHeight;
}, },
unloadTopMessages(){
if (this.selectedChannelMessages && this.selectedChannelMessages.length >= 100)
this.$store.dispatch('unloadTopMessages', {channelID: this.selectedChannelID});
},
unloadBottomMessages(){
if (this.selectedChannelMessages && this.selectedChannelMessages.length >= 100)
this.$store.dispatch('unloadBottomMessages', {channelID: this.selectedChannelID});
},
onResize(dimentions) { onResize(dimentions) {
this.scrollDown(); this.scrollDown();
}, },
async loadMoreMessages() { async loadMoreMessages() {
if (this.loadMoreTop.loading) return;
const msgLogs = this.$refs['msg-logs']; const msgLogs = this.$refs['msg-logs'];
const scrollTop = msgLogs.scrollTop; const scrollTop = msgLogs.scrollTop;
const scrollHeight = msgLogs.scrollHeight; const scrollHeight = msgLogs.scrollHeight;
const continueMessageID = this.selectedChannelMessages[0].messageID; const continueMessageID = this.selectedChannelMessages[0].messageID;
this.loadingMore = true this.$set(this.loadMoreTop, 'loading', true);
const {ok, result, error} = await messagesService.get(this.selectedChannelID, continueMessageID) const {ok, result, error} = await messagesService.get(this.selectedChannelID, continueMessageID)
if (ok) { if (ok) {
if (!result.data.messages.length) { if (!result.data.messages.length) {
this.loadingMore = false; this.$set(this.loadMoreTop, 'loading', false);
this.noMoreLoadMore = true; this.$set(this.loadMoreTop, 'show', false);
return; return;
} }
this.$store.dispatch('addMessages', result.data.messages) this.$store.dispatch('addMessages', result.data.messages)
this.$nextTick(_ => { this.$nextTick(_ => {
this.loadingMore = false; this.$set(this.loadMoreTop, 'loading', false);
msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight; msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight;
}) })
} }
}, },
async loadBottomMessages() {
if (this.loadMoreBottom.loading) return;
const msgLogs = this.$refs['msg-logs'];
const scrollTop = msgLogs.scrollTop;
const scrollHeight = msgLogs.scrollHeight;
const beforeMessageID = this.selectedChannelMessages[this.selectedChannelMessages.length - 1].messageID;
this.$set(this.loadMoreBottom, 'loading', true);
const {ok, result, error} = await messagesService.get(this.selectedChannelID, null, beforeMessageID)
if (ok) {
if (!result.data.messages.length) {
this.$set(this.loadMoreBottom, 'loading', false);
this.$set(this.loadMoreBottom, 'show', false);
return;
}
this.$store.dispatch('addMessagesBefore', result.data.messages)
this.$nextTick(_ => {
this.$set(this.loadMoreBottom, 'loading', false);
this.scrolledDown = false;
msgLogs.scrollTop = scrollTop
this.$set(this.loadMoreBottom, 'show', true);
})
}
},
scrolledUpEvent() { scrolledUpEvent() {
this.loadMoreMessages(); const msgLogs = this.$refs['msg-logs'];
const scrollTop = msgLogs.scrollTop;
const scrollHeight = msgLogs.scrollHeight;
this.unloadBottomMessages();
this.$set(this.loadMoreBottom, 'show', true);
this.$nextTick(_ => {
msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight;
if (this.loadMoreTop.show)
this.loadMoreMessages();
})
}, },
scrolledDownEvent(){ scrolledDownEvent(){
this.noMoreLoadMore = false;
this.unloadTopMessages() this.unloadTopMessages()
}, this.$nextTick(_ => {
unloadTopMessages(){ if (this.loadMoreBottom.show)
if (this.selectedChannelMessages && this.selectedChannelMessages.length) this.loadBottomMessages();
this.$store.dispatch('unloadTopMessages', {channelID: this.selectedChannelID}); this.$set(this.loadMoreTop, 'show', true);
})
}, },
backToBottomEvent() { backToBottomEvent() {
this.scrollDown({force: true}); this.scrollDown({force: true});
@ -130,14 +187,17 @@ export default {
beforeDestroy() { beforeDestroy() {
this.$store.dispatch("setEditMessage", null); this.$store.dispatch("setEditMessage", null);
this.$store.dispatch('changeScrollPosition',{ channelID: this.selectedChannelID, pos: this.currentScrollTopPos }); this.$store.dispatch('changeScrollPosition',{
channelID: this.selectedChannelID,
pos: !this.scrolledDown ? this.currentScrollTopPos : null
});
bus.$off('backToBottom', this.backToBottomEvent); bus.$off('backToBottom', this.backToBottomEvent);
bus.$off('scrollDown', this.scrollDown) bus.$off('scrollDown', this.scrollDown)
}, },
watch: { watch: {
selectedChannelMessages(newMessages, oldMessages){ selectedChannelMessages(newMessages, oldMessages){
this.noMoreLoadMore = false; this.$set(this.loadMoreTop, 'show', true);
const msgLogs = this.$refs['msg-logs']; const msgLogs = this.$refs['msg-logs'];
this.$nextTick(function () { this.$nextTick(function () {
this.scrollDown(); this.scrollDown();

View file

@ -9,9 +9,9 @@
<spinner /> <spinner />
</div> </div>
<message-logs v-else-if="selectedChannelID && selectedChannelMessages" :key="selectedChannelID" /> <message-logs v-else-if="selectedChannelID && selectedChannelMessages" :key="selectedChannelID" />
<div class="no-channel-selected" v-if="!selectedChannelID "> <div class="no-channel-selected" v-if="!selectedChannelID">
<div class="material-icons">chat</div> <div class="material-icons">{{type === 0 ? 'chat' : type === 1 ? 'forum' : 'question'}}</div>
<div class="message">Select a person to message!</div> <div class="message">{{type === 0 ? 'Select a person to message!' : type === 1 ?'Selected a server!' : "wot"}}</div>
</div> </div>
<div class="chat-input-area" v-if="selectedChannelID"> <div class="chat-input-area" v-if="selectedChannelID">
<div style="position: relative;"> <div style="position: relative;">
@ -86,6 +86,7 @@ const emojiPanel = () => import("@/components/app/EmojiPanels/emojiPanel.vue");
const EditPanel = () => import("@/components/app/EditPanel.vue"); const EditPanel = () => import("@/components/app/EditPanel.vue");
export default { export default {
props: ['type'], // type 0: dm; type 1: server
components: { components: {
Spinner, Spinner,
TypingStatus, TypingStatus,

View file

@ -7,7 +7,7 @@
class="left-panel" class="left-panel"
/> />
</transition> </transition>
<message-panel /> <message-panel :type="0"/>
</div> </div>
</template> </template>

View file

@ -7,7 +7,7 @@
class="left-panel" class="left-panel"
/> />
</transition> </transition>
<message-panel /> <message-panel :type="1" />
<transition :name="$mq !== 'desktop' ? 'slide-right' : 'none'"> <transition :name="$mq !== 'desktop' ? 'slide-right' : 'none'">
<members-list <members-list
v-if="selectedServerID && (($mq === 'members_panel' || $mq === 'mobile') && showMembersPanel || ($mq === 'desktop'))" v-if="selectedServerID && (($mq === 'members_panel' || $mq === 'mobile') && showMembersPanel || ($mq === 'desktop'))"

View file

@ -2,8 +2,8 @@ import {instance, wrapper} from './Api';
import filesize from "filesize"; import filesize from "filesize";
export default { export default {
// TODO: add ?continue=id // TODO: add ?continue=id
get ( channelID, continueMessageID ) { get ( channelID, continueMessageID, beforeMessageID ) {
return wrapper(instance().get(`messages/channels/${channelID}${continueMessageID ? '?continue=' + continueMessageID : ''}`)); return wrapper(instance().get(`messages/channels/${channelID}${continueMessageID ? '?continue=' + continueMessageID : beforeMessageID ? '?before=' + beforeMessageID : '' }`));
}, },
delete ( messageID, channelID ) { delete ( messageID, channelID ) {
return wrapper(instance().delete(`messages/${messageID}/channels/${channelID}`)); return wrapper(instance().delete(`messages/${messageID}/channels/${channelID}`));

View file

@ -86,6 +86,14 @@ const actions = {
context.commit('messages', {messages: join, channelID}); context.commit('messages', {messages: join, channelID});
}, },
addMessagesBefore(context, messagesArr){
const channelID = messagesArr[0].channelID;
const messages = context.state.messages[channelID];
const join = [ ...messages, ...messagesArr, ];
context.commit('messages', {messages: join, channelID});
},
replaceMessage(context, data) { replaceMessage(context, data) {
context.commit("replaceMessage", data); context.commit("replaceMessage", data);
}, },
@ -112,8 +120,14 @@ const actions = {
context.commit('changeScrollPosition', {channelID, pos}) context.commit('changeScrollPosition', {channelID, pos})
}, },
unloadTopMessages(context, {channelID}) { unloadTopMessages(context, {channelID}) {
const messages = [...[], ...context.state.messages[channelID]];
const unloaded = messages.splice(50)
context.commit('messages', {channelID, messages: unloaded})
},
unloadBottomMessages(context, {channelID}) {
const messages = context.state.messages[channelID]; const messages = context.state.messages[channelID];
const unloaded = messages.slice(Math.max(messages.length - 50, 0)) const unloaded = messages.slice(0, -50)
context.commit('messages', {channelID, messages: unloaded}) context.commit('messages', {channelID, messages: unloaded})
} }
}; };

View file

@ -14,13 +14,23 @@
const config = [ const config = [
{
version: 6.4,
title: "Scrolling up should be smoother!",
shortTitle: "",
date: "19/08/2019",
headColor: "rgba(25, 130, 255, 0.77)",
new: [
'Scrolling up should be smoother now as messages below get unloaded.'
]
},
{ {
version: 6.3, version: 6.3,
title: "Performance Improvements!", title: "Performance Improvements!",
shortTitle: "", shortTitle: "",
date: "18/08/2019", date: "18/08/2019",
headColor: "rgba(25, 130, 255, 0.77)", headColor: "rgba(25, 130, 255, 0.77)",
msg: "I finally managed to find out why the chat is choppy when scrolling. The rotated emote is the cause. In this update, emotes only appear only when hovering over the profile picture." msg: "I finally managed to find out why the chat is choppy when scrolling. The rotated emote is the cause. In this update, emotes only appear when hovering over the profile picture."
}, },
{ {