Nertivia-Client/src/components/app/MessageLogs.vue
2020-02-16 13:29:25 +00:00

390 lines
11 KiB
Vue

<template>
<div
ref="msg-logs"
class="message-logs"
@scroll.passive="scrollEvent"
@resize="onResize"
>
<div
class="load-more-button"
v-if="loadMoreTop.show && selectedChannelMessages.length >= 50"
>
<spinner :size="30" v-if="loadMoreTop.loading" />
<div class="text" v-if="!loadMoreTop.loading" @click="loadMoreMessages">
Load more
</div>
</div>
<message
v-for="(msg, index) in selectedChannelMessages"
:class="{
'show-message-animation': index === selectedChannelMessages.length - 1
}"
:key="msg.tempID || msg.messageID"
:creator="msg.creator"
:message="msg"
:isServer="isServer"
:hideAditional="groupedMessages.includes(msg.messageID)"
/>
<!-- {{ groupedMessages }} -->
<uploadsQueue v-if="uploadQueue !== undefined" :queue="uploadQueue" />
<div
class="load-more-button"
v-if="loadMoreBottom.show && selectedChannelMessages.length >= 50"
>
<spinner :size="30" v-if="loadMoreBottom.loading" />
<div
class="text"
v-if="!loadMoreBottom.loading"
@click="loadBottomMessages"
>
Load more
</div>
</div>
</div>
</template>
<script>
import messagesService from "@/services/messagesService";
import { bus } from "../../main";
import Message from "../../components/app/MessageTemplate.vue";
import Spinner from "@/components/Spinner.vue";
import uploadsQueue from "@/components/app/uploadsQueue.vue";
import debounce from "lodash/debounce";
import windowProperties from "@/utils/windowProperties";
export default {
components: {
Message,
Spinner,
uploadsQueue
},
data() {
return {
scrolledDown: true,
scrolledTop: false,
loadMoreTop: {
show: true,
loading: false
},
loadMoreBottom: {
show: false,
loading: false
},
selectedChannelID: null,
currentScrollTopPos: null,
backToBottomLoading: false
};
},
methods: {
scrollEvent: debounce(function(event) {
const {
target: { scrollTop, clientHeight, scrollHeight }
} = event;
this.scrolledDown =
Math.abs(scrollHeight - scrollTop - clientHeight) <= 3.0;
this.scrolledTop = scrollTop === 0;
this.currentScrollTopPos = scrollTop;
}, 20),
scrollDown(data) {
const element = this.$refs["msg-logs"];
const force = data && data.force ? data.force : false;
const pos = data && data.pos ? data.pos : undefined;
if (!force && !this.scrolledDown) return;
if (!element) return;
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("setBottomUnloadStatus", {
channelID: this.selectedChannelID,
status: true
});
this.$store.dispatch("unloadBottomMessages", {
channelID: this.selectedChannelID
});
}
},
onResize() {
this.scrollDown();
},
async loadMoreMessages() {
if (this.loadMoreTop.loading) return;
const msgLogs = this.$refs["msg-logs"];
const scrollHeight = msgLogs.scrollHeight;
const continueMessageID = this.selectedChannelMessages[0].messageID;
this.$set(this.loadMoreTop, "loading", true);
const { ok, result } = await messagesService.get(
this.selectedChannelID,
continueMessageID
);
if (ok) {
if (!result.data.messages.length) {
this.$set(this.loadMoreTop, "loading", false);
this.$set(this.loadMoreTop, "show", false);
return;
}
this.$store.dispatch("addMessages", result.data.messages);
this.$nextTick(() => {
this.$set(this.loadMoreTop, "loading", false);
msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight;
});
}
},
async loadBottomMessages() {
if (this.loadMoreBottom.loading) return;
const msgLogs = this.$refs["msg-logs"];
const scrollTop = msgLogs.scrollTop;
const channelID = this.selectedChannelID;
const beforeMessageID = this.selectedChannelMessages[
this.selectedChannelMessages.length - 1
].messageID;
this.$set(this.loadMoreBottom, "loading", true);
const { ok, result } = await messagesService.get(
channelID,
null,
beforeMessageID
);
if (ok) {
if (!result.data.messages.length) {
this.$store.dispatch("setBottomUnloadStatus", {
channelID,
status: false
});
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() {
this.unloadBottomMessages();
const msgLogs = this.$refs["msg-logs"];
this.$set(this.loadMoreBottom, "show", true);
this.$nextTick(() => {
msgLogs.scrollTop = 0;
if (this.loadMoreTop.show) this.loadMoreMessages();
});
},
scrolledDownEvent() {
this.unloadTopMessages();
this.$set(this.loadMoreTop, "show", true);
this.$nextTick(() => {
if (this.loadMoreBottom.show) this.loadBottomMessages();
});
},
async backToBottomEvent() {
if (this.backToBottomLoading) return;
const channelID = this.selectedChannelID;
const bottomUnloaded = this.bottomUnloaded;
if (!bottomUnloaded) {
this.scrollDown({ force: true });
this.unloadTopMessages();
return;
}
this.backToBottomLoading = true;
const { ok, result } = await messagesService.get(this.selectedChannelID);
if (ok) {
this.$store.dispatch("messages", {
messages: result.data.messages.reverse(),
channelID
});
this.$set(this.loadMoreBottom, "show", false);
this.$store.dispatch("setBottomUnloadStatus", {
channelID,
status: false
});
this.$nextTick(() => {
this.scrollDown({ force: true });
});
}
this.backToBottomLoading = false;
}
},
mounted() {
this.selectedChannelID = this.$store.getters.selectedChannelID;
const pos = this.$store.getters.scrollPosition[this.selectedChannelID];
bus.$on("backToBottom", this.backToBottomEvent);
bus.$on("scrollDown", this.scrollDown);
bus.$emit("scrolledDown", this.scrolledDown);
if (this.bottomUnloaded) {
this.$set(this.loadMoreBottom, "show", true);
}
this.$nextTick(() => {
this.scrollDown({ force: pos, pos: pos });
});
},
beforeDestroy() {
this.$store.dispatch("setEditMessage", null);
this.$store.dispatch("changeScrollPosition", {
channelID: this.selectedChannelID,
pos: !this.scrolledDown ? this.currentScrollTopPos : null
});
bus.$off("backToBottom", this.backToBottomEvent);
bus.$off("scrollDown", this.scrollDown);
},
watch: {
selectedChannelMessages() {
this.$set(this.loadMoreTop, "show", true);
this.$nextTick(function() {
this.scrollDown();
});
},
uploadQueue() {
this.$nextTick(function() {
this.scrollDown({ force: true });
});
},
getWindowWidth() {
this.onResize();
},
scrolledTop(scrolledTop) {
if (scrolledTop) this.scrolledUpEvent();
},
scrolledDown(scrolledDown) {
bus.$emit("scrolledDown", scrolledDown);
if (scrolledDown) this.scrolledDownEvent();
}
},
computed: {
isServer() {
return this.$store.getters.currentTab === 2;
},
uploadQueue() {
const allUploads = this.$store.getters.getAllUploads;
const selectedChannelID = this.$store.getters.selectedChannelID;
const filteredArray = [];
for (let upload in allUploads) {
if (allUploads[upload].channelID === selectedChannelID) {
filteredArray.push(allUploads[upload]);
}
}
if (!filteredArray.length) return undefined;
return filteredArray;
},
user() {
return this.$store.getters.user;
},
channel() {
return this.$store.getters.channels[this.selectedChannelID];
},
selectedChannelMessages() {
const selectedChannel = this.$store.getters.selectedChannelID;
return this.$store.getters.messages[selectedChannel];
},
editMessage() {
let editMessage = this.$store.getters.popouts.editMessage;
if (!editMessage) return null;
return editMessage;
},
getWindowWidth() {
return {
width: windowProperties.resizeWidth,
height: windowProperties.resizeHeight
};
},
scrollPosition() {
return this.$store.getters.scrollPosition;
},
bottomUnloaded() {
return (
this.$store.getters.bottomUnloaded[this.selectedChannelID] || false
);
},
groupedMessages() {
const messages = this.selectedChannelMessages;
const grouped = [];
let groupLength = 0;
let prevMessageCreator = null;
for (let index = 0; index < messages.length; index++) {
const message = messages[index];
if (message.type !== 0 && message.type !== undefined) {
groupLength = 0;
prevMessageCreator = null;
continue;
}
if (message.creator.uniqueID !== prevMessageCreator) {
groupLength = 0;
prevMessageCreator = message.creator.uniqueID;
} else {
if (groupLength > 3) {
groupLength = 0;
continue;
}
grouped.push(message.messageID);
groupLength += 1;
}
}
return grouped;
}
}
};
</script>
<style lang="scss" scoped>
.message-logs {
overflow: auto;
flex: 1;
position: relative;
padding-bottom: 23px;
}
.load-more-button {
background: rgba(0, 0, 0, 0.46);
padding: 5px;
user-select: none;
border-radius: 5px;
margin: 5px;
height: 30px;
display: flex;
flex-direction: column;
justify-content: center;
.text {
text-align: center;
color: white;
cursor: pointer;
align-self: center;
}
}
.show-message-animation {
animation: showMessage 0.3s ease-in-out;
}
@keyframes showMessage {
from {
transform: translate(-50px, 0);
opacity: 0;
}
}
</style>