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%;
|
||||
background-color: #ffffff;
|
||||
margin-top: 15px;
|
||||
box-shadow: none;
|
||||
height: 100%;
|
||||
flex: 1 1 100%;
|
||||
|
||||
.container-emoji {
|
||||
height: 60vh;
|
||||
.v3-emojis button {
|
||||
@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>
|
||||
|
||||
<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>
|
||||
|
||||
<StickerPickerBottomSheet ref="stickerPickerSheet" v-on:selectSticker="sendSticker" />
|
||||
|
|
@ -358,6 +365,7 @@
|
|||
|
||||
<script>
|
||||
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 MessageOperations from "./messages/MessageOperations.vue";
|
||||
import ChatHeader from "./ChatHeader";
|
||||
|
|
@ -388,8 +396,10 @@ import { imageSize } from "image-size";
|
|||
import prettyBytes from "pretty-bytes";
|
||||
import RoomExport from "./RoomExport.vue";
|
||||
import EmojiPicker from 'vue3-emoji-picker';
|
||||
import 'vue3-emoji-picker/css';
|
||||
import emitter from 'tiny-emitter/instance';
|
||||
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 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: "",
|
||||
|
||||
isEmojiQuickReaction: true,
|
||||
i18nEmoji: {
|
||||
search: this.$t("emoji.search"),
|
||||
categories: {
|
||||
Activity: this.$t("emoji.categories.activity"),
|
||||
Flags: this.$t("emoji.categories.flags"),
|
||||
Foods: this.$t("emoji.categories.foods"),
|
||||
Frequently: this.$t("emoji.categories.frequently"),
|
||||
Objects: this.$t("emoji.categories.objects"),
|
||||
Nature: this.$t("emoji.categories.nature"),
|
||||
Peoples: this.$t("emoji.categories.peoples"),
|
||||
Symbols: this.$t("emoji.categories.symbols"),
|
||||
Places: this.$t("emoji.categories.places")
|
||||
}
|
||||
emojiGroupNames: {
|
||||
"smileys_people": this.$t("emoji.categories.peoples"),
|
||||
"animals_nature": this.$t("emoji.categories.nature"),
|
||||
"food_drink": this.$t("emoji.categories.foods"),
|
||||
"activities": this.$t("emoji.categories.activity"),
|
||||
"travel_places": this.$t("emoji.categories.places"),
|
||||
"objects": this.$t("emoji.categories.objects"),
|
||||
"symbols": this.$t("emoji.categories.symbols"),
|
||||
"flags": this.$t("emoji.categories.flags"),
|
||||
"recently_used": this.$t("emoji.categories.frequently"),
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -570,6 +577,12 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
additionalEmojiGroups() {
|
||||
return { 'recently_used': this.recentEmojis }
|
||||
},
|
||||
additionalEmojiGroupIcons() {
|
||||
return { 'recently_used': timerIcon }
|
||||
},
|
||||
latestReply() {
|
||||
const contents = this.replyToEvent ? this.replyToEvent.getContent().body : "";
|
||||
const contentArr = contents.split("\n").reverse();
|
||||
|
|
@ -1229,7 +1242,6 @@ export default {
|
|||
* Triggered when our "long tap" timer hits.
|
||||
*/
|
||||
touchTimerElapsed() {
|
||||
this.updateRecentEmojis();
|
||||
this.showContextMenu = true;
|
||||
},
|
||||
|
||||
|
|
@ -1817,14 +1829,25 @@ export default {
|
|||
if (this.selectedEvent) {
|
||||
const event = this.selectedEvent;
|
||||
this.selectedEvent = null;
|
||||
this.sendQuickReaction({ reaction: e.data, event: event });
|
||||
this.sendQuickReaction({ reaction: e.i, event: event });
|
||||
}
|
||||
} else {
|
||||
// When text input emoji picker is clicked
|
||||
this.currentInput = `${this.currentInput} ${e.data}`;
|
||||
this.currentInput = `${this.currentInput} ${e.i}`;
|
||||
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.$refs.messageOperationsSheet.close();
|
||||
},
|
||||
|
|
@ -1895,7 +1918,6 @@ export default {
|
|||
this.showContextMenu = false;
|
||||
this.$nextTick(() => {
|
||||
this.selectedEvent = event;
|
||||
this.updateRecentEmojis();
|
||||
this.showContextMenuAnchor = e.anchor;
|
||||
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) {
|
||||
return prettyBytes(bytes);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ export default {
|
|||
}
|
||||
.card {
|
||||
padding: 0px !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&[data-state="half"] {
|
||||
top: 100px !important;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ import ReadMarker from "./messages/ReadMarker.vue";
|
|||
import roomDisplayOptionsMixin from "./roomDisplayOptionsMixin";
|
||||
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 {
|
||||
mixins: [ roomDisplayOptionsMixin, roomTypeMixin ],
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div :class="{'message-operations':true,'incoming':incoming,'outgoing':!incoming}">
|
||||
<template v-for="(item,index) in getEmojis" :key="item.data">
|
||||
<v-btn v-if="userCanSendReactionAndAnswerPoll && index < maxRecents" id="btn-quick-reaction" icon @click.stop="addQuickReaction(item.data)" class="ma-0 pa-0" density="compact">
|
||||
<span class="recent-emoji">{{ item.data }}</span>
|
||||
<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.i)" class="ma-0 pa-0" density="compact">
|
||||
<span class="recent-emoji">{{ item.i }}</span>
|
||||
</v-btn>
|
||||
</template>
|
||||
<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 duration from "dayjs/plugin/duration";
|
||||
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_DELETED = "im.keanu.room_deleted";
|
||||
|
|
@ -782,10 +788,10 @@ class Util {
|
|||
|
||||
getDefaultAvatars() {
|
||||
var images = [];
|
||||
const modules = import.meta.glob("@/assets/avatars/*.{jpeg,jpg,png}", {
|
||||
query: '?url',
|
||||
import: 'default',
|
||||
eager: true
|
||||
const modules = import.meta.glob("@/assets/avatars/*.{jpeg,jpg,png}", {
|
||||
query: "?url",
|
||||
import: "default",
|
||||
eager: true,
|
||||
});
|
||||
Object.keys(modules).map((path) => {
|
||||
var name = path.split("_")[1];
|
||||
|
|
@ -1180,7 +1186,7 @@ class Util {
|
|||
* Possibly convert numerals to local representation (currently only for "bo" locale)
|
||||
* @param str String in which to convert numerals [0-9]
|
||||
* @returns converted string
|
||||
*/
|
||||
*/
|
||||
toLocalNumbers = (str) => {
|
||||
if (i18n.locale == "my") {
|
||||
// Translate to burmese numerals
|
||||
|
|
@ -1210,5 +1216,24 @@ class Util {
|
|||
|
||||
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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue