aboutsummaryrefslogtreecommitdiff
path: root/src/components/emoji-input/emoji-input.js
blob: 8f7598cad63d799424f5d853a5820c6193ccca26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import Completion from '../../services/completion/completion.js'
import EmojiSelector from '../emoji-selector/emoji-selector.vue'

import { take, filter, map } from 'lodash'

const EmojiInput = {
  props: [
    'value',
    'placeholder',
    'type',
    'classname'
  ],
  data () {
    return {
      highlighted: 0,
      caret: 0
    }
  },
  components: {
    EmojiSelector
  },
  computed: {
    suggestions () {
      const firstchar = this.textAtCaret.charAt(0)
      if (firstchar === ':') {
        if (this.textAtCaret === ':') { return }
        const matchedEmoji = filter(this.emoji.concat(this.customEmoji), (emoji) => emoji.shortcode.startsWith(this.textAtCaret.slice(1)))
        if (matchedEmoji.length <= 0) {
          return false
        }
        return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({
          shortcode: `:${shortcode}:`,
          utf: utf || '',
          // eslint-disable-next-line camelcase
          img: utf ? '' : this.$store.state.instance.server + image_url,
          highlighted: index === this.highlighted
        }))
      } else {
        return false
      }
    },
    textAtCaret () {
      return (this.wordAtCaret || {}).word || ''
    },
    wordAtCaret () {
      const word = Completion.wordAtPosition(this.value, this.caret - 1) || {}
      return word
    },
    emoji () {
      return this.$store.state.instance.emoji || []
    },
    customEmoji () {
      return this.$store.state.instance.customEmoji || []
    }
  },
  methods: {
    replace (replacement) {
      const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
      this.$emit('input', newValue)
      this.caret = 0
    },
    replaceEmoji (e) {
      const len = this.suggestions.length || 0
      if (this.textAtCaret === ':' || e.ctrlKey) { return }
      if (len > 0) {
        e.preventDefault()
        const emoji = this.suggestions[this.highlighted]
        const replacement = emoji.utf || (emoji.shortcode + ' ')
        const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement)
        this.$emit('input', newValue)
        this.caret = 0
        this.highlighted = 0
      }
    },
    cycleBackward (e) {
      const len = this.suggestions.length || 0
      if (len > 0) {
        e.preventDefault()
        this.highlighted -= 1
        if (this.highlighted < 0) {
          this.highlighted = this.suggestions.length - 1
        }
      } else {
        this.highlighted = 0
      }
    },
    cycleForward (e) {
      const len = this.suggestions.length || 0
      if (len > 0) {
        if (e.shiftKey) { return }
        e.preventDefault()
        this.highlighted += 1
        if (this.highlighted >= len) {
          this.highlighted = 0
        }
      } else {
        this.highlighted = 0
      }
    },
    onKeydown (e) {
      e.stopPropagation()
    },
    onInput (e) {
      this.$emit('input', e.target.value)
    },
    setCaret ({target: {selectionStart}}) {
      this.caret = selectionStart
    },
    onEmoji (emoji) {
      const newValue = this.value.substr(0, this.caret) + emoji + this.value.substr(this.caret)
      this.$refs.input.focus()
      this.$emit('input', newValue)
    }
  }
}

export default EmojiInput