Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85628949
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/components/autocomplete_input/autocomplete_input.js b/src/components/autocomplete_input/autocomplete_input.js
index 1544e7bb01..404a8cdbc5 100644
--- a/src/components/autocomplete_input/autocomplete_input.js
+++ b/src/components/autocomplete_input/autocomplete_input.js
@@ -1,149 +1,151 @@
import Completion from '../../services/completion/completion.js'
import { take, filter, map } from 'lodash'
const AutoCompleteInput = {
props: [
'id',
'classObj',
'value',
'placeholder',
'autoResize',
'multiline',
'drop',
'dragoverPrevent',
'paste',
'keydownMetaEnter',
'keyupCtrlEnter'
],
components: {},
mounted () {
this.autoResize && this.resize(this.$refs.textarea)
const textLength = this.$refs.textarea.value.length
this.$refs.textarea.setSelectionRange(textLength, textLength)
},
data () {
return {
caret: 0,
- highlighted: 0
+ highlighted: 0,
+ text: this.value
}
},
computed: {
users () {
return this.$store.state.users.users
},
emoji () {
return this.$store.state.instance.emoji || []
},
customEmoji () {
return this.$store.state.instance.customEmoji || []
},
textAtCaret () {
return (this.wordAtCaret || {}).word || ''
},
wordAtCaret () {
- const word = Completion.wordAtPosition(this.value, this.caret - 1) || {}
+ const word = Completion.wordAtPosition(this.text, this.caret - 1) || {}
return word
},
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
}
}
},
methods: {
setCaret ({target: {selectionStart}}) {
this.caret = selectionStart
},
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
}
},
replace (replacement) {
- this.$emit('input', Completion.replaceWord(this.value, this.wordAtCaret, replacement))
- const el = this.$el.querySelector('textarea') || this.$el.querySelector('input')
+ this.text = Completion.replaceWord(this.text, 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.$emit('input', Completion.replaceWord(this.value, this.wordAtCaret, replacement))
+ this.text = Completion.replaceWord(this.text, this.wordAtCaret, replacement)
+ this.$emit('input', this.text)
const el = this.$el.querySelector('textarea') || this.$el.querySelector('input')
el.focus()
this.caret = 0
this.highlighted = 0
}
},
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
}
}
}
}
export default AutoCompleteInput
diff --git a/src/components/autocomplete_input/autocomplete_input.vue b/src/components/autocomplete_input/autocomplete_input.vue
index 1e26b76bc0..56233535a1 100644
--- a/src/components/autocomplete_input/autocomplete_input.vue
+++ b/src/components/autocomplete_input/autocomplete_input.vue
@@ -1,104 +1,104 @@
<template>
<div style="display: flex; flex-direction: column;">
<textarea
v-if="multiline"
ref="textarea"
rows="1"
- :value="value" :class="classObj" :id="id" :placeholder="placeholder"
- @input="$emit('input', $event.target.value), autoResize && resize($event)"
+ :value="text" :class="classObj" :id="id" :placeholder="placeholder"
+ @input="text = $event.target.value, $emit('input', $event.target.value), autoResize && resize($event)"
@click="setCaret"
@keyup="setCaret"
@keydown.down="cycleForward"
@keydown.up="cycleBackward"
@keydown.shift.tab="cycleBackward"
@keydown.tab="cycleForward"
@keydown.enter="replaceCandidate"
- @drop="drop && drop($event)"
- @dragover.prevent="dragoverPrevent && dragoverPrevent($event)"
- @paste="paste && paste($event)"
- @keydown.meta.enter="keydownMetaEnter && keydownMetaEnter($event)"
- @keyup.ctrl.enter="keyupCtrlEnter && keyupCtrlEnter($event)">
+ @drop="drop && drop()"
+ @dragover.prevent="dragoverPrevent && dragoverPrevent()"
+ @paste="paste && paste()"
+ @keydown.meta.enter="keydownMetaEnter && keydownMetaEnter()"
+ @keyup.ctrl.enter="keyupCtrlEnter && keyupCtrlEnter()">
</textarea>
<input
v-else
ref="textarea"
- :value="value" :class="classObj" :id="id" :placeholder="placeholder"
- @input="$emit('input', $event.target.value), autoResize && resize($event)"
+ :value="text" :class="classObj" :id="id" :placeholder="placeholder"
+ @input="text = $event.target.value, $emit('input', $event.target.value), autoResize && resize($event)"
@click="setCaret"
@keyup="setCaret"
@keydown.down="cycleForward"
@keydown.up="cycleBackward"
@keydown.shift.tab="cycleBackward"
@keydown.tab="cycleForward"
@keydown.enter="replaceCandidate"
- @drop="drop && drop($event)"
- @dragover.prevent="dragoverPrevent && dragoverPrevent($event)"
- @paste="paste && paste($event)"
- @keydown.meta.enter="keydownMetaEnter && keydownMetaEnter($event)"
- @keyup.ctrl.enter="keyupCtrlEnter && keyupCtrlEnter($event)"/>
+ @drop="drop && drop()"
+ @dragover.prevent="dragoverPrevent && dragoverPrevent()"
+ @paste="paste && paste()"
+ @keydown.meta.enter="keydownMetaEnter && keydownMetaEnter()"
+ @keyup.ctrl.enter="keyupCtrlEnter && keyupCtrlEnter()"/>
<div style="position:relative;" v-if="candidates">
<div class="autocomplete-panel">
<div v-for="candidate in candidates" @click="replace(candidate.utf || (candidate.screen_name + ' '))">
<div class="autocomplete" :class="{ highlighted: candidate.highlighted }">
<span v-if="candidate.img"><img :src="candidate.img"></img></span>
<span v-else>{{candidate.utf}}</span>
<span>{{candidate.screen_name}}<small>{{candidate.name}}</small></span>
</div>
</div>
</div>
</div>
</div>
</template>
<script src="./autocomplete_input.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.autocomplete-panel {
margin: 0 0.5em 0 0.5em;
border-radius: $fallback--tooltipRadius;
border-radius: var(--tooltipRadius, $fallback--tooltipRadius);
position: absolute;
z-index: 1;
box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5);
// this doesn't match original but i don't care, making it uniform.
box-shadow: var(--popupShadow);
min-width: 75%;
background: $fallback--bg;
background: var(--bg, $fallback--bg);
color: $fallback--lightText;
color: var(--lightText, $fallback--lightText);
}
.autocomplete {
cursor: pointer;
padding: 0.2em 0.4em 0.2em 0.4em;
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
display: flex;
img {
width: 24px;
height: 24px;
border-radius: $fallback--avatarRadius;
border-radius: var(--avatarRadius, $fallback--avatarRadius);
object-fit: contain;
}
span {
line-height: 24px;
margin: 0 0.1em 0 0.2em;
}
small {
margin-left: .5em;
color: $fallback--faint;
color: var(--faint, $fallback--faint);
}
&.highlighted {
background-color: $fallback--fg;
background-color: var(--lightBg, $fallback--fg);
}
}
</style>
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Aug 8, 4:03 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1723257
Default Alt Text
(10 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline
Log In to Comment