Emoji Pack Picker #102
3 changed files with 79 additions and 51 deletions
|
@ -6,7 +6,7 @@ import {
|
||||||
faStickyNote,
|
faStickyNote,
|
||||||
faSmileBeam
|
faSmileBeam
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { trim } from 'lodash'
|
import { trim, escapeRegExp, startCase } from 'lodash'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faBoxOpen,
|
faBoxOpen,
|
||||||
|
@ -21,23 +21,6 @@ const LOAD_EMOJI_BY = 60
|
||||||
// When to start loading new batch emoji, in pixels
|
// When to start loading new batch emoji, in pixels
|
||||||
const LOAD_EMOJI_MARGIN = 64
|
const LOAD_EMOJI_MARGIN = 64
|
||||||
|
|
||||||
const filterByKeyword = (list, keyword = '') => {
|
|
||||||
if (keyword === '') return list
|
|
||||||
|
|
||||||
const keywordLowercase = keyword.toLowerCase()
|
|
||||||
let orderedEmojiList = []
|
|
||||||
for (const emoji of list) {
|
|
||||||
const indexOfKeyword = emoji.displayText.toLowerCase().indexOf(keywordLowercase)
|
|
||||||
if (indexOfKeyword > -1) {
|
|
||||||
if (!Array.isArray(orderedEmojiList[indexOfKeyword])) {
|
|
||||||
orderedEmojiList[indexOfKeyword] = []
|
|
||||||
}
|
|
||||||
orderedEmojiList[indexOfKeyword].push(emoji)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return orderedEmojiList.flat()
|
|
||||||
}
|
|
||||||
|
|
||||||
const EmojiPicker = {
|
const EmojiPicker = {
|
||||||
props: {
|
props: {
|
||||||
enableStickerPicker: {
|
enableStickerPicker: {
|
||||||
|
@ -49,7 +32,7 @@ const EmojiPicker = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
keyword: '',
|
keyword: '',
|
||||||
activeGroup: 'custom',
|
activeGroup: 'standard',
|
||||||
showingStickers: false,
|
showingStickers: false,
|
||||||
groupsScrolledClass: 'scrolled-top',
|
groupsScrolledClass: 'scrolled-top',
|
||||||
keepOpen: false,
|
keepOpen: false,
|
||||||
|
@ -80,13 +63,8 @@ const EmojiPicker = {
|
||||||
this.triggerLoadMore(target)
|
this.triggerLoadMore(target)
|
||||||
},
|
},
|
||||||
highlight (key) {
|
highlight (key) {
|
||||||
const ref = this.$refs['group-' + key]
|
|
||||||
const top = ref.offsetTop
|
|
||||||
this.setShowStickers(false)
|
this.setShowStickers(false)
|
||||||
this.activeGroup = key
|
this.activeGroup = key
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs['emoji-groups'].scrollTop = top + 1
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
updateScrolledClass (target) {
|
updateScrolledClass (target) {
|
||||||
if (target.scrollTop <= 5) {
|
if (target.scrollTop <= 5) {
|
||||||
|
@ -155,6 +133,13 @@ const EmojiPicker = {
|
||||||
},
|
},
|
||||||
setShowStickers (value) {
|
setShowStickers (value) {
|
||||||
this.showingStickers = value
|
this.showingStickers = value
|
||||||
|
},
|
||||||
|
filterByKeyword (list) {
|
||||||
|
if (this.keyword === '') return list
|
||||||
|
const regex = new RegExp(escapeRegExp(trim(this.keyword)), 'i')
|
||||||
|
return list.filter(emoji => {
|
||||||
|
return regex.test(emoji.displayText)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -175,9 +160,8 @@ const EmojiPicker = {
|
||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
filteredEmoji () {
|
filteredEmoji () {
|
||||||
return filterByKeyword(
|
return this.filterByKeyword(
|
||||||
this.$store.state.instance.customEmoji || [],
|
this.$store.state.instance.customEmoji || []
|
||||||
trim(this.keyword)
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
customEmojiBuffer () {
|
customEmojiBuffer () {
|
||||||
|
@ -185,25 +169,50 @@ const EmojiPicker = {
|
||||||
},
|
},
|
||||||
emojis () {
|
emojis () {
|
||||||
const standardEmojis = this.$store.state.instance.emoji || []
|
const standardEmojis = this.$store.state.instance.emoji || []
|
||||||
const customEmojis = this.customEmojiBuffer
|
const customEmojis = this.sortedEmoji
|
||||||
|
const emojiPacks = []
|
||||||
|
customEmojis.forEach((pack, id) => {
|
||||||
|
emojiPacks.push({
|
||||||
|
id: id.replace(/^pack:/, ''),
|
||||||
|
text: startCase(id.replace(/^pack:/, '')),
|
||||||
|
first: pack[0],
|
||||||
|
emojis: this.filterByKeyword(pack)
|
||||||
|
})
|
||||||
|
})
|
||||||
return [
|
return [
|
||||||
{
|
|
||||||
id: 'custom',
|
|
||||||
text: this.$t('emoji.custom'),
|
|
||||||
icon: 'smile-beam',
|
|
||||||
emojis: customEmojis
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'standard',
|
id: 'standard',
|
||||||
text: this.$t('emoji.unicode'),
|
text: this.$t('emoji.unicode'),
|
||||||
icon: 'box-open',
|
first: {
|
||||||
emojis: filterByKeyword(standardEmojis, trim(this.keyword))
|
imageUrl: '',
|
||||||
|
replacement: '🥴'
|
||||||
Ghost marked this conversation as resolved
|
|||||||
|
},
|
||||||
|
emojis: this.filterByKeyword(standardEmojis)
|
||||||
}
|
}
|
||||||
]
|
].concat(emojiPacks)
|
||||||
|
},
|
||||||
|
sortedEmoji () {
|
||||||
Ghost
commented
think this should probably sort alphabetically by pack name instead of by.. it looks like pack size? think this should probably sort alphabetically by pack name instead of by.. it looks like pack size?
Mergan
commented
The emojis come alphabetically ordered by default, but they were in a single pack. All I did was sort them into their respective packs. After that they're aplhabetically ordered within their packs (I think). The order of the packs is a first come first serve on the packing lol The emojis come alphabetically ordered by default, but they were in a single pack. All I did was sort them into their respective packs. After that they're aplhabetically ordered within their packs (I think). The order of the packs is a first come first serve on the packing lol
Ghost
commented
yeah i think the order of the pack should be passed through a sort yeah i think the order of the pack should be passed through a sort
Mergan
commented
I can add it real quick but hmm how do I hmmm does this undo the pull request or what's the procedure I can add it real quick but hmm how do I hmmm does this undo the pull request or what's the procedure
Ghost
commented
you can send a new commit to the branch and the pr will be updated you can send a new commit to the branch and the pr will be updated
or, if you want it to still be one commit, you can `git commit --amend` and `git push --force`
|
|||||||
|
const customEmojis = this.$store.state.instance.customEmoji || []
|
||||||
|
const sortedEmojiGroups = new Map()
|
||||||
|
customEmojis.forEach((emoji) => {
|
||||||
|
if (!sortedEmojiGroups.has(emoji.tags[0])) {
|
||||||
|
sortedEmojiGroups.set(emoji.tags[0], [emoji])
|
||||||
|
} else {
|
||||||
|
sortedEmojiGroups.get(emoji.tags[0]).push(emoji)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return new Map([...sortedEmojiGroups.entries()].sort())
|
||||||
},
|
},
|
||||||
emojisView () {
|
emojisView () {
|
||||||
return this.emojis.filter(value => value.emojis.length > 0)
|
if (this.keyword === '') {
|
||||||
|
return this.emojis.filter(pack => {
|
||||||
|
return pack.id === this.activeGroup
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return this.emojis.filter(pack => {
|
||||||
|
return pack.emojis.length > 0
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
stickerPickerEnabled () {
|
stickerPickerEnabled () {
|
||||||
return (this.$store.state.instance.stickers || []).length !== 0
|
return (this.$store.state.instance.stickers || []).length !== 0
|
||||||
|
|
|
@ -35,9 +35,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading {
|
.heading {
|
||||||
display: flex;
|
margin-top: 10px;
|
||||||
height: 32px;
|
height: 4.8em;
|
||||||
padding: 10px 7px 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
@ -65,15 +64,34 @@
|
||||||
|
|
||||||
.additional-tabs,
|
.additional-tabs,
|
||||||
.emoji-tabs {
|
.emoji-tabs {
|
||||||
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 0;
|
flex-wrap: nowrap;
|
||||||
flex-basis: auto;
|
|
||||||
flex-shrink: 1;
|
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
&-item {
|
&-item {
|
||||||
padding: 0 7px;
|
vertical-align: top;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
padding: .4em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 1.85em;
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 1.9em;
|
||||||
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|
|
@ -13,10 +13,11 @@
|
||||||
:title="group.text"
|
:title="group.text"
|
||||||
@click.prevent="highlight(group.id)"
|
@click.prevent="highlight(group.id)"
|
||||||
>
|
>
|
||||||
<FAIcon
|
<span v-if="!group.first.imageUrl">{{ group.first.replacement }}</span>
|
||||||
:icon="group.icon"
|
<img
|
||||||
fixed-width
|
v-else
|
||||||
/>
|
:src="group.first.imageUrl"
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
|
|
Loading…
Reference in a new issue
kinda confusing when we're dealing with emoji, i think the default "missing file" sprite or maybe a Ø svg would be appropriate
faExclamation
, perhaps?The 🥴 emoji is the icon I chose for the Unicode Emoji Pack. I'm not sure what it returns when a missing file happens, but I left that part mostly intact 🤔
That'd be on emoji_picker.vue 16
aaahh, i see. disregard this then