aboutsummaryrefslogtreecommitdiff
path: root/src/components/emoji_picker
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/emoji_picker')
-rw-r--r--src/components/emoji_picker/emoji_picker.js82
-rw-r--r--src/components/emoji_picker/emoji_picker.scss78
-rw-r--r--src/components/emoji_picker/emoji_picker.vue60
3 files changed, 164 insertions, 56 deletions
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index e25f98ff..0a64f759 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -1,15 +1,26 @@
+
const filterByKeyword = (list, keyword = '') => {
return list.filter(x => x.displayText.includes(keyword))
}
const EmojiPicker = {
+ props: {
+ stickerPicker: {
+ required: false,
+ type: Boolean,
+ default: false
+ }
+ },
data () {
return {
keyword: '',
- activeGroup: 'standard',
- showingAdditional: false
+ activeGroup: 'custom',
+ showingStickers: false
}
},
+ components: {
+ StickerPicker: () => import('../sticker_picker/sticker_picker.vue')
+ },
methods: {
onEmoji (emoji) {
const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement
@@ -19,37 +30,72 @@ const EmojiPicker = {
highlight (key) {
const ref = this.$refs['group-' + key]
const top = ref[0].offsetTop
- this.$refs['emoji-groups'].scrollTop = top + 1
+ this.setShowStickers(false)
this.activeGroup = key
+ this.$nextTick(() => {
+ this.$refs['emoji-groups'].scrollTop = top + 1
+ })
},
scrolledGroup (e) {
- const top = e.target.scrollTop
- Object.keys(this.emojis).forEach(key => {
- if (this.$refs['group-' + key][0].offsetTop < top) {
- this.activeGroup = key
- }
+ const target = (e && e.target) || this.$refs['emoji-groups']
+ const top = target.scrollTop + 5
+ this.$nextTick(() => {
+ this.emojisView.forEach(group => {
+ const ref = this.$refs['group-' + group.id]
+ if (ref[0].offsetTop <= top) {
+ this.activeGroup = group.id
+ }
+ })
})
},
- toggleAdditional (value) {
- this.showingAdditional = value
+ toggleStickers () {
+ this.showingStickers = !this.showingStickers
+ },
+ setShowStickers (value) {
+ this.showingStickers = value
+ },
+ onStickerUploaded (e) {
+ this.$emit('sticker-uploaded', e)
+ },
+ onStickerUploadFailed (e) {
+ this.$emit('sticker-upload-failed', e)
+ }
+ },
+ watch: {
+ keyword () {
+ this.scrolledGroup()
}
},
computed: {
+ activeGroupView () {
+ return this.showingStickers ? '' : this.activeGroup
+ },
+ stickersAvailable () {
+ if (this.$store.state.instance.stickers) {
+ return this.$store.state.instance.stickers.length > 0
+ }
+ return 0
+ },
emojis () {
const standardEmojis = this.$store.state.instance.emoji || []
const customEmojis = this.$store.state.instance.customEmoji || []
- return {
- custom: {
- text: 'Custom',
- icon: 'icon-picture',
+ return [
+ {
+ id: 'custom',
+ text: this.$t('emoji.custom'),
+ icon: 'icon-smile',
emojis: filterByKeyword(customEmojis, this.keyword)
},
- standard: {
- text: 'Standard',
- icon: 'icon-star',
+ {
+ id: 'standard',
+ text: this.$t('emoji.unicode'),
+ icon: 'icon-picture',
emojis: filterByKeyword(standardEmojis, this.keyword)
}
- }
+ ]
+ },
+ emojisView () {
+ return this.emojis.filter(value => value.emojis.length > 0)
}
}
}
diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index 72889441..6c13e82b 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -1,39 +1,78 @@
@import '../../_variables.scss';
.emoji-picker {
+ display: flex;
+ flex-direction: column;
position: absolute;
- z-index: 1;
right: 0;
- width: 300px;
+ left: 0;
height: 300px;
- display: flex;
- flex-direction: column;
margin: 0 !important;
+ z-index: 1;
- .emoji {
- &-tabs {
- &-item {
- padding: 0 5px;
+ .panel-body {
+ display: flex;
+ flex-direction: column;
+ flex: 1 1 0;
+ min-height: 0px;
+ }
+
+ .additional-tabs {
+ border-left: 1px solid;
+ border-left-color: $fallback--icon;
+ border-left-color: var(--icon, $fallback--icon);
+ padding-left: 5px;
+ flex: 0 0 0;
+ }
+
+ .emoji-tabs {
+ flex: 1 1 0;
+ }
+
+ .additional-tabs,
+ .emoji-tabs {
+ &-item {
+ padding: 0 5px;
+ cursor: pointer;
+ font-size: 24px;
- &.active {
- border-bottom: 4px solid;
+ &.disabled {
+ opacity: 0.5;
+ pointer-events: none;
+ }
+ &.active {
+ border-bottom: 4px solid;
- i {
- color: $fallback--lightText;
- color: var(--lightText, $fallback--lightText);
- }
+ i {
+ color: $fallback--lightText;
+ color: var(--lightText, $fallback--lightText);
}
}
}
+ }
+ .sticker-picker {
+ flex: 1 1 0
+ }
+
+ .stickers,
+ .emoji {
&-content {
display: flex;
flex-direction: column;
+ flex: 1 1 0;
+ min-height: 0;
+
+ &.hidden {
+ display: none
+ }
}
+ }
+ .emoji {
&-search {
padding: 5px;
- flex: 0 0 1px;
+ flex: 0 0 0;
input {
width: 100%;
@@ -50,13 +89,16 @@
display: flex;
align-items: center;
flex-wrap: wrap;
- padding: 5px;
- justify-content: space-between;
+ padding-left: 5px;
+ justify-content: left;
&-title {
font-size: 12px;
width: 100%;
margin: 0;
+ &.disabled {
+ display: none;
+ }
}
}
@@ -68,7 +110,7 @@
font-size: 32px;
align-items: center;
justify-content: center;
- margin: 2px;
+ margin: 4px;
cursor: pointer;
diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue
index ec1702f3..12b1569e 100644
--- a/src/components/emoji_picker/emoji_picker.vue
+++ b/src/components/emoji_picker/emoji_picker.vue
@@ -3,30 +3,44 @@
<div class="panel-heading">
<span class="emoji-tabs">
<span
- v-for="(value, key) in emojis"
- :key="key"
+ v-for="group in emojis"
+ :key="group.id"
class="emoji-tabs-item"
- :class="{'active': activeGroup === key}"
- :title="value.text"
- @click.prevent="highlight(key)"
+ :class="{
+ active: activeGroupView === group.id,
+ disabled: group.emojis.length === 0
+ }"
+ :title="group.text"
+ @click.prevent="highlight(group.id)"
>
- <i :class="value.icon" />
+ <i :class="group.icon" />
</span>
</span>
- <span class="additional-tabs">
- <slot name="tabs" />
+ <span
+ v-if="stickerPicker"
+ class="additional-tabs"
+ >
+ <span
+ class="stickers-tab-icon additional-tabs-item"
+ :class="{active: showingStickers}"
+ :title="$t('emoji.stickers')"
+ @click.prevent="toggleStickers"
+ >
+ <i class="icon-star" />
+ </span>
</span>
</div>
- <div class="panel-body emoji-dropdown-menu-content">
+ <div class="panel-body">
<div
- v-if="!showingAdditional"
class="emoji-content"
+ :class="{hidden: showingStickers}"
>
<div class="emoji-search">
<input
v-model="keyword"
type="text"
class="form-control"
+ :placeholder="$t('emoji.search_emoji')"
>
</div>
<div
@@ -35,22 +49,22 @@
@scroll="scrolledGroup"
>
<div
- v-for="(value, key) in emojis"
- :key="key"
+ v-for="group in emojisView"
+ :key="group.id"
class="emoji-group"
>
<h6
- :ref="'group-' + key"
+ :ref="'group-' + group.id"
class="emoji-group-title"
>
- {{ value.text }}
+ {{ group.text }}
</h6>
<span
- v-for="emoji in value.emojis"
- :key="key + emoji.displayText"
+ v-for="emoji in group.emojis"
+ :key="group.id + emoji.displayText"
:title="emoji.displayText"
class="emoji-item"
- @click="onEmoji(emoji)"
+ @click.stop.prevent="onEmoji(emoji)"
>
<span v-if="!emoji.imageUrl">{{ emoji.replacement }}</span>
<img
@@ -61,11 +75,17 @@
</div>
</div>
</div>
- <div v-if="showingAdditional" class="additional-tabs-content">
- <slot name="tab-content" />
+ <div
+ v-if="showingStickers"
+ class="stickers-content"
+ >
+ <sticker-picker
+ @uploaded="onStickerUploaded"
+ @upload-failed="onStickerUploadFailed"
+ />
</div>
</div>
-</div>
+ </div>
</template>
<script src="./emoji_picker.js"></script>