Browse Source

Merge pull request #2695 from pixelfed/staging

Add Autocomplete (hashtags + mentions)
daniel 4 years ago
parent
commit
e25600cdc6

+ 1 - 0
CHANGELOG.md

@@ -2,6 +2,7 @@
 
 ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.10.10...dev)
 ### Added
+- Autocomplete Support (hashtags + mentions) ([de514f7d](https://github.com/pixelfed/pixelfed/commit/de514f7d))
 
 ### Updated
 - Updated AdminController, fix variable name in updateSpam method. ([6edaf940](https://github.com/pixelfed/pixelfed/commit/6edaf940))

BIN
public/css/app.css


BIN
public/css/appdark.css


BIN
public/css/landing.css


BIN
public/js/compose.js


BIN
public/js/status.js


BIN
public/js/timeline.js


BIN
public/mix-manifest.json


+ 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>

+ 54 - 1
resources/assets/sass/appdark.scss

@@ -153,4 +153,57 @@ hr {
 
 .border {
 	border-color: #282828 !important;
-}
+}
+
+.tribute-container {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: auto;
+    max-height: 300px;
+    min-width: 120px;
+    max-width: 500px;
+    overflow: auto;
+    display: block;
+    z-index: 999999;
+    border-radius: 4px;
+    border: 1px solid #282828;
+
+    ul {
+      margin: 0;
+      margin-top: 2px;
+      padding: 0;
+      list-style: none;
+      background: #181818;
+      border-radius: 4px;
+      border: 1px solid #282828;
+      background-clip: padding-box;
+      overflow: hidden;
+    }
+
+    li {
+        color: #ADAFAE;
+        padding: 5px 15px;
+        cursor: pointer;
+        font-size: 14px;
+        overflow-x: hidden !important;
+        
+        span {
+          font-weight: bold;
+        }
+
+        &.highlight,
+        &:hover {
+            background: #11304c;
+            color: #fff;
+        }
+
+        &.no-match {
+            cursor: default;
+        }
+    }
+
+    .menu-highlighted {
+        font-weight: bold;
+    }
+}

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

@@ -594,4 +594,54 @@ 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: 500px;
+    overflow: auto;
+    display: block;
+    z-index: 999999;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    box-shadow: 0 1px 4px rgba(#000, 0.13);
+    
+    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;
+    }
+
+    li {
+        color: #000;
+        padding: 5px 15px;
+        cursor: pointer;
+        font-size: 14px;
+        overflow-x: hidden !important;
+        
+        &.highlight,
+        &:hover {
+            background: #2c78bf;
+            color: #fff;
+        }
+        
+        &.no-match {
+            cursor: default;
+        }
+    }
+
+    .menu-highlighted {
+        font-weight: bold;
+    }
+}