Merge branch 'refactor-emoji-input' into 'develop'
EmojiInput refactoring Closes #565 See merge request pleroma/pleroma-fe!824
This commit is contained in:
commit
69eff65130
10 changed files with 445 additions and 299 deletions
|
@ -3,16 +3,16 @@ import MediaUpload from '../media_upload/media_upload.vue'
|
|||
import ScopeSelector from '../scope_selector/scope_selector.vue'
|
||||
import EmojiInput from '../emoji-input/emoji-input.vue'
|
||||
import fileTypeService from '../../services/file_type/file_type.service.js'
|
||||
import Completion from '../../services/completion/completion.js'
|
||||
import { take, filter, reject, map, uniqBy } from 'lodash'
|
||||
import { reject, map, uniqBy } from 'lodash'
|
||||
import suggestor from '../emoji-input/suggestor.js'
|
||||
|
||||
const buildMentionsString = ({user, attentions}, currentUser) => {
|
||||
const buildMentionsString = ({ user, attentions }, currentUser) => {
|
||||
let allAttentions = [...attentions]
|
||||
|
||||
allAttentions.unshift(user)
|
||||
|
||||
allAttentions = uniqBy(allAttentions, 'id')
|
||||
allAttentions = reject(allAttentions, {id: currentUser.id})
|
||||
allAttentions = reject(allAttentions, { id: currentUser.id })
|
||||
|
||||
let mentions = map(allAttentions, (attention) => {
|
||||
return `@${attention.screen_name}`
|
||||
|
@ -48,17 +48,17 @@ const PostStatusForm = {
|
|||
let statusText = preset || ''
|
||||
|
||||
const scopeCopy = typeof this.$store.state.config.scopeCopy === 'undefined'
|
||||
? this.$store.state.instance.scopeCopy
|
||||
: this.$store.state.config.scopeCopy
|
||||
? this.$store.state.instance.scopeCopy
|
||||
: this.$store.state.config.scopeCopy
|
||||
|
||||
if (this.replyTo) {
|
||||
const currentUser = this.$store.state.users.currentUser
|
||||
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
|
||||
}
|
||||
|
||||
const scope = (this.copyMessageScope && scopeCopy || this.copyMessageScope === 'direct')
|
||||
? this.copyMessageScope
|
||||
: this.$store.state.users.currentUser.default_scope
|
||||
const scope = ((this.copyMessageScope && scopeCopy) || this.copyMessageScope === 'direct')
|
||||
? this.copyMessageScope
|
||||
: this.$store.state.users.currentUser.default_scope
|
||||
|
||||
const contentType = typeof this.$store.state.config.postContentType === 'undefined'
|
||||
? this.$store.state.instance.postContentType
|
||||
|
@ -82,50 +82,6 @@ const PostStatusForm = {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
candidates () {
|
||||
const firstchar = this.textAtCaret.charAt(0)
|
||||
if (firstchar === '@') {
|
||||
const query = this.textAtCaret.slice(1).toUpperCase()
|
||||
const matchedUsers = filter(this.users, (user) => {
|
||||
return user.screen_name.toUpperCase().startsWith(query) ||
|
||||
user.name && user.name.toUpperCase().startsWith(query)
|
||||
})
|
||||
if (matchedUsers.length <= 0) {
|
||||
return false
|
||||
}
|
||||
// eslint-disable-next-line camelcase
|
||||
return map(take(matchedUsers, 5), ({screen_name, name, profile_image_url_original}, index) => ({
|
||||
// eslint-disable-next-line camelcase
|
||||
screen_name: `@${screen_name}`,
|
||||
name: name,
|
||||
img: profile_image_url_original,
|
||||
highlighted: index === this.highlighted
|
||||
}))
|
||||
} else 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) => ({
|
||||
screen_name: `:${shortcode}:`,
|
||||
name: '',
|
||||
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.newStatus.status, this.caret - 1) || {}
|
||||
return word
|
||||
},
|
||||
users () {
|
||||
return this.$store.state.users.users
|
||||
},
|
||||
|
@ -134,10 +90,27 @@ const PostStatusForm = {
|
|||
},
|
||||
showAllScopes () {
|
||||
const minimalScopesMode = typeof this.$store.state.config.minimalScopesMode === 'undefined'
|
||||
? this.$store.state.instance.minimalScopesMode
|
||||
: this.$store.state.config.minimalScopesMode
|
||||
? this.$store.state.instance.minimalScopesMode
|
||||
: this.$store.state.config.minimalScopesMode
|
||||
return !minimalScopesMode
|
||||
},
|
||||
emojiUserSuggestor () {
|
||||
return suggestor({
|
||||
emoji: [
|
||||
...this.$store.state.instance.emoji,
|
||||
...this.$store.state.instance.customEmoji
|
||||
],
|
||||
users: this.$store.state.users.users
|
||||
})
|
||||
},
|
||||
emojiSuggestor () {
|
||||
return suggestor({
|
||||
emoji: [
|
||||
...this.$store.state.instance.emoji,
|
||||
...this.$store.state.instance.customEmoji
|
||||
]
|
||||
})
|
||||
},
|
||||
emoji () {
|
||||
return this.$store.state.instance.emoji || []
|
||||
},
|
||||
|
@ -185,57 +158,6 @@ const PostStatusForm = {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
replace (replacement) {
|
||||
this.newStatus.status = Completion.replaceWord(this.newStatus.status, this.wordAtCaret, replacement)
|
||||
const el = this.$el.querySelector('textarea')
|
||||
el.focus()
|
||||
this.caret = 0
|
||||
},
|
||||
replaceCandidate (e) {
|
||||
const len = this.candidates.length || 0
|
||||
if (this.textAtCaret === ':' || e.ctrlKey) { return }
|
||||
if (len > 0) {
|
||||
e.preventDefault()
|
||||
const candidate = this.candidates[this.highlighted]
|
||||
const replacement = candidate.utf || (candidate.screen_name + ' ')
|
||||
this.newStatus.status = Completion.replaceWord(this.newStatus.status, this.wordAtCaret, replacement)
|
||||
const el = this.$el.querySelector('textarea')
|
||||
el.focus()
|
||||
this.caret = 0
|
||||
this.highlighted = 0
|
||||
}
|
||||
},
|
||||
cycleBackward (e) {
|
||||
const len = this.candidates.length || 0
|
||||
if (len > 0) {
|
||||
e.preventDefault()
|
||||
this.highlighted -= 1
|
||||
if (this.highlighted < 0) {
|
||||
this.highlighted = this.candidates.length - 1
|
||||
}
|
||||
} else {
|
||||
this.highlighted = 0
|
||||
}
|
||||
},
|
||||
cycleForward (e) {
|
||||
const len = this.candidates.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()
|
||||
},
|
||||
setCaret ({target: {selectionStart}}) {
|
||||
this.caret = selectionStart
|
||||
},
|
||||
postStatus (newStatus) {
|
||||
if (this.posting) { return }
|
||||
if (this.submitDisabled) { return }
|
||||
|
@ -314,7 +236,7 @@ const PostStatusForm = {
|
|||
},
|
||||
fileDrop (e) {
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
e.preventDefault() // allow dropping text like before
|
||||
e.preventDefault() // allow dropping text like before
|
||||
this.dropFiles = e.dataTransfer.files
|
||||
}
|
||||
},
|
||||
|
|
|
@ -33,30 +33,39 @@
|
|||
</p>
|
||||
<EmojiInput
|
||||
v-if="newStatus.spoilerText || alwaysShowSubject"
|
||||
type="text"
|
||||
:placeholder="$t('post_status.content_warning')"
|
||||
:suggest="emojiSuggestor"
|
||||
v-model="newStatus.spoilerText"
|
||||
classname="form-control"
|
||||
/>
|
||||
<textarea
|
||||
ref="textarea"
|
||||
@click="setCaret"
|
||||
@keyup="setCaret" v-model="newStatus.status" :placeholder="$t('post_status.default')" rows="1" class="form-control"
|
||||
@keydown="onKeydown"
|
||||
@keydown.down="cycleForward"
|
||||
@keydown.up="cycleBackward"
|
||||
@keydown.shift.tab="cycleBackward"
|
||||
@keydown.tab="cycleForward"
|
||||
@keydown.enter="replaceCandidate"
|
||||
@keydown.meta.enter="postStatus(newStatus)"
|
||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
||||
@drop="fileDrop"
|
||||
@dragover.prevent="fileDrag"
|
||||
@input="resize"
|
||||
@paste="paste"
|
||||
:disabled="posting"
|
||||
>
|
||||
</textarea>
|
||||
class="form-control"
|
||||
>
|
||||
<input
|
||||
|
||||
type="text"
|
||||
:placeholder="$t('post_status.content_warning')"
|
||||
v-model="newStatus.spoilerText"
|
||||
class="form-post-subject"
|
||||
/>
|
||||
</EmojiInput>
|
||||
<EmojiInput
|
||||
:suggest="emojiUserSuggestor"
|
||||
v-model="newStatus.status"
|
||||
class="form-control"
|
||||
>
|
||||
<textarea
|
||||
ref="textarea"
|
||||
v-model="newStatus.status"
|
||||
:placeholder="$t('post_status.default')"
|
||||
rows="1"
|
||||
@keydown.meta.enter="postStatus(newStatus)"
|
||||
@keyup.ctrl.enter="postStatus(newStatus)"
|
||||
@drop="fileDrop"
|
||||
@dragover.prevent="fileDrag"
|
||||
@input="resize"
|
||||
@paste="paste"
|
||||
:disabled="posting"
|
||||
class="form-post-body"
|
||||
>
|
||||
</textarea>
|
||||
</EmojiInput>
|
||||
<div class="visibility-tray">
|
||||
<div class="text-format" v-if="postFormats.length > 1">
|
||||
<label for="post-content-type" class="select">
|
||||
|
@ -82,21 +91,6 @@
|
|||
:onScopeChange="changeVis"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="autocomplete-panel" v-if="candidates">
|
||||
<div class="autocomplete-panel-body">
|
||||
<div
|
||||
v-for="(candidate, index) in candidates"
|
||||
:key="index"
|
||||
@click="replace(candidate.utf || (candidate.screen_name + ' '))"
|
||||
class="autocomplete-item"
|
||||
:class="{ highlighted: candidate.highlighted }"
|
||||
>
|
||||
<span v-if="candidate.img"><img :src="candidate.img" /></span>
|
||||
<span v-else>{{candidate.utf}}</span>
|
||||
<span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='form-bottom'>
|
||||
<media-upload ref="mediaUpload" @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
|
||||
|
||||
|
@ -276,7 +270,7 @@
|
|||
min-height: 1px;
|
||||
}
|
||||
|
||||
form textarea.form-control {
|
||||
.form-post-body {
|
||||
line-height:16px;
|
||||
resize: none;
|
||||
overflow: hidden;
|
||||
|
@ -285,7 +279,7 @@
|
|||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
form textarea.form-control:focus {
|
||||
.form-post-body:focus {
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue