-
+
+
+
+
@@ -52,10 +54,14 @@
v-model="message"
@paste="onPaste"
>
+
@@ -85,6 +91,7 @@ import Spinner from "@/components/Spinner.vue";
import TypingStatus from "@/components/app/TypingStatus.vue";
import uploadsQueue from "@/components/app/uploadsQueue.vue";
import emojiSuggestions from "@/components/app/emojiSuggestions.vue";
+import emojiPanel from "@/components/app/emojiPanel.vue";
import emojiParser from "@/utils/emojiParser.js";
export default {
@@ -94,7 +101,8 @@ export default {
News,
TypingStatus,
uploadsQueue,
- emojiSuggestions
+ emojiSuggestions,
+ emojiPanel
},
data() {
return {
@@ -103,7 +111,8 @@ export default {
postTimerID: null,
getTimerID: null,
typing: false,
- whosTyping: ""
+ whosTyping: "",
+ showEmojiPanel: false
};
},
methods: {
@@ -267,7 +276,12 @@ export default {
const end = cursorPosition;
this.message = this.message.substring(0, start) + emojiShortCode + this.message.substring(end);
- return (this.$store.dispatch('setEmojiArray', null));
+ this.$store.dispatch('setEmojiArray', null);
+ },
+ enterEmojiPanel(shortcode){
+ const target = this.$refs["input-box"];
+ target.focus();
+ document.execCommand('insertText', false, `:${shortcode}:`);
},
keyDown(event) {
this.resize(event);
@@ -353,6 +367,7 @@ export default {
};
bus.$on("newMessage", this.hideTypingStatus);
bus.$on("emojiSuggestions:Selected", this.enterEmojiSuggestion)
+ bus.$on("emojiPanel:Selected", this.enterEmojiPanel)
//dismiss notification on focus
window.onfocus = () => {
bus.$emit("title:change", "Nertivia");
@@ -370,6 +385,7 @@ export default {
beforeDestroy() {
bus.$off("newMessage", this.hideTypingStatus);
bus.$off("emojiSuggestions:Selected", this.enterEmojiSuggestion)
+ bus.$on("emojiPanel:Selected", this.enterEmojiPanel)
delete this.$options.sockets.typingStatus;
},
computed: {
@@ -442,9 +458,6 @@ export default {
display: flex;
flex-shrink: 0;
}
-.emoji-suggestion-outer {
- position: relative;
-}
.show-menu-button {
display: inline-block;
margin: auto;
@@ -506,6 +519,7 @@ export default {
cursor: default;
user-select: none;
transition: 0.3s;
+ border-radius: 5px;
}
.attachment-button:hover {
background: rgba(0, 0, 0, 0.322);
@@ -553,6 +567,7 @@ export default {
overflow: hidden;
max-height: 30vh;
overflow-y: auto;
+ border-radius: 5px;
}
.chat-input:hover {
@@ -576,6 +591,8 @@ export default {
transition: 0.3s;
display: flex;
flex-shrink: 0;
+ border-radius: 5px;
+ user-select: none;
}
.send-button .material-icons {
margin: auto;
@@ -590,6 +607,29 @@ export default {
.error-send-button:hover {
background-color: rgba(255, 0, 0, 0.294);
}
+.emojis-button{
+ font-size: 20px;
+ color: white;
+ background: rgba(0, 0, 0, 0.274);
+ border: none;
+ outline: none;
+ margin-left: 2px;
+
+ min-height: 40px;
+ width: 50px;
+ transition: 0.3s;
+ display: flex;
+ flex-shrink: 0;
+ border-radius: 5px;
+ user-select: none;
+}
+
+.emojis-button .material-icons {
+ margin: auto;
+}
+.emojis-button:hover {
+ background: rgba(0, 0, 0, 0.514);
+}
@media (max-width: 600px) {
.show-menu-button {
display: block;
diff --git a/src/components/app/emojiPanel.vue b/src/components/app/emojiPanel.vue
new file mode 100644
index 0000000..0541b06
--- /dev/null
+++ b/src/components/app/emojiPanel.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+
{{group}}
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/directives/LazyLoad.js b/src/directives/LazyLoad.js
new file mode 100644
index 0000000..7c6edcf
--- /dev/null
+++ b/src/directives/LazyLoad.js
@@ -0,0 +1,49 @@
+export default {
+ inserted: el => {
+ function loadImage() {
+ const imageElement = el
+ if (imageElement) {
+ imageElement.addEventListener("load", () => {
+ setTimeout(() => el.classList.add("loaded"), 100);
+ });
+ imageElement.addEventListener("error", () => console.log("error"));
+ imageElement.src = imageElement.dataset.url;
+ }
+ }
+
+ function handleIntersect(entries, observer) {
+ entries.forEach(entry => {
+ if (!entry.isIntersecting) {
+ return;
+ } else {
+ loadImage();
+ observer.unobserve(el);
+ }
+ });
+ }
+
+ function createObserver() {
+ const options = {
+ // circumstances under which the observer's callback is invoked
+ root: null, // defaults to the browser viewport if not specified or if null
+ threshold: "0" // the degree of intersection between the target element and its root (0 - 1)
+ // threshold of 1.0 means that when 100% of the target is visible within
+ //the element specified by the root option, the callback is invoked
+ };
+
+ // Whether you're using the viewport or some other element as the root,the API works the same way,
+ // executing a callback function you provide whenever the visibility of the target element changes
+ // so that it crosses desired amounts of intersection with the root
+
+ const observer = new IntersectionObserver(handleIntersect, options);
+
+ observer.observe(el); // target element to watch
+ }
+
+ if (!window["IntersectionObserver"]) {
+ loadImage();
+ } else {
+ createObserver();
+ }
+ }
+};
diff --git a/src/utils/changelog.js b/src/utils/changelog.js
index 2ed735d..2e8c097 100644
--- a/src/utils/changelog.js
+++ b/src/utils/changelog.js
@@ -1,8 +1,24 @@
const config = [
+ {
+ title: 'Emojis :D',
+ shortTitle: 'Emojis',
+ date: '20/03/2019',
+ headColor: "rgba(17, 153, 69, 0.87)",
+ new: [
+ 'Emoji suggestions in chat when typing in any emoji :ok_hand:',
+ 'Emoji picker',
+ 'Removed planned features from changelog'
+ ],
+ next: [
+ 'make tabs in emoji panel',
+ 'Custom emojis for freeeee!',
+ ]
+ },
{
title: 'Upload anything!',
shortTitle: 'Upload anything!',
date: '08/03/2019',
+ headColor: "rgba(38, 139, 255, 0.87)",
new: [
'You can now upload any kind of files to friends. (Google drive required)',
'Shift + enter should expand the text area.',
diff --git a/src/utils/emojiParser.js b/src/utils/emojiParser.js
index 5c313df..9dfce6b 100644
--- a/src/utils/emojiParser.js
+++ b/src/utils/emojiParser.js
@@ -23,7 +23,15 @@ export default {
return require("twemoji/2/svg/" + icon + ".svg")
})
},
-
+ GetEmojiPath: (string) => {
+ let emojiPath;
+ twemoji.parse(string,
+ function (icon, options, variant) {
+ if (!icon) return string;
+ emojiPath = require("twemoji/2/svg/" + icon + ".svg")
+ })
+ return emojiPath;
+ },
searchEmoji: (shortCode) => {
return matchSorter(emojis, shortCode, {keys: ['shortcodes']});
}