akkoma-fe/src/components/post_status_form/post_status_form.js

147 lines
3.7 KiB
JavaScript

import statusPoster from '../../services/status_poster/status_poster.service.js'
import MediaUpload from '../media_upload/media_upload.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
import Tribute from '../../../node_modules/tributejs/src/Tribute.js'
require('../../../node_modules/tributejs/scss/tribute.scss')
import { merge, reject, map, uniqBy } from 'lodash'
const buildMentionsString = ({user, attentions}, currentUser) => {
let allAttentions = [...attentions]
allAttentions.unshift(user)
allAttentions = uniqBy(allAttentions, 'id')
allAttentions = reject(allAttentions, {id: currentUser.id})
let mentions = map(allAttentions, (attention) => {
return `@${attention.screen_name}`
})
return mentions.join(' ') + ' '
}
const defaultCollection = {
// symbol that starts the lookup
trigger: '@',
// element to target for @mentions
iframe: null,
// class added in the flyout menu for active item
selectClass: 'highlight',
// function called on select that returns the content to insert
selectTemplate: function (item) {
return '@' + item.original.screen_name
},
// template for displaying item in menu
menuItemTemplate: function (item) {
return `<img src="${item.original.profile_image_url}"></img> <div class='name'>${item.string}</div>`
},
// template for when no match is found (optional),
// If no template is provided, menu is hidden.
noMatchTemplate: null,
// specify an alternative parent container for the menu
menuContainer: document.body,
// column to search against in the object (accepts function or string)
lookup: 'name',
// column that contains the content to insert by default
fillAttr: 'screen_name',
// REQUIRED: array of objects to match
values: [],
// specify whether a space is required before the trigger character
requireLeadingSpace: true,
// specify whether a space is allowed in the middle of mentions
allowSpaces: false
}
const tribute = new Tribute({ collection: [] })
const PostStatusForm = {
props: [
'replyTo',
'repliedUser',
'attentions'
],
components: {
MediaUpload
},
data () {
let statusText = ''
if (this.replyTo) {
const currentUser = this.$store.state.users.currentUser
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
return {
submitDisabled: false,
newStatus: {
status: statusText,
files: []
}
}
},
computed: {
completions () {
let users = map(this.$store.state.statuses.allStatuses, 'user')
users = uniqBy(users, 'id')
users = merge({values: users}, defaultCollection)
return [users]
}
},
watch: {
completions () {
tribute.collection = this.completions
}
},
mounted () {
const textarea = this.$el.querySelector('textarea')
tribute.collection = this.completions
tribute.attach(textarea)
},
methods: {
postStatus (newStatus) {
statusPoster.postStatus({
status: newStatus.status,
media: newStatus.files,
store: this.$store,
inReplyToStatusId: this.replyTo
})
this.newStatus = {
status: '',
files: []
}
this.$emit('posted')
},
addMediaFile (fileInfo) {
this.newStatus.files.push(fileInfo)
this.enableSubmit()
},
removeMediaFile (fileInfo) {
let index = this.newStatus.files.indexOf(fileInfo)
this.newStatus.files.splice(index, 1)
},
disableSubmit () {
this.submitDisabled = true
},
enableSubmit () {
this.submitDisabled = false
},
type (fileInfo) {
return fileTypeService.fileType(fileInfo.mimetype)
}
}
}
export default PostStatusForm