Quellcode durchsuchen

Add Autocomplete for hashtags + mentions

Daniel Supernault vor 4 Jahren
Ursprung
Commit
de514f7d76

+ 40 - 3
resources/assets/js/components/ComposeModal.vue

@@ -295,7 +295,9 @@
 								<div class="media-body">
 									<div class="form-group">
 										<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>
 									</div>
 								</div>
@@ -647,11 +649,14 @@ import VueCropper from 'vue-cropperjs';
 import 'cropperjs/dist/cropper.css';
 import Autocomplete from '@trevoreyre/autocomplete-vue'
 import '@trevoreyre/autocomplete-vue/dist/style.css'
+import VueTribute from 'vue-tribute'
 
 export default {
+
 	components: { 
 		VueCropper,
-		Autocomplete 
+		Autocomplete,
+		VueTribute
 	},
 
 	data() {
@@ -707,7 +712,39 @@ export default {
 			cameraRollMedia: [],
 			taggedUsernames: [],
 			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);
+							})
+						})
+					}
+				]
+			}
 		}
 	},
 

+ 43 - 2
resources/assets/js/components/PostComponent.vue

@@ -643,8 +643,10 @@
     size="md"
     body-class="p-2 rounded">
     <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">
-      </textarea>
+      <vue-tribute :options="tributeSettings">
+        <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">
         <ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
@@ -757,10 +759,12 @@
 </style>
 
 <script>
+import VueTribute from 'vue-tribute'
 
 pixelfed.postComponent = {};
 
 export default {
+
     props: [
       'status-id',
       'status-username',
@@ -771,6 +775,11 @@ export default {
       'status-profile-id',
       'profile-layout'
     ],
+
+    components: { 
+        VueTribute
+    },
+
     data() {
         return {
             config: window.App.config,
@@ -817,6 +826,38 @@ export default {
             profileMorePosts: [],
             replySending: false,
             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: {

+ 0 - 49
resources/assets/js/components/Timeline.vue

@@ -2224,52 +2224,3 @@
 		box-shadow: none;
 	}
 </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>

+ 55 - 1
resources/assets/sass/custom.scss

@@ -594,4 +594,58 @@ details summary::-webkit-details-marker {
     width: 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;
+}