Fix emoji picker
This commit is contained in:
parent
bde99dc242
commit
d766f9a0e3
7 changed files with 124 additions and 45 deletions
16
src/assets/css/vendors/_v-emoji-picker.scss
vendored
16
src/assets/css/vendors/_v-emoji-picker.scss
vendored
|
|
@ -1,9 +1,19 @@
|
||||||
#EmojiPicker {
|
.v3-emoji-picker {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
|
box-shadow: none;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
|
||||||
.container-emoji {
|
.v3-emojis button {
|
||||||
height: 60vh;
|
@media #{map-get($display-breakpoints, 'sm')} {
|
||||||
|
flex-basis: 10% !important;
|
||||||
|
max-width: 10% !important;
|
||||||
|
}
|
||||||
|
@media #{map-get($display-breakpoints, 'md-and-up')} {
|
||||||
|
flex-basis: 6.25% !important;
|
||||||
|
max-width: 6.25% !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
src/assets/icons/ic_timer.svg
Normal file
34
src/assets/icons/ic_timer.svg
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M1.08333 5.77777H0.361111C0.161778 5.77777 0 5.93955 0 6.13888C0 6.33822 0.161778 6.49999 0.361111 6.49999H1.08333C1.28267 6.49999 1.44444 6.33822 1.44444 6.13888C1.44444 5.93955 1.28267 5.77777 1.08333 5.77777Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1.08333 5.77777H0.361111C0.161778 5.77777 0 5.93955 0 6.13888C0 6.33822 0.161778 6.49999 0.361111 6.49999H1.08333C1.28267 6.49999 1.44444 6.33822 1.44444 6.13888C1.44444 5.93955 1.28267 5.77777 1.08333 5.77777Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1.08333 8.66669H0.361111C0.161778 8.66669 0 8.82846 0 9.0278C0 9.22713 0.161778 9.38891 0.361111 9.38891H1.08333C1.28267 9.38891 1.44444 9.22713 1.44444 9.0278C1.44444 8.82846 1.28267 8.66669 1.08333 8.66669Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M1.08333 8.66669H0.361111C0.161778 8.66669 0 8.82846 0 9.0278C0 9.22713 0.161778 9.38891 0.361111 9.38891H1.08333C1.28267 9.38891 1.44444 9.22713 1.44444 9.0278C1.44444 8.82846 1.28267 8.66669 1.08333 8.66669Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M11.6553 4.02206L12.1724 3.50494C12.3132 3.36411 12.3132 3.13517 12.1724 2.99433C12.0316 2.8535 11.8026 2.8535 11.6618 2.99433L11.1447 3.51144C10.2766 2.75239 9.1658 2.26633 7.94453 2.18472V0.722222H9.02786C9.22719 0.722222 9.38897 0.560444 9.38897 0.361111C9.38897 0.161778 9.22719 0 9.02786 0H6.13897C5.93964 0 5.77786 0.161778 5.77786 0.361111C5.77786 0.560444 5.93964 0.722222 6.13897 0.722222H7.2223V2.18472C4.40419 2.37178 2.16675 4.71828 2.16675 7.58333C2.16675 10.5704 4.5963 13 7.58341 13C10.5705 13 13.0001 10.5704 13.0001 7.58333C13.0001 6.21978 12.4895 4.97611 11.6553 4.02206ZM7.58341 12.2778C4.99497 12.2778 2.88897 10.1718 2.88897 7.58333C2.88897 4.99489 4.99497 2.88889 7.58341 2.88889C10.1719 2.88889 12.2779 4.99489 12.2779 7.58333C12.2779 10.1718 10.1719 12.2778 7.58341 12.2778Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M11.6553 4.02206L12.1724 3.50494C12.3132 3.36411 12.3132 3.13517 12.1724 2.99433C12.0316 2.8535 11.8026 2.8535 11.6618 2.99433L11.1447 3.51144C10.2766 2.75239 9.1658 2.26633 7.94453 2.18472V0.722222H9.02786C9.22719 0.722222 9.38897 0.560444 9.38897 0.361111C9.38897 0.161778 9.22719 0 9.02786 0H6.13897C5.93964 0 5.77786 0.161778 5.77786 0.361111C5.77786 0.560444 5.93964 0.722222 6.13897 0.722222H7.2223V2.18472C4.40419 2.37178 2.16675 4.71828 2.16675 7.58333C2.16675 10.5704 4.5963 13 7.58341 13C10.5705 13 13.0001 10.5704 13.0001 7.58333C13.0001 6.21978 12.4895 4.97611 11.6553 4.02206ZM7.58341 12.2778C4.99497 12.2778 2.88897 10.1718 2.88897 7.58333C2.88897 4.99489 4.99497 2.88889 7.58341 2.88889C10.1719 2.88889 12.2779 4.99489 12.2779 7.58333C12.2779 10.1718 10.1719 12.2778 7.58341 12.2778Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M7.58328 4.33331C7.38395 4.33331 7.22217 4.49509 7.22217 4.69442V7.58331C7.22217 7.78265 7.38395 7.94442 7.58328 7.94442C7.78261 7.94442 7.94439 7.78265 7.94439 7.58331V4.69442C7.94439 4.49509 7.78261 4.33331 7.58328 4.33331Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M7.58328 4.33331C7.38395 4.33331 7.22217 4.49509 7.22217 4.69442V7.58331C7.22217 7.78265 7.38395 7.94442 7.58328 7.94442C7.78261 7.94442 7.94439 7.78265 7.94439 7.58331V4.69442C7.94439 4.49509 7.78261 4.33331 7.58328 4.33331Z"
|
||||||
|
fill="black"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
|
|
@ -305,7 +305,14 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MessageOperationsBottomSheet ref="messageOperationsSheet">
|
<MessageOperationsBottomSheet ref="messageOperationsSheet">
|
||||||
<EmojiPicker ref="emojiPicker" @select="emojiSelected" :i18n="i18nEmoji"/>
|
<EmojiPicker ref="emojiPicker"
|
||||||
|
@select="emojiSelected"
|
||||||
|
:additional-groups="additionalEmojiGroups"
|
||||||
|
:group-names="emojiGroupNames"
|
||||||
|
:group-icons="additionalEmojiGroupIcons"
|
||||||
|
:group-order="['recently_used']"
|
||||||
|
disable-skin-tones
|
||||||
|
:static-texts="{ placeholder: $t('emoji.search')}"/>
|
||||||
</MessageOperationsBottomSheet>
|
</MessageOperationsBottomSheet>
|
||||||
|
|
||||||
<StickerPickerBottomSheet ref="stickerPickerSheet" v-on:selectSticker="sendSticker" />
|
<StickerPickerBottomSheet ref="stickerPickerSheet" v-on:selectSticker="sendSticker" />
|
||||||
|
|
@ -358,6 +365,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
||||||
|
import { toRaw } from "vue";
|
||||||
import util, { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE, ROOM_TYPE_CHANNEL } from "../plugins/utils";
|
import util, { ROOM_TYPE_VOICE_MODE, ROOM_TYPE_FILE_MODE, ROOM_TYPE_CHANNEL } from "../plugins/utils";
|
||||||
import MessageOperations from "./messages/MessageOperations.vue";
|
import MessageOperations from "./messages/MessageOperations.vue";
|
||||||
import ChatHeader from "./ChatHeader";
|
import ChatHeader from "./ChatHeader";
|
||||||
|
|
@ -388,8 +396,10 @@ import { imageSize } from "image-size";
|
||||||
import prettyBytes from "pretty-bytes";
|
import prettyBytes from "pretty-bytes";
|
||||||
import RoomExport from "./RoomExport.vue";
|
import RoomExport from "./RoomExport.vue";
|
||||||
import EmojiPicker from 'vue3-emoji-picker';
|
import EmojiPicker from 'vue3-emoji-picker';
|
||||||
|
import 'vue3-emoji-picker/css';
|
||||||
import emitter from 'tiny-emitter/instance';
|
import emitter from 'tiny-emitter/instance';
|
||||||
import { markRaw } from "vue";
|
import { markRaw } from "vue";
|
||||||
|
import timerIcon from '@/assets/icons/ic_timer.svg';
|
||||||
|
|
||||||
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
|
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
|
||||||
const WINDOW_BUFFER_SIZE = 0.3; /** Relative window height of when we start paginating. Always keep this much loaded before and after our scroll position! */
|
const WINDOW_BUFFER_SIZE = 0.3; /** Relative window height of when we start paginating. Always keep this much loaded before and after our scroll position! */
|
||||||
|
|
@ -512,19 +522,16 @@ export default {
|
||||||
opStyle: "",
|
opStyle: "",
|
||||||
|
|
||||||
isEmojiQuickReaction: true,
|
isEmojiQuickReaction: true,
|
||||||
i18nEmoji: {
|
emojiGroupNames: {
|
||||||
search: this.$t("emoji.search"),
|
"smileys_people": this.$t("emoji.categories.peoples"),
|
||||||
categories: {
|
"animals_nature": this.$t("emoji.categories.nature"),
|
||||||
Activity: this.$t("emoji.categories.activity"),
|
"food_drink": this.$t("emoji.categories.foods"),
|
||||||
Flags: this.$t("emoji.categories.flags"),
|
"activities": this.$t("emoji.categories.activity"),
|
||||||
Foods: this.$t("emoji.categories.foods"),
|
"travel_places": this.$t("emoji.categories.places"),
|
||||||
Frequently: this.$t("emoji.categories.frequently"),
|
"objects": this.$t("emoji.categories.objects"),
|
||||||
Objects: this.$t("emoji.categories.objects"),
|
"symbols": this.$t("emoji.categories.symbols"),
|
||||||
Nature: this.$t("emoji.categories.nature"),
|
"flags": this.$t("emoji.categories.flags"),
|
||||||
Peoples: this.$t("emoji.categories.peoples"),
|
"recently_used": this.$t("emoji.categories.frequently"),
|
||||||
Symbols: this.$t("emoji.categories.symbols"),
|
|
||||||
Places: this.$t("emoji.categories.places")
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -570,6 +577,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
additionalEmojiGroups() {
|
||||||
|
return { 'recently_used': this.recentEmojis }
|
||||||
|
},
|
||||||
|
additionalEmojiGroupIcons() {
|
||||||
|
return { 'recently_used': timerIcon }
|
||||||
|
},
|
||||||
latestReply() {
|
latestReply() {
|
||||||
const contents = this.replyToEvent ? this.replyToEvent.getContent().body : "";
|
const contents = this.replyToEvent ? this.replyToEvent.getContent().body : "";
|
||||||
const contentArr = contents.split("\n").reverse();
|
const contentArr = contents.split("\n").reverse();
|
||||||
|
|
@ -1229,7 +1242,6 @@ export default {
|
||||||
* Triggered when our "long tap" timer hits.
|
* Triggered when our "long tap" timer hits.
|
||||||
*/
|
*/
|
||||||
touchTimerElapsed() {
|
touchTimerElapsed() {
|
||||||
this.updateRecentEmojis();
|
|
||||||
this.showContextMenu = true;
|
this.showContextMenu = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1817,14 +1829,25 @@ export default {
|
||||||
if (this.selectedEvent) {
|
if (this.selectedEvent) {
|
||||||
const event = this.selectedEvent;
|
const event = this.selectedEvent;
|
||||||
this.selectedEvent = null;
|
this.selectedEvent = null;
|
||||||
this.sendQuickReaction({ reaction: e.data, event: event });
|
this.sendQuickReaction({ reaction: e.i, event: event });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// When text input emoji picker is clicked
|
// When text input emoji picker is clicked
|
||||||
this.currentInput = `${this.currentInput} ${e.data}`;
|
this.currentInput = `${this.currentInput} ${e.i}`;
|
||||||
this.$refs.messageInput.focus();
|
this.$refs.messageInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emojis = this.recentEmojis;
|
||||||
|
const existingIdx = emojis.findIndex(emoji => emoji.u == e.u);
|
||||||
|
if (existingIdx >= 0) {
|
||||||
|
emojis.splice(existingIdx, 1);
|
||||||
|
}
|
||||||
|
emojis.splice(0, 0, markRaw(e));
|
||||||
|
if (emojis.length > 5) {
|
||||||
|
emojis.splice(5, emojis.length - 5);
|
||||||
|
}
|
||||||
|
this.recentEmojis = emojis;
|
||||||
|
|
||||||
this.showEmojiPicker = false;
|
this.showEmojiPicker = false;
|
||||||
this.$refs.messageOperationsSheet.close();
|
this.$refs.messageOperationsSheet.close();
|
||||||
},
|
},
|
||||||
|
|
@ -1895,7 +1918,6 @@ export default {
|
||||||
this.showContextMenu = false;
|
this.showContextMenu = false;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.selectedEvent = event;
|
this.selectedEvent = event;
|
||||||
this.updateRecentEmojis();
|
|
||||||
this.showContextMenuAnchor = e.anchor;
|
this.showContextMenuAnchor = e.anchor;
|
||||||
this.showContextMenu = true;
|
this.showContextMenu = true;
|
||||||
})
|
})
|
||||||
|
|
@ -2033,20 +2055,6 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateRecentEmojis() {
|
|
||||||
if (this.$refs.emojiPicker) {
|
|
||||||
this.recentEmojis = this.$refs.emojiPicker.mapEmojis["Frequently"];
|
|
||||||
if (this.recentEmojis.length < 20) {
|
|
||||||
let peoples = this.$refs.emojiPicker.mapEmojis["Peoples"];
|
|
||||||
for (var p of peoples) {
|
|
||||||
this.recentEmojis.push(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.recentEmojis = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
formatBytes(bytes) {
|
formatBytes(bytes) {
|
||||||
return prettyBytes(bytes);
|
return prettyBytes(bytes);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ export default {
|
||||||
}
|
}
|
||||||
.card {
|
.card {
|
||||||
padding: 0px !important;
|
padding: 0px !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
&[data-state="half"] {
|
&[data-state="half"] {
|
||||||
top: 100px !important;
|
top: 100px !important;
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ import ReadMarker from "./messages/ReadMarker.vue";
|
||||||
import roomDisplayOptionsMixin from "./roomDisplayOptionsMixin";
|
import roomDisplayOptionsMixin from "./roomDisplayOptionsMixin";
|
||||||
import roomTypeMixin from "./roomTypeMixin";
|
import roomTypeMixin from "./roomTypeMixin";
|
||||||
|
|
||||||
export const ROOM_READ_MARKER_EVENT_PLACEHOLDER = { getId: () => "ROOM_READ_MARKER" };
|
export const ROOM_READ_MARKER_EVENT_PLACEHOLDER = { getId: () => "ROOM_READ_MARKER", getTs: () => Date.now() };
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [ roomDisplayOptionsMixin, roomTypeMixin ],
|
mixins: [ roomDisplayOptionsMixin, roomTypeMixin ],
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="{'message-operations':true,'incoming':incoming,'outgoing':!incoming}">
|
<div :class="{'message-operations':true,'incoming':incoming,'outgoing':!incoming}">
|
||||||
<template v-for="(item,index) in getEmojis" :key="item.data">
|
<template v-for="(item,index) in getEmojis" :key="item.i">
|
||||||
<v-btn v-if="userCanSendReactionAndAnswerPoll && index < maxRecents" id="btn-quick-reaction" icon @click.stop="addQuickReaction(item.data)" class="ma-0 pa-0" density="compact">
|
<v-btn v-if="userCanSendReactionAndAnswerPoll && index < maxRecents" id="btn-quick-reaction" icon @click.stop="addQuickReaction(item.i)" class="ma-0 pa-0" density="compact">
|
||||||
<span class="recent-emoji">{{ item.data }}</span>
|
<span class="recent-emoji">{{ item.i }}</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-btn v-if="userCanSendReactionAndAnswerPoll" id="btn-more" icon @click.stop="more" class="ma-0 pa-0">
|
<v-btn v-if="userCanSendReactionAndAnswerPoll" id="btn-more" icon @click.stop="more" class="ma-0 pa-0">
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ import aesjs from "aes-js";
|
||||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||||
import duration from "dayjs/plugin/duration";
|
import duration from "dayjs/plugin/duration";
|
||||||
import i18n from "./lang";
|
import i18n from "./lang";
|
||||||
|
import {
|
||||||
|
toRaw,
|
||||||
|
isRef,
|
||||||
|
isReactive,
|
||||||
|
isProxy,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
export const STATE_EVENT_ROOM_DELETION_NOTICE = "im.keanu.room_deletion_notice";
|
export const STATE_EVENT_ROOM_DELETION_NOTICE = "im.keanu.room_deletion_notice";
|
||||||
export const STATE_EVENT_ROOM_DELETED = "im.keanu.room_deleted";
|
export const STATE_EVENT_ROOM_DELETED = "im.keanu.room_deleted";
|
||||||
|
|
@ -783,9 +789,9 @@ class Util {
|
||||||
getDefaultAvatars() {
|
getDefaultAvatars() {
|
||||||
var images = [];
|
var images = [];
|
||||||
const modules = import.meta.glob("@/assets/avatars/*.{jpeg,jpg,png}", {
|
const modules = import.meta.glob("@/assets/avatars/*.{jpeg,jpg,png}", {
|
||||||
query: '?url',
|
query: "?url",
|
||||||
import: 'default',
|
import: "default",
|
||||||
eager: true
|
eager: true,
|
||||||
});
|
});
|
||||||
Object.keys(modules).map((path) => {
|
Object.keys(modules).map((path) => {
|
||||||
var name = path.split("_")[1];
|
var name = path.split("_")[1];
|
||||||
|
|
@ -1180,7 +1186,7 @@ class Util {
|
||||||
* Possibly convert numerals to local representation (currently only for "bo" locale)
|
* Possibly convert numerals to local representation (currently only for "bo" locale)
|
||||||
* @param str String in which to convert numerals [0-9]
|
* @param str String in which to convert numerals [0-9]
|
||||||
* @returns converted string
|
* @returns converted string
|
||||||
*/
|
*/
|
||||||
toLocalNumbers = (str) => {
|
toLocalNumbers = (str) => {
|
||||||
if (i18n.locale == "my") {
|
if (i18n.locale == "my") {
|
||||||
// Translate to burmese numerals
|
// Translate to burmese numerals
|
||||||
|
|
@ -1210,5 +1216,24 @@ class Util {
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
deepToRaw(sourceObj) {
|
||||||
|
const objectIterator = (input) => {
|
||||||
|
if (Array.isArray(input)) {
|
||||||
|
return input.map((item) => objectIterator(item));
|
||||||
|
}
|
||||||
|
if (isRef(input) || isReactive(input) || isProxy(input)) {
|
||||||
|
return objectIterator(toRaw(input));
|
||||||
|
}
|
||||||
|
if (input && typeof input === "object") {
|
||||||
|
return Object.keys(input).reduce((acc, key) => {
|
||||||
|
acc[key] = objectIterator(input[key]);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
};
|
||||||
|
return objectIterator(sourceObj);
|
||||||
|
}
|
||||||
|
};
|
||||||
export default new Util();
|
export default new Util();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue