mirror of
https://github.com/danbulant/Nertivia-Client
synced 2026-06-18 22:11:03 +00:00
added load more messages and scroll down button.
This commit is contained in:
parent
6f65d1291d
commit
53e8fff392
12 changed files with 532 additions and 305 deletions
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
<script>
|
||||
import messageFormatter from "@/utils/messageFormatter.js";
|
||||
import { bus } from "../../main";
|
||||
|
||||
export default {
|
||||
props: ['data'],
|
||||
|
|
@ -20,6 +21,9 @@ export default {
|
|||
this.close();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$emit('scrollDown')
|
||||
},
|
||||
created() {
|
||||
document.addEventListener('keydown', this.keyDownEvent)
|
||||
},
|
||||
|
|
@ -46,7 +50,7 @@ export default {
|
|||
background: rgba(23, 112, 255, 0.877);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 99999;
|
||||
z-index:1;
|
||||
border-radius: 10px;
|
||||
margin: 10px;
|
||||
margin-bottom: 0;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
<template>
|
||||
<div
|
||||
v-click-outside="closePanel"
|
||||
class="emoji-panel"
|
||||
>
|
||||
<div v-click-outside="closePanel" class="emoji-panel">
|
||||
<div class="emoji-panel-inner">
|
||||
<div class="emojis-list">
|
||||
<!-- Recent Emojis Category -->
|
||||
<div class="category">
|
||||
<div class="category-name">
|
||||
Recent
|
||||
</div>
|
||||
<div class="category-name">Recent</div>
|
||||
<div class="list">
|
||||
<div
|
||||
v-for="(recentEmoji, index) in this.recentEmojisList"
|
||||
|
|
@ -21,16 +16,14 @@
|
|||
v-lazyload
|
||||
class="panel emoji"
|
||||
:data-url=" getCustomEmoji(recentEmoji) || emojiShortcodeToPath(':' + recentEmoji + ':')"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Emojis Category -->
|
||||
<div class="category">
|
||||
<div class="category-name">
|
||||
Custom Emojis
|
||||
</div>
|
||||
<div class="category-name">Custom Emojis</div>
|
||||
<div class="list">
|
||||
<div
|
||||
v-for="(customEmoji, index) in this.customEmojisList"
|
||||
|
|
@ -38,23 +31,13 @@
|
|||
class="emoji-item"
|
||||
@click="customEmojiClickEvent(customEmoji)"
|
||||
>
|
||||
<img
|
||||
v-lazyload
|
||||
class="panel emoji"
|
||||
:data-url="customEmojiPath + customEmoji.emojiID"
|
||||
>
|
||||
<img v-lazyload class="panel emoji" :data-url="customEmojiPath + customEmoji.emojiID" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="(group, index) in groups"
|
||||
:key="group"
|
||||
class="category"
|
||||
>
|
||||
<div class="category-name">
|
||||
{{ group }}
|
||||
</div>
|
||||
<div v-for="(group, index) in groups" :key="group" class="category">
|
||||
<div class="category-name">{{ group }}</div>
|
||||
<div class="list">
|
||||
<div
|
||||
v-for="emojiSorted in emojiByGroup(index)"
|
||||
|
|
@ -62,33 +45,19 @@
|
|||
class="emoji-item"
|
||||
@click="emojiClickEvent(emojiSorted.shortcodes[0])"
|
||||
>
|
||||
<img
|
||||
v-lazyload
|
||||
class="panel emoji"
|
||||
:data-url="parseEmojiPath(emojiSorted.unicode)"
|
||||
>
|
||||
<img v-lazyload class="panel emoji" :data-url="parseEmojiPath(emojiSorted.unicode)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<div
|
||||
class="tab"
|
||||
@click="scrollToCategory(0)"
|
||||
>
|
||||
<div class="tab" @click="scrollToCategory(0)">
|
||||
<i class="material-icons">history</i>
|
||||
<div class="tooltip">
|
||||
Recent
|
||||
</div>
|
||||
<div class="tooltip">Recent</div>
|
||||
</div>
|
||||
<div
|
||||
class="tab"
|
||||
@click="scrollToCategory(1)"
|
||||
>
|
||||
<div class="tab" @click="scrollToCategory(1)">
|
||||
<i class="material-icons">face</i>
|
||||
<div class="tooltip">
|
||||
Custom Emojis
|
||||
</div>
|
||||
<div class="tooltip">Custom Emojis</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="(emoji, index) in groupUnicodes"
|
||||
|
|
@ -97,13 +66,8 @@
|
|||
@mouseenter="mouseHover(emoji, $event)"
|
||||
@click="scrollToCategory(index + 2)"
|
||||
>
|
||||
<img
|
||||
class="panel-emoji"
|
||||
:src="selectRandom(emoji)"
|
||||
>
|
||||
<div class="tooltip">
|
||||
{{ groups[index] }}
|
||||
</div>
|
||||
<img class="panel-emoji" :src="selectRandom(emoji)" />
|
||||
<div class="tooltip">{{ groups[index] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -115,10 +79,9 @@
|
|||
import { bus } from "@/main";
|
||||
import emojiParser from "@/utils/emojiParser.js";
|
||||
import lazyLoad from "@/directives/LazyLoad.js";
|
||||
import {mapState} from 'vuex'
|
||||
import { mapState } from "vuex";
|
||||
import config from "@/config.js";
|
||||
|
||||
|
||||
export default {
|
||||
directives: {
|
||||
lazyload: lazyLoad
|
||||
|
|
@ -377,23 +340,23 @@ export default {
|
|||
emojis: emojiParser.allEmojis,
|
||||
groups: emojiParser.allGroups,
|
||||
recentEmojisList: null,
|
||||
customEmojisList : null,
|
||||
customEmojiPath: config.domain + "/files/"
|
||||
|
||||
customEmojisList: null,
|
||||
customEmojiPath: config.domain + "/media/"
|
||||
};
|
||||
},
|
||||
beforeMount() {
|
||||
this.recentEmojisList = this.recentEmojis
|
||||
this.customEmojisList = this.customEmojis
|
||||
this.recentEmojisList = this.recentEmojis;
|
||||
this.customEmojisList = this.customEmojis;
|
||||
},
|
||||
methods: {
|
||||
getCustomEmoji(shortCode){
|
||||
const customEmoji = emojiParser.getCustomEmojisByShortCode(shortCode)
|
||||
return (customEmoji ? this.customEmojiPath + customEmoji.emojiID : undefined)
|
||||
getCustomEmoji(shortCode) {
|
||||
const customEmoji = emojiParser.getCustomEmojisByShortCode(shortCode);
|
||||
return customEmoji
|
||||
? this.customEmojiPath + customEmoji.emojiID
|
||||
: undefined;
|
||||
},
|
||||
closePanel(event) {
|
||||
if (!event.target.closest('.emojis-button'))
|
||||
this.$emit('close')
|
||||
if (!event.target.closest(".emojis-button")) this.$emit("close");
|
||||
},
|
||||
emojiByGroup(index) {
|
||||
index = parseInt(index);
|
||||
|
|
@ -422,9 +385,9 @@ export default {
|
|||
const elements = document.querySelectorAll(".category-name");
|
||||
elements[index].scrollIntoView();
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState('settingsModule', ['recentEmojis', 'customEmojis'])
|
||||
...mapState("settingsModule", ["recentEmojis", "customEmojis"])
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -483,6 +446,7 @@ export default {
|
|||
padding: 2px;
|
||||
border-radius: 5px;
|
||||
min-width: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.emoji-item:hover {
|
||||
background: rgb(59, 59, 59);
|
||||
|
|
@ -529,6 +493,7 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
|
|
@ -571,12 +536,10 @@ export default {
|
|||
</style>
|
||||
<style>
|
||||
img.panel.emoji {
|
||||
|
||||
margin: auto;
|
||||
padding: 2px;
|
||||
object-fit: contain;
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default {
|
|||
props: ["emojiArray"],
|
||||
data(){
|
||||
return {
|
||||
customEmojiPath: config.domain + "/files/"
|
||||
customEmojiPath: config.domain + "/media/"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
|
|||
259
src/components/app/MessageLogs.vue
Normal file
259
src/components/app/MessageLogs.vue
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
<template>
|
||||
|
||||
<div ref="msg-logs" class="message-logs" @scroll="scrollEvent" @resize="onResize">
|
||||
<div class="load-more-button" v-if="!noMoreLoadMore && selectedChannelMessages.length >= 50">
|
||||
<spinner :size="30" v-if="loadingMore" />
|
||||
<div class="text" v-if="!loadingMore" @click="loadMoreMessages">Load more</div>
|
||||
</div>
|
||||
<message
|
||||
class="message-container"
|
||||
v-for="(msg, index) in selectedChannelMessages"
|
||||
:key="index + selectedChannelID"
|
||||
:date="msg.created"
|
||||
:admin="msg.creator.admin"
|
||||
:username="msg.creator.username"
|
||||
:uniqueID="msg.creator.uniqueID"
|
||||
:avatar="msg.creator.avatar"
|
||||
:message="msg.message"
|
||||
:embed="msg.embed"
|
||||
:files="msg.files"
|
||||
:status="msg.status"
|
||||
:messageID="msg.messageID"
|
||||
:channelID="msg.channelID"
|
||||
:type="msg.type"
|
||||
:timeEdited="msg.timeEdited"
|
||||
/>
|
||||
<uploadsQueue v-if="uploadQueue !== undefined" :queue="uploadQueue"/>
|
||||
|
||||
</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 windowProperties from '@/utils/windowProperties';
|
||||
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Message,
|
||||
Spinner,
|
||||
uploadsQueue,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrolledDown: true,
|
||||
scrolledTop: false,
|
||||
|
||||
//load more messages
|
||||
loadingMore: false,
|
||||
noMoreLoadMore: false,
|
||||
selectedChannelID: null,
|
||||
currentScrollTopPos: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
scrollEvent(event) {
|
||||
const { currentTarget: { scrollTop, clientHeight, scrollHeight} } = event;
|
||||
this.scrolledDown = Math.abs(scrollHeight - scrollTop - clientHeight) <= 3.0;
|
||||
this.scrolledTop = scrollTop === 0;
|
||||
this.currentScrollTopPos = scrollTop;
|
||||
},
|
||||
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;
|
||||
},
|
||||
onResize(dimentions) {
|
||||
this.scrollDown();
|
||||
},
|
||||
async loadMoreMessages() {
|
||||
const msgLogs = this.$refs['msg-logs'];
|
||||
const scrollTop = msgLogs.scrollTop;
|
||||
const scrollHeight = msgLogs.scrollHeight;
|
||||
|
||||
const continueMessageID = this.selectedChannelMessages[0].messageID;
|
||||
this.loadingMore = true
|
||||
const {ok, result, error} = await messagesService.get(this.selectedChannelID, continueMessageID)
|
||||
if (ok) {
|
||||
if (!result.data.messages.length) {
|
||||
this.loadingMore = false;
|
||||
this.noMoreLoadMore = true;
|
||||
return;
|
||||
}
|
||||
this.$store.dispatch('addMessages', result.data.messages)
|
||||
this.$nextTick(_ => {
|
||||
this.loadingMore = false;
|
||||
msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight;
|
||||
})
|
||||
}
|
||||
},
|
||||
scrolledUpEvent() {
|
||||
this.loadMoreMessages();
|
||||
},
|
||||
scrolledDownEvent(){
|
||||
this.noMoreLoadMore = false;
|
||||
this.unloadTopMessages()
|
||||
},
|
||||
unloadTopMessages(){
|
||||
if (this.selectedChannelMessages && this.selectedChannelMessages.length)
|
||||
this.$store.dispatch('unloadTopMessages', {channelID: this.selectedChannelID});
|
||||
},
|
||||
backToBottomEvent() {
|
||||
this.scrollDown({force: true});
|
||||
this.unloadTopMessages();
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
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);
|
||||
this.$nextTick( _ => {
|
||||
this.scrollDown({force: pos, pos: pos});
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.$store.dispatch("setEditMessage", null);
|
||||
this.$store.dispatch('changeScrollPosition',{ channelID: this.selectedChannelID, pos: this.currentScrollTopPos });
|
||||
bus.$off('backToBottom', this.backToBottomEvent);
|
||||
bus.$off('scrollDown', this.scrollDown)
|
||||
},
|
||||
|
||||
watch: {
|
||||
selectedChannelMessages(newMessages, oldMessages){
|
||||
this.noMoreLoadMore = false;
|
||||
const msgLogs = this.$refs['msg-logs'];
|
||||
this.$nextTick(function () {
|
||||
this.scrollDown();
|
||||
})
|
||||
},
|
||||
uploadQueue() {
|
||||
this.$nextTick(function () {
|
||||
this.scrollDown({force: true});
|
||||
})
|
||||
},
|
||||
getWindowWidth(dimentions) {
|
||||
this.onResize();
|
||||
},
|
||||
scrolledTop(scrolledTop) {
|
||||
if (scrolledTop)
|
||||
this.scrolledUpEvent();
|
||||
},
|
||||
scrolledDown(scrolledDown) {
|
||||
bus.$emit('scrolledDown',scrolledDown);
|
||||
if (scrolledDown)
|
||||
this.scrolledDownEvent();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.message-logs {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
margin-right: 2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
.back-to-bottom-button {
|
||||
&:hover {
|
||||
background: rgb(23, 124, 255);
|
||||
box-shadow: 0px 0px 15px 0px #0000008a;
|
||||
}
|
||||
transition: 0.2s;
|
||||
background: rgba(23, 124, 255, 0.818);
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 25px;
|
||||
border-radius: 10px;
|
||||
height: 50px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 0px 7px 0px #0000008a;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
padding-left: 10px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
.material-icons {
|
||||
align-self: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 35px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,48 +3,31 @@
|
|||
<heading
|
||||
:uniqueID="recipients && recipients.length ? recipients[0].uniqueID : undefined"
|
||||
:type="selectedChannelID && channel && !channel.server_id ? 1 : channel && channel.server_id ? 2 : 0"
|
||||
:status-color="userStatusColor"
|
||||
:name="selectedChannelID ? channelName : `Welcome back, ${user.username}!` "
|
||||
/>
|
||||
<div class="loading" v-if="selectedChannelID && !selectedChannelMessages">
|
||||
<spinner/>
|
||||
</div>
|
||||
<div v-else-if="selectedChannelID" ref="msg-logs" class="message-logs" @scroll="scrollEvent">
|
||||
<div class="scroll">
|
||||
<message
|
||||
class="message-container"
|
||||
v-for="(msg, index) in selectedChannelMessages"
|
||||
:key="index + selectedChannelID"
|
||||
:date="msg.created"
|
||||
:admin="msg.creator.admin"
|
||||
:username="msg.creator.username"
|
||||
:uniqueID="msg.creator.uniqueID"
|
||||
:avatar="msg.creator.avatar"
|
||||
:message="msg.message"
|
||||
:embed="msg.embed"
|
||||
:files="msg.files"
|
||||
:status="msg.status"
|
||||
:messageID="msg.messageID"
|
||||
:channelID="msg.channelID"
|
||||
:type="msg.type"
|
||||
:timeEdited="msg.timeEdited"
|
||||
/>
|
||||
<uploadsQueue v-if="uploadQueue !== undefined" :queue="uploadQueue"/>
|
||||
</div>
|
||||
<spinner />
|
||||
</div>
|
||||
<message-logs v-else-if="selectedChannelID && selectedChannelMessages" :key="selectedChannelID" />
|
||||
<div class="no-channel-selected" v-if="!selectedChannelID ">
|
||||
<div class="material-icons">chat</div>
|
||||
<div class="message">Select a person to message!</div>
|
||||
</div>
|
||||
<div class="chat-input-area" v-if="selectedChannelID">
|
||||
<div style="position: relative;">
|
||||
<emoji-suggestions v-if="emojiArray" :emojiArray="emojiArray"/>
|
||||
<emoji-panel v-if="showEmojiPanel" @close="showEmojiPanel = false"/>
|
||||
<transition name="show-up">
|
||||
<div class="back-to-bottom-button" @click="backToTopButton" v-if="!scrolledDown && selectedChannelMessages">
|
||||
Back to bottom
|
||||
<i class="material-icons">keyboard_arrow_down</i>
|
||||
</div>
|
||||
</transition>
|
||||
<emoji-suggestions v-if="emojiArray" :emojiArray="emojiArray" />
|
||||
<emoji-panel v-if="showEmojiPanel" @close="showEmojiPanel = false" />
|
||||
</div>
|
||||
|
||||
<edit-panel v-if="editMessage" :data='editMessage' />
|
||||
<edit-panel v-if="editMessage" :data="editMessage" />
|
||||
<div class="message-area">
|
||||
<input type="file" ref="sendFileBrowse" @change="attachmentChange" class="hidden">
|
||||
<input type="file" ref="sendFileBrowse" @change="attachmentChange" class="hidden" />
|
||||
<div class="attachment-button" @click="attachmentButton">
|
||||
<i class="material-icons">attach_file</i>
|
||||
</div>
|
||||
|
|
@ -64,7 +47,8 @@
|
|||
<i class="material-icons">face</i>
|
||||
</button>
|
||||
<button
|
||||
:class="{'send-button': true, 'error-send-button': messageLength > 5000}"
|
||||
class="send-button"
|
||||
:class="{'error-send-button': messageLength > 5000}"
|
||||
@click="editMessage ? updateMessage() : sendMessage()"
|
||||
>
|
||||
<i class="material-icons">{{editMessage ? 'edit' : 'send'}}</i>
|
||||
|
|
@ -90,30 +74,26 @@ import messagesService from "@/services/messagesService";
|
|||
import typingService from "@/services/TypingService";
|
||||
import { bus } from "../../main";
|
||||
import JQuery from "jquery";
|
||||
let $ = JQuery;
|
||||
import Message from "../../components/app/MessageTemplate.vue";
|
||||
import Spinner from "@/components/Spinner.vue";
|
||||
import TypingStatus from "@/components/app/TypingStatus.vue";
|
||||
import uploadsQueue from "@/components/app/uploadsQueue.vue";
|
||||
import heading from "@/components/app/MessagePanel/Heading.vue";
|
||||
import emojiSuggestions from "@/components/app/EmojiPanels/emojiSuggestions.vue";
|
||||
import emojiParser from "@/utils/emojiParser.js";
|
||||
import statuses from "@/utils/statuses";
|
||||
import windowProperties from '@/utils/windowProperties';
|
||||
import MessageLogs from "@/components/app/MessageLogs.vue";
|
||||
import emojiParser from "@/utils/emojiParser.js";
|
||||
import windowProperties from "@/utils/windowProperties";
|
||||
|
||||
const emojiPanel = () => import("@/components/app/EmojiPanels/emojiPanel.vue");
|
||||
const EditPanel = () => import("@/components/app/EditPanel.vue");
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Message,
|
||||
Spinner,
|
||||
TypingStatus,
|
||||
uploadsQueue,
|
||||
emojiSuggestions,
|
||||
emojiPanel,
|
||||
heading,
|
||||
EditPanel
|
||||
EditPanel,
|
||||
MessageLogs
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -124,8 +104,8 @@ export default {
|
|||
typing: false,
|
||||
typingRecipients: {},
|
||||
showEmojiPanel: false,
|
||||
scrolledDown: true,
|
||||
scrolledTop: false,
|
||||
|
||||
scrolledDown: true
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -199,7 +179,7 @@ export default {
|
|||
const editMessage = this.editMessage;
|
||||
this.$refs["input-box"].focus();
|
||||
this.message = this.message.trim();
|
||||
if (this.message === this.editMessage.message){
|
||||
if (this.message === this.editMessage.message) {
|
||||
this.$store.dispatch("setEditMessage", null);
|
||||
this.message = "";
|
||||
return;
|
||||
|
|
@ -212,29 +192,33 @@ export default {
|
|||
this.messageLength = 0;
|
||||
|
||||
const msg = emojiParser.replaceShortcode(this.message);
|
||||
this.$store.dispatch('updateMessage', {
|
||||
this.$store.dispatch("updateMessage", {
|
||||
channelID: editMessage.channelID,
|
||||
messageID: editMessage.messageID,
|
||||
message: {message: msg, status: 0}
|
||||
})
|
||||
message: { message: msg, status: 0 }
|
||||
});
|
||||
this.$store.dispatch("setEditMessage", null);
|
||||
this.message = "";
|
||||
|
||||
const {ok, error, result} = await messagesService.update(editMessage.messageID, editMessage.channelID, {
|
||||
message: msg
|
||||
})
|
||||
const { ok, error, result } = await messagesService.update(
|
||||
editMessage.messageID,
|
||||
editMessage.channelID,
|
||||
{
|
||||
message: msg
|
||||
}
|
||||
);
|
||||
if (ok) {
|
||||
this.$store.dispatch('updateMessage', {
|
||||
this.$store.dispatch("updateMessage", {
|
||||
channelID: editMessage.channelID,
|
||||
messageID: editMessage.messageID,
|
||||
message: {status: 1}
|
||||
})
|
||||
message: { status: 1 }
|
||||
});
|
||||
} else {
|
||||
this.$store.dispatch('updateMessage', {
|
||||
this.$store.dispatch("updateMessage", {
|
||||
channelID: editMessage.channelID,
|
||||
messageID: editMessage.messageID,
|
||||
message: {message: msg, status: 2}
|
||||
})
|
||||
message: { message: msg, status: 2 }
|
||||
});
|
||||
}
|
||||
},
|
||||
async postTimer() {
|
||||
|
|
@ -242,14 +226,13 @@ export default {
|
|||
if (this.message.trim() == "") {
|
||||
clearInterval(this.postTimerID);
|
||||
this.postTimerID = null;
|
||||
}else {
|
||||
} else {
|
||||
if (this.selectedChannelID)
|
||||
await typingService.post(this.selectedChannelID);
|
||||
|
||||
if (this.postTimerID)
|
||||
this.postTimer()
|
||||
|
||||
if (this.postTimerID) this.postTimer();
|
||||
}
|
||||
}, 2000)
|
||||
}, 2000);
|
||||
},
|
||||
resize() {
|
||||
let input = this.$refs["input-box"];
|
||||
|
|
@ -259,9 +242,8 @@ export default {
|
|||
} else {
|
||||
input.style.height = "auto";
|
||||
input.style.height = `calc(${input.scrollHeight}px - 1em)`;
|
||||
this.scrollDown();
|
||||
|
||||
}
|
||||
bus.$emit('scrollDown');
|
||||
},
|
||||
emojiSwitchKey(event) {
|
||||
if (!this.emojiArray) return;
|
||||
|
|
@ -347,11 +329,16 @@ export default {
|
|||
},
|
||||
enterEmojiPanel(shortcode) {
|
||||
const target = this.$refs["input-box"];
|
||||
if (!target) return;
|
||||
target.focus();
|
||||
const isSuccessful = document.execCommand("insertText", false, `:${shortcode}: `);
|
||||
const isSuccessful = document.execCommand(
|
||||
"insertText",
|
||||
false,
|
||||
`:${shortcode}: `
|
||||
);
|
||||
|
||||
if (!isSuccessful) {
|
||||
this.message = this.message + `:${shortcode}: `;
|
||||
this.message = this.message + `:${shortcode}: `;
|
||||
}
|
||||
target.blur();
|
||||
this.$store.dispatch("settingsModule/addRecentEmoji", shortcode);
|
||||
|
|
@ -369,17 +356,20 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (this.editMessage) {
|
||||
return this.updateMessage()
|
||||
return this.updateMessage();
|
||||
} else {
|
||||
this.sendMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.keyCode === 38){ //38 = up arrow
|
||||
if (event.keyCode === 38) {
|
||||
//38 = up arrow
|
||||
if (this.message !== "") return;
|
||||
if (this.editMessage) return;
|
||||
const messagesFiltered = this.selectedChannelMessages.filter(m => m.creator.uniqueID === this.user.uniqueID);
|
||||
const messagesFiltered = this.selectedChannelMessages.filter(
|
||||
m => m.creator.uniqueID === this.user.uniqueID
|
||||
);
|
||||
|
||||
if (!messagesFiltered.length) return;
|
||||
event.preventDefault();
|
||||
|
|
@ -389,14 +379,19 @@ export default {
|
|||
channelID: lastMessage.channelID,
|
||||
message: lastMessage.message
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
hideTypingStatus(data) {
|
||||
if (this.user.uniqueID === data.message.creator.uniqueID) return;
|
||||
if (!this.typingRecipients[data.channelID] || !this.typingRecipients[data.channelID][data.message.creator.uniqueID]) return;
|
||||
clearTimeout( this.typingRecipients[data.channelID][data.message.creator.uniqueID].timer );
|
||||
if (
|
||||
!this.typingRecipients[data.channelID] ||
|
||||
!this.typingRecipients[data.channelID][data.message.creator.uniqueID]
|
||||
)
|
||||
return;
|
||||
clearTimeout(
|
||||
this.typingRecipients[data.channelID][data.message.creator.uniqueID]
|
||||
.timer
|
||||
);
|
||||
this.$delete(
|
||||
this.typingRecipients[data.channelID],
|
||||
data.message.creator.uniqueID
|
||||
|
|
@ -456,38 +451,16 @@ export default {
|
|||
});
|
||||
}
|
||||
},
|
||||
scrollEvent(event) {
|
||||
const { currentTarget: { scrollTop, clientHeight, scrollHeight} } = event;
|
||||
this.scrolledDown = Math.abs(scrollHeight - scrollTop - clientHeight) <= 3.0;
|
||||
this.scrolledTop = scrollTop === 0;
|
||||
backToTopButton() {
|
||||
bus.$emit('backToBottom');
|
||||
},
|
||||
scrollDown() {
|
||||
if (!this.scrolledDown) return;
|
||||
const element = this.$refs['msg-logs']
|
||||
if (!element) return;
|
||||
element.scrollTop = element.scrollHeight;
|
||||
},
|
||||
onResize(dimentions) {
|
||||
this.scrollDown();
|
||||
},
|
||||
async loadMoreMessages() {
|
||||
const msgLogs = this.$refs['msg-logs'];
|
||||
const scrollTop = msgLogs.scrollTop;
|
||||
const scrollHeight = msgLogs.scrollHeight;
|
||||
editMessageEvent(editMessage) {
|
||||
this.message = editMessage ? emojiParser.emojiToShortcode(editMessage.message) : '';
|
||||
|
||||
const continueMessageID = this.selectedChannelMessages[0].messageID;
|
||||
|
||||
const {ok, result, error} = await messagesService.get(this.selectedChannelID, continueMessageID)
|
||||
if (ok) {
|
||||
if (!result.data.messages.length) return
|
||||
this.$store.dispatch('addMessages', result.data.messages)
|
||||
this.$nextTick(_ => {
|
||||
msgLogs.scrollTop = msgLogs.scrollHeight - scrollHeight;
|
||||
})
|
||||
}
|
||||
},
|
||||
scrolledUpEvent() {
|
||||
this.loadMoreMessages();
|
||||
onBlur() {
|
||||
clearTimeout(this.postTimerID);
|
||||
this.postTimerID = null;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -520,59 +493,34 @@ export default {
|
|||
2500
|
||||
);
|
||||
};
|
||||
this.scrollDown();
|
||||
|
||||
bus.$on("newMessage", this.hideTypingStatus);
|
||||
bus.$on("emojiSuggestions:Selected", this.enterEmojiSuggestion);
|
||||
bus.$on("emojiPanel:Selected", this.enterEmojiPanel);
|
||||
window.onblur = () => {
|
||||
clearTimeout(this.postTimerID);
|
||||
this.postTimerID = null;
|
||||
}
|
||||
window.addEventListener('focus', this.onFocus)
|
||||
|
||||
bus.$on('scrolledDown', (scrolledDown) => {
|
||||
this.scrolledDown = scrolledDown;
|
||||
})
|
||||
|
||||
window.addEventListener('blur', this.onBlur)
|
||||
window.addEventListener("focus", this.onFocus);
|
||||
},
|
||||
|
||||
|
||||
beforeDestroy() {
|
||||
clearTimeout(this.postTimerID);
|
||||
this.postTimerID = null;
|
||||
|
||||
bus.$off("newMessage", this.hideTypingStatus);
|
||||
bus.$off("emojiSuggestions:Selected", this.enterEmojiSuggestion);
|
||||
bus.$on("emojiPanel:Selected", this.enterEmojiPanel);
|
||||
window.removeEventListener('focus', this.onFocus)
|
||||
window.removeEventListener("focus", this.onFocus);
|
||||
window.removeEventListener("blur", this.onBlur);
|
||||
|
||||
delete this.$options.sockets.typingStatus;
|
||||
},
|
||||
watch: {
|
||||
selectedChannelMessages(newMessages, oldMessages){
|
||||
this.$nextTick(function () {
|
||||
this.scrollDown();
|
||||
})
|
||||
},
|
||||
selectedChannelID(){
|
||||
this.scrolledDown = true;
|
||||
},
|
||||
uploadQueue() {
|
||||
this.$nextTick(function () {
|
||||
this.scrollDown(true);
|
||||
})
|
||||
},
|
||||
editMessage(editMessage) {
|
||||
if (!editMessage) {
|
||||
this.message = ""
|
||||
} else {
|
||||
this.message = emojiParser.emojiToShortcode(editMessage.message)
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.resize();
|
||||
this.scrollDown();
|
||||
})
|
||||
},
|
||||
getWindowWidth(dimentions) {
|
||||
this.onResize();
|
||||
},
|
||||
scrolledTop(scrolledTop) {
|
||||
if (scrolledTop)
|
||||
this.scrolledUpEvent();
|
||||
this.editMessageEvent(editMessage);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -617,37 +565,30 @@ export default {
|
|||
const channel = this.$store.getters.channels[selectedChannel];
|
||||
return channel ? channel.recipients : undefined;
|
||||
},
|
||||
userStatusColor() {
|
||||
const selectedChannel = this.$store.getters.selectedChannelID;
|
||||
const channel = this.$store.getters.channels[selectedChannel];
|
||||
const presences = this.$store.getters['members/presences'];
|
||||
|
||||
let status = 0;
|
||||
if (!channel || !channel.recipients || !channel.recipients.length) {
|
||||
status = 0;
|
||||
} else if (
|
||||
this.$store.getters.user.friends[channel.recipients[0].uniqueID]
|
||||
) {
|
||||
status = presences[channel.recipients[0].uniqueID] || 0;
|
||||
}
|
||||
return statuses[status].color;
|
||||
},
|
||||
editMessage() {
|
||||
let editMessage = this.$store.getters.popouts.editMessage;
|
||||
if (!editMessage) return null;
|
||||
return editMessage;
|
||||
},
|
||||
getWindowWidth() {
|
||||
return {width: windowProperties.resizeWidth, height: windowProperties.resizeHeight};
|
||||
return {
|
||||
width: windowProperties.resizeWidth,
|
||||
height: windowProperties.resizeHeight
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.show-up-enter-active,
|
||||
.show-up-leave-active {
|
||||
transition: 0.3s;
|
||||
}
|
||||
.show-up-enter, .show-up-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
.no-channel-selected {
|
||||
display: flex;
|
||||
|
|
@ -659,19 +600,13 @@ export default {
|
|||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
}
|
||||
.no-channel-selected .message {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.no-channel-selected .material-icons {
|
||||
font-size: 50px;
|
||||
}
|
||||
.channel-selected {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
.message {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.material-icons {
|
||||
font-size: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
|
|
@ -695,11 +630,8 @@ export default {
|
|||
.message-logs {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
}
|
||||
.message-logs,
|
||||
.message-logs .scroll {
|
||||
/* transform: scale(1, -1) translate3d(0,0,0); */
|
||||
margin-right: 5px;
|
||||
margin-right: 2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
|
@ -725,14 +657,16 @@ export default {
|
|||
user-select: none;
|
||||
transition: 0.3s;
|
||||
border-radius: 5px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.322);
|
||||
}
|
||||
.material-icons {
|
||||
color: white;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
.attachment-button:hover {
|
||||
background: rgba(0, 0, 0, 0.322);
|
||||
}
|
||||
.attachment-button .material-icons {
|
||||
color: white;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.chat-input-area .info {
|
||||
color: rgba(255, 255, 255, 0.466);
|
||||
font-size: 12px;
|
||||
|
|
@ -740,15 +674,18 @@ export default {
|
|||
margin-top: 5px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.typing-outer {
|
||||
flex: 1;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.message-count {
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.message-area {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
|
@ -772,14 +709,14 @@ export default {
|
|||
max-height: 30vh;
|
||||
overflow-y: auto;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.chat-input:hover {
|
||||
background: rgba(0, 0, 0, 0.288);
|
||||
}
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.288);
|
||||
}
|
||||
|
||||
.chat-input:focus {
|
||||
background: rgba(0, 0, 0, 0.466);
|
||||
&:focus {
|
||||
background: rgba(0, 0, 0, 0.466);
|
||||
}
|
||||
}
|
||||
|
||||
.send-button {
|
||||
|
|
@ -797,20 +734,22 @@ export default {
|
|||
flex-shrink: 0;
|
||||
border-radius: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
.send-button .material-icons {
|
||||
margin: auto;
|
||||
}
|
||||
.send-button:hover {
|
||||
background: rgba(0, 0, 0, 0.514);
|
||||
}
|
||||
.error-send-button {
|
||||
background-color: rgba(255, 0, 0, 0.294);
|
||||
cursor: pointer;
|
||||
.material-icons {
|
||||
margin: auto;
|
||||
}
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.514);
|
||||
}
|
||||
}
|
||||
|
||||
.error-send-button:hover {
|
||||
.error-send-button {
|
||||
background-color: rgba(255, 0, 0, 0.294);
|
||||
&:hover {
|
||||
background-color: rgba(255, 0, 0, 0.294);
|
||||
}
|
||||
}
|
||||
|
||||
.emojis-button {
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
|
|
@ -818,7 +757,7 @@ export default {
|
|||
border: none;
|
||||
outline: none;
|
||||
margin-left: 2px;
|
||||
|
||||
cursor: pointer;
|
||||
min-height: 40px;
|
||||
width: 50px;
|
||||
transition: 0.3s;
|
||||
|
|
@ -826,12 +765,41 @@ export default {
|
|||
flex-shrink: 0;
|
||||
border-radius: 5px;
|
||||
user-select: none;
|
||||
.material-icons {
|
||||
margin: auto;
|
||||
}
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.514);
|
||||
}
|
||||
}
|
||||
|
||||
.emojis-button .material-icons {
|
||||
margin: auto;
|
||||
}
|
||||
.emojis-button:hover {
|
||||
background: rgba(0, 0, 0, 0.514);
|
||||
.back-to-bottom-button {
|
||||
&:hover {
|
||||
background: rgb(23, 124, 255);
|
||||
box-shadow: 0px 0px 15px 0px #0000008a;
|
||||
}
|
||||
transition: 0.2s;
|
||||
background: rgba(23, 124, 255, 0.818);
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 25px;
|
||||
border-radius: 10px;
|
||||
height: 50px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 0px 7px 0px #0000008a;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
padding-left: 10px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
.material-icons {
|
||||
align-self: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 35px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
<template>
|
||||
<div class="heading">
|
||||
<div
|
||||
class="show-menu-button"
|
||||
@click="toggleLeftMenu"
|
||||
>
|
||||
<div class="show-menu-button" @click="toggleLeftMenu">
|
||||
<i class="material-icons">menu</i>
|
||||
</div>
|
||||
<div
|
||||
v-if="type === 1"
|
||||
class="user-status"
|
||||
:style="`box-shadow: 0px 0px 14px 3px ${statusColor}; background-color: ${statusColor};`"
|
||||
:style="`box-shadow: 0px 0px 14px 3px ${userStatusColor}; background-color: ${userStatusColor};`"
|
||||
/>
|
||||
<div class="information">
|
||||
<div
|
||||
:class="{name: true, clickable: !!uniqueID }"
|
||||
@click="openUserInfoPanel"
|
||||
>
|
||||
{{ name }}
|
||||
</div>
|
||||
<div :class="{name: true, clickable: !!uniqueID }" @click="openUserInfoPanel">{{ name }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="type === 2 && selectedServerID"
|
||||
|
|
@ -31,18 +23,14 @@
|
|||
|
||||
<script>
|
||||
import { bus } from "@/main";
|
||||
import statuses from "@/utils/statuses";
|
||||
export default {
|
||||
props: [
|
||||
"type", // 0: without online status; 1: with online status; 2: server.
|
||||
"statusColor", // only if type is set to 1;
|
||||
"name",
|
||||
"uniqueID"
|
||||
],
|
||||
computed: {
|
||||
selectedServerID() {
|
||||
return this.$store.getters['servers/selectedServerID'];
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
openUserInfoPanel() {
|
||||
if (this.uniqueID)
|
||||
|
|
@ -54,6 +42,26 @@ export default {
|
|||
toggleMembersPanel() {
|
||||
bus.$emit("toggleMembersPanel");
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedServerID() {
|
||||
return this.$store.getters["servers/selectedServerID"];
|
||||
},
|
||||
userStatusColor() {
|
||||
const selectedChannel = this.$store.getters.selectedChannelID;
|
||||
const channel = this.$store.getters.channels[selectedChannel];
|
||||
const presences = this.$store.getters["members/presences"];
|
||||
|
||||
let status = 0;
|
||||
if (!channel || !channel.recipients || !channel.recipients.length) {
|
||||
status = 0;
|
||||
} else if (
|
||||
this.$store.getters.user.friends[channel.recipients[0].uniqueID]
|
||||
) {
|
||||
status = presences[channel.recipients[0].uniqueID] || 0;
|
||||
}
|
||||
return statuses[status].color;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -75,7 +83,7 @@ export default {
|
|||
user-select: none;
|
||||
display: none;
|
||||
}
|
||||
.show-members-button{
|
||||
.show-members-button {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-top: 3px;
|
||||
|
|
@ -127,7 +135,6 @@ export default {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 949px) {
|
||||
.show-members-button {
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ export default {
|
|||
if (!files || files.length === 0 || !files[0].dimensions)
|
||||
return undefined;
|
||||
|
||||
const messageLog = document.querySelector('.scroll');
|
||||
const messageLog = document.querySelector('.message-logs');
|
||||
const w = messageLog.offsetWidth;
|
||||
const h = messageLog.offsetHeight;
|
||||
|
||||
|
|
@ -187,6 +187,9 @@ export default {
|
|||
|
||||
const imageTag = this.$refs['image'];
|
||||
|
||||
imageTag.firstChild.style.width = "100%"
|
||||
imageTag.firstChild.style.height = "100%"
|
||||
|
||||
imageTag.style.width = this.clamp(newDimentions.width, 0, srcWidth) + "px"
|
||||
imageTag.style.height = this.clamp(newDimentions.height, 0, srcHeight) + "px"
|
||||
},
|
||||
|
|
@ -425,8 +428,10 @@ export default {
|
|||
flex-direction: column;
|
||||
}
|
||||
.image-content img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100px;
|
||||
object-fit: contain;
|
||||
height: 100px;
|
||||
|
||||
}
|
||||
.image-content:hover img {
|
||||
filter: brightness(70%);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="content">
|
||||
<errors-list-template :errors="errors" v-if="errors" />
|
||||
<div class="content-inner">
|
||||
<div class="content-inner" :key="key">
|
||||
<div class="top">
|
||||
<profile-picture
|
||||
class="server-avatar"
|
||||
|
|
@ -65,7 +65,8 @@ export default {
|
|||
changed: false,
|
||||
errors: null,
|
||||
avatarDomain: config.domain + "/avatars/",
|
||||
update: {}
|
||||
update: {},
|
||||
key: 1,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -93,6 +94,7 @@ export default {
|
|||
this.requestSent = false;
|
||||
return;
|
||||
}
|
||||
this.key = Math.random();
|
||||
this.update = {};
|
||||
this.requestSent = false;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<errors-list-template :errors="errors" v-if="errors" />
|
||||
<div class="inner-content">
|
||||
<div class="left">
|
||||
<form>
|
||||
<form :key="key">
|
||||
<div class="outer-input">
|
||||
<div class="title">Username</div>
|
||||
<div class="user-tag">
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
<div class="outer-input">
|
||||
<div class="title">Current Password</div>
|
||||
<input type="password" autocomplete="new-password" @input="inputEvent('password', $event)" />
|
||||
<input type="password" autocomplete="new-password" ref="passwordInput" @input="inputEvent('password', $event)" />
|
||||
</div>
|
||||
<div class="link" v-if="!resetPassword" @click="resetPassword = true">Reset Password</div>
|
||||
<div class="outer-input" v-if="resetPassword">
|
||||
|
|
@ -68,7 +68,8 @@ export default {
|
|||
requestSent: false,
|
||||
changed: false,
|
||||
resetPassword: false,
|
||||
update: {}
|
||||
update: {},
|
||||
key: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -121,8 +122,10 @@ export default {
|
|||
}
|
||||
this.errors = data.errors;
|
||||
} else {
|
||||
this.$refs['passwordInput'].value = "";
|
||||
this.resetPassword = false
|
||||
this.update = {};
|
||||
this.$set(this, 'update', {})
|
||||
this.key = Math.random();
|
||||
}
|
||||
this.requestSent = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default {
|
|||
return undefined;
|
||||
|
||||
const embed = this.$refs['embed'];
|
||||
const messageLog = document.querySelector('.scroll');
|
||||
const messageLog = document.querySelector('.message-logs');
|
||||
const w = messageLog.offsetWidth;
|
||||
const h = messageLog.offsetHeight;
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ export default {
|
|||
imageURL() {
|
||||
const image = this.embed.image;
|
||||
if (!image) return undefined;
|
||||
if (typeof image === 'string') return image;
|
||||
if (typeof image === 'string') return undefined;
|
||||
if (image.url) return image.url;
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,16 @@ import channelService from "@/services/channelService";
|
|||
import messagesService from "@/services/messagesService";
|
||||
|
||||
const state = {
|
||||
messages: {}
|
||||
messages: {},
|
||||
scrollPosition: {}
|
||||
};
|
||||
|
||||
const getters = {
|
||||
messages(state) {
|
||||
return state.messages;
|
||||
},
|
||||
scrollPosition(state) {
|
||||
return state.scrollPosition
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -103,6 +107,14 @@ const actions = {
|
|||
return true;
|
||||
}
|
||||
})
|
||||
},
|
||||
changeScrollPosition(context, {channelID, pos}) {
|
||||
context.commit('changeScrollPosition', {channelID, pos})
|
||||
},
|
||||
unloadTopMessages(context, {channelID}) {
|
||||
const messages = context.state.messages[channelID];
|
||||
const unloaded = messages.slice(Math.max(messages.length - 50, 0))
|
||||
context.commit('messages', {channelID, messages: unloaded})
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -127,6 +139,9 @@ async function getMessages(context, channelID, isServerChannel) {
|
|||
|
||||
|
||||
const mutations = {
|
||||
changeScrollPosition(state, {channelID, pos}) {
|
||||
Vue.set(state.scrollPosition, channelID, pos);
|
||||
},
|
||||
deleteMessage(state, {channelID, index}) {
|
||||
Vue.delete(state.messages[channelID], index)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ const config = [
|
|||
version: 6.1,
|
||||
title: "Download button, bug fixes",
|
||||
shortTitle: "",
|
||||
date: "13/08/2019",
|
||||
headColor: "rgba(205, 80, 87, 0.77)",
|
||||
date: "16/08/2019",
|
||||
headColor: "rgba(25, 300, 87, 0.77)",
|
||||
new: [
|
||||
"Added download button.",
|
||||
|
||||
"Scroll up to load more messages.",
|
||||
"Scroll to bottom button has been added."
|
||||
],
|
||||
fix: [
|
||||
"Fixed emoji size (2emx2em).",
|
||||
|
|
|
|||
Loading…
Reference in a new issue