Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85630811
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 6552eb816d..c666c1d934 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -1,349 +1,349 @@
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 Completion from '../../services/completion/completion.js'
import { take, filter, 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.length > 0 ? mentions.join(' ') + ' ' : ''
}
const PostStatusForm = {
props: [
'replyTo',
'repliedUser',
'attentions',
'copyMessageScope',
'subject'
],
components: {
MediaUpload
},
mounted () {
this.resize(this.$refs.textarea)
const textLength = this.$refs.textarea.value.length
this.$refs.textarea.setSelectionRange(textLength, textLength)
if (this.replyTo) {
this.$refs.textarea.focus()
}
},
data () {
const preset = this.$route.query.message
let statusText = preset || ''
const scopeCopy = typeof this.$store.state.config.scopeCopy === 'undefined'
? 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 contentType = typeof this.$store.state.config.postContentType === 'undefined'
? this.$store.state.instance.postContentType
: this.$store.state.config.postContentType
return {
dropFiles: [],
submitDisabled: false,
error: null,
posting: false,
highlighted: 0,
newStatus: {
spoilerText: this.subject || '',
status: statusText,
nsfw: false,
files: [],
visibility: scope,
contentType
},
caret: 0
}
},
computed: {
vis () {
return {
public: { selected: this.newStatus.visibility === 'public' },
unlisted: { selected: this.newStatus.visibility === 'unlisted' },
private: { selected: this.newStatus.visibility === 'private' },
direct: { selected: this.newStatus.visibility === 'direct' }
}
},
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
},
emoji () {
return this.$store.state.instance.emoji || []
},
customEmoji () {
return this.$store.state.instance.customEmoji || []
},
statusLength () {
return this.newStatus.status.length
},
spoilerTextLength () {
return this.newStatus.spoilerText.length
},
statusLengthLimit () {
return this.$store.state.instance.textlimit
},
hasStatusLengthLimit () {
return this.statusLengthLimit > 0
},
charactersLeft () {
return this.statusLengthLimit - (this.statusLength + this.spoilerTextLength)
},
isOverLengthLimit () {
return this.hasStatusLengthLimit && (this.charactersLeft < 0)
},
scopeOptionsEnabled () {
return this.$store.state.instance.scopeOptionsEnabled
},
alwaysShowSubject () {
if (typeof this.$store.state.config.alwaysShowSubjectInput !== 'undefined') {
return this.$store.state.config.alwaysShowSubjectInput
} else if (typeof this.$store.state.instance.alwaysShowSubjectInput !== 'undefined') {
return this.$store.state.instance.alwaysShowSubjectInput
} else {
return this.$store.state.instance.scopeOptionsEnabled
}
},
formattingOptionsEnabled () {
return this.$store.state.instance.formattingOptionsEnabled
}
},
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
}
},
setCaret ({target: {selectionStart}}) {
this.caret = selectionStart
},
isValidDM (status) {
// eslint-disable-next-line
- const regex = /\@([\w@.]+)/g
+ const regex = /\@([\w@.]+)(?<![@.])/g
const mentions = status.match(regex) || []
if (!mentions.length) {
window.alert(this.$t('settings.dm_warning_no_user'))
return false
} else if (mentions.length >= 2) {
let mentionsText = mentions.slice(0, mentions.length - 1).join(', ')
mentionsText = [mentionsText, mentions[mentions.length - 1]].join(' and ')
const confirmed = window.confirm(this.$t('settings.dm_warning_multi_user') + mentionsText + '. ' + this.$t('settings.dm_confirm'))
return confirmed
}
return true
},
postStatus (newStatus) {
if (this.posting) { return }
if (this.submitDisabled) { return }
if (this.newStatus.status === '') {
if (this.newStatus.files.length > 0) {
this.newStatus.status = '\u200b' // hack
} else {
this.error = 'Cannot post an empty status with no files'
return
}
}
if (newStatus.visibility === 'direct' && !this.replyTo && !this.isValidDM(newStatus.status)) {
return
}
this.posting = true
statusPoster.postStatus({
status: newStatus.status,
spoilerText: newStatus.spoilerText || null,
visibility: newStatus.visibility,
sensitive: newStatus.nsfw,
media: newStatus.files,
store: this.$store,
inReplyToStatusId: this.replyTo,
contentType: newStatus.contentType
}).then((data) => {
if (!data.error) {
this.newStatus = {
status: '',
spoilerText: '',
files: [],
visibility: newStatus.visibility,
contentType: newStatus.contentType
}
this.$refs.mediaUpload.clearFile()
this.$emit('posted')
let el = this.$el.querySelector('textarea')
el.style.height = 'auto'
el.style.height = undefined
this.error = null
} else {
this.error = data.error
}
this.posting = false
})
},
addMediaFile (fileInfo) {
this.newStatus.files.push(fileInfo)
this.enableSubmit()
},
removeMediaFile (fileInfo) {
let index = this.newStatus.files.indexOf(fileInfo)
this.newStatus.files.splice(index, 1)
},
uploadFailed (errString, templateArgs) {
templateArgs = templateArgs || {}
this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)
this.enableSubmit()
},
disableSubmit () {
this.submitDisabled = true
},
enableSubmit () {
this.submitDisabled = false
},
type (fileInfo) {
return fileTypeService.fileType(fileInfo.mimetype)
},
paste (e) {
if (e.clipboardData.files.length > 0) {
// Strangely, files property gets emptied after event propagation
// Trying to wrap it in array doesn't work. Plus I doubt it's possible
// to hold more than one file in clipboard.
this.dropFiles = [e.clipboardData.files[0]]
}
},
fileDrop (e) {
if (e.dataTransfer.files.length > 0) {
e.preventDefault() // allow dropping text like before
this.dropFiles = e.dataTransfer.files
}
},
fileDrag (e) {
e.dataTransfer.dropEffect = 'copy'
},
resize (e) {
const target = e.target || e
if (!(target instanceof window.Element)) { return }
const vertPadding = Number(window.getComputedStyle(target)['padding-top'].substr(0, 1)) +
Number(window.getComputedStyle(target)['padding-bottom'].substr(0, 1))
// Auto is needed to make textbox shrink when removing lines
target.style.height = 'auto'
target.style.height = `${target.scrollHeight - vertPadding}px`
if (target.value === '') {
target.style.height = null
}
},
clearError () {
this.error = null
},
changeVis (visibility) {
this.newStatus.visibility = visibility
}
}
}
export default PostStatusForm
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Aug 9, 9:26 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1724799
Default Alt Text
(11 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline
Log In to Comment