Add Autocomplete for hashtags + mentions

This commit is contained in:
Daniel Supernault 2021-03-01 22:04:46 -07:00
parent 77e1115740
commit de514f7d76
No known key found for this signature in database
GPG key ID: 0DEF1C662C9033F7
4 changed files with 138 additions and 55 deletions

View file

@ -295,7 +295,9 @@
<div class="media-body"> <div class="media-body">
<div class="form-group"> <div class="form-group">
<label class="font-weight-bold text-muted small d-none">Caption</label> <label class="font-weight-bold text-muted small d-none">Caption</label>
<textarea class="form-control border-0 rounded-0 no-focus" rows="3" placeholder="Write a caption..." style="" v-model="composeText" v-on:keyup="composeTextLength = composeText.length"></textarea> <vue-tribute :options="tributeSettings">
<textarea class="form-control border-0 rounded-0 no-focus" rows="3" placeholder="Write a caption..." style="" v-model="composeText" v-on:keyup="composeTextLength = composeText.length"></textarea>
</vue-tribute>
<p class="help-text small text-right text-muted mb-0">{{composeTextLength}}/{{config.uploader.max_caption_length}}</p> <p class="help-text small text-right text-muted mb-0">{{composeTextLength}}/{{config.uploader.max_caption_length}}</p>
</div> </div>
</div> </div>
@ -647,11 +649,14 @@ import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css'; import 'cropperjs/dist/cropper.css';
import Autocomplete from '@trevoreyre/autocomplete-vue' import Autocomplete from '@trevoreyre/autocomplete-vue'
import '@trevoreyre/autocomplete-vue/dist/style.css' import '@trevoreyre/autocomplete-vue/dist/style.css'
import VueTribute from 'vue-tribute'
export default { export default {
components: { components: {
VueCropper, VueCropper,
Autocomplete Autocomplete,
VueTribute
}, },
data() { data() {
@ -707,7 +712,39 @@ export default {
cameraRollMedia: [], cameraRollMedia: [],
taggedUsernames: [], taggedUsernames: [],
taggedPeopleSearch: null, taggedPeopleSearch: null,
textMode: false textMode: false,
tributeSettings: {
collection: [
{
trigger: '@',
menuShowMinLength: 2,
values: (function (text, cb) {
let url = '/api/compose/v0/search/mention';
axios.get(url, { params: { q: text }})
.then(res => {
cb(res.data);
})
.catch(err => {
console.log(err);
})
})
},
{
trigger: '#',
menuShowMinLength: 2,
values: (function (text, cb) {
let url = '/api/compose/v0/search/hashtag';
axios.get(url, { params: { q: text }})
.then(res => {
cb(res.data);
})
.catch(err => {
console.log(err);
})
})
}
]
}
} }
}, },

View file

@ -643,8 +643,10 @@
size="md" size="md"
body-class="p-2 rounded"> body-class="p-2 rounded">
<div> <div>
<textarea class="form-control" rows="4" style="border: none; font-size: 18px; resize: none; white-space: pre-wrap;outline: none;" placeholder="Reply here ..." v-model="replyText"> <vue-tribute :options="tributeSettings">
</textarea> <textarea class="form-control" rows="4" style="border: none; font-size: 18px; resize: none; white-space: pre-wrap;outline: none;" placeholder="Reply here ..." v-model="replyText">
</textarea>
</vue-tribute>
<div class="border-top border-bottom my-2"> <div class="border-top border-bottom my-2">
<ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;"> <ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
@ -757,10 +759,12 @@
</style> </style>
<script> <script>
import VueTribute from 'vue-tribute'
pixelfed.postComponent = {}; pixelfed.postComponent = {};
export default { export default {
props: [ props: [
'status-id', 'status-id',
'status-username', 'status-username',
@ -771,6 +775,11 @@ export default {
'status-profile-id', 'status-profile-id',
'profile-layout' 'profile-layout'
], ],
components: {
VueTribute
},
data() { data() {
return { return {
config: window.App.config, config: window.App.config,
@ -817,6 +826,38 @@ export default {
profileMorePosts: [], profileMorePosts: [],
replySending: false, replySending: false,
reactionBarLoading: true, reactionBarLoading: true,
tributeSettings: {
collection: [
{
trigger: '@',
menuShowMinLength: 2,
values: (function (text, cb) {
let url = '/api/compose/v0/search/mention';
axios.get(url, { params: { q: text }})
.then(res => {
cb(res.data);
})
.catch(err => {
console.log(err);
})
})
},
{
trigger: '#',
menuShowMinLength: 2,
values: (function (text, cb) {
let url = '/api/compose/v0/search/hashtag';
axios.get(url, { params: { q: text }})
.then(res => {
cb(res.data);
})
.catch(err => {
console.log(err);
})
})
}
]
}
} }
}, },
watch: { watch: {

View file

@ -2224,52 +2224,3 @@
box-shadow: none; box-shadow: none;
} }
</style> </style>
<style type="text/css">
.tribute-container {
position: absolute;
top: 0;
left: 0;
height: auto;
max-height: 300px;
min-width: 120px;
max-width: 100vw;
overflow: auto;
display: block;
z-index: 999999;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(#000, 0.13);
}
.tribute-container ul {
margin: 0;
margin-top: 2px;
padding: 0;
list-style: none;
background: #fff;
border-radius: 4px;
border: 1px solid rgba(#000, 0.13);
background-clip: padding-box;
overflow: hidden;
}
.tribute-container li {
color: #000;
padding: 5px 15px;
cursor: pointer;
font-size: 14px;
overflow-x: hidden !important;
}
.tribute-container li.highlight,
.tribute-container li:hover {
background: #2c78bf;
color: #fff;
}
.tribute-container li span {
font-weight: bold;
}
.tribute-container li.no-match {
cursor: default;
}
.tribute-container .menu-highlighted {
font-weight: bold;
}
</style>

View file

@ -594,4 +594,58 @@ details summary::-webkit-details-marker {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.tribute-container {
position: absolute;
top: 0;
left: 0;
height: auto;
max-height: 300px;
min-width: 120px;
max-width: 100vw;
overflow: auto;
display: block;
z-index: 999999;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(#000, 0.13);
}
.tribute-container ul {
margin: 0;
margin-top: 2px;
padding: 0;
list-style: none;
background: #fff;
border-radius: 4px;
border: 1px solid rgba(#000, 0.13);
background-clip: padding-box;
overflow: hidden;
}
.tribute-container li {
color: #000;
padding: 5px 15px;
cursor: pointer;
font-size: 14px;
overflow-x: hidden !important;
}
.tribute-container li.highlight,
.tribute-container li:hover {
background: #2c78bf;
color: #fff;
}
.tribute-container li span {
font-weight: bold;
}
.tribute-container li.no-match {
cursor: default;
}
.tribute-container .menu-highlighted {
font-weight: bold;
}