Browse Source

Merge branch 'search-pagination' into 'develop'

Implement loading more statuses when searching

See merge request pleroma/pleroma-fe!1410
HJ 2 years ago
parent
commit
d1885d45e7

+ 30 - 9
src/components/search/search.js

@@ -8,6 +8,7 @@ import {
   faCircleNotch,
   faCircleNotch,
   faSearch
   faSearch
 } from '@fortawesome/free-solid-svg-icons'
 } from '@fortawesome/free-solid-svg-icons'
+import { uniqBy } from 'lodash'
 
 
 library.add(
 library.add(
   faCircleNotch,
   faCircleNotch,
@@ -32,7 +33,11 @@ const Search = {
       userIds: [],
       userIds: [],
       statuses: [],
       statuses: [],
       hashtags: [],
       hashtags: [],
-      currenResultTab: 'statuses'
+      currenResultTab: 'statuses',
+
+      statusesOffset: 0,
+      lastStatusFetchCount: 0,
+      lastQuery: ''
     }
     }
   },
   },
   computed: {
   computed: {
@@ -61,26 +66,42 @@ const Search = {
       this.$router.push({ name: 'search', query: { query } })
       this.$router.push({ name: 'search', query: { query } })
       this.$refs.searchInput.focus()
       this.$refs.searchInput.focus()
     },
     },
-    search (query) {
+    search (query, searchType = null) {
       if (!query) {
       if (!query) {
         this.loading = false
         this.loading = false
         return
         return
       }
       }
 
 
       this.loading = true
       this.loading = true
-      this.userIds = []
-      this.statuses = []
-      this.hashtags = []
       this.$refs.searchInput.blur()
       this.$refs.searchInput.blur()
+      if (this.lastQuery !== query) {
+        this.userIds = []
+        this.hashtags = []
+        this.statuses = []
+
+        this.statusesOffset = 0
+        this.lastStatusFetchCount = 0
+      }
 
 
-      this.$store.dispatch('search', { q: query, resolve: true })
+      this.$store.dispatch('search', { q: query, resolve: true, offset: this.statusesOffset, 'type': searchType })
         .then(data => {
         .then(data => {
           this.loading = false
           this.loading = false
-          this.userIds = map(data.accounts, 'id')
-          this.statuses = data.statuses
-          this.hashtags = data.hashtags
+
+          let oldLength = this.statuses.length
+
+          // Always append to old results. If new results are empty, this doesn't change anything
+          this.userIds = this.userIds.concat(map(data.accounts, 'id'))
+          this.statuses = uniqBy(this.statuses.concat(data.statuses), 'id')
+          this.hashtags = this.hashtags.concat(data.hashtags)
+
           this.currenResultTab = this.getActiveTab()
           this.currenResultTab = this.getActiveTab()
           this.loaded = true
           this.loaded = true
+
+          // Offset from whatever we already have
+          this.statusesOffset = this.statuses.length
+          // Because the amount of new statuses can actually be zero, compare to old lenght instead
+          this.lastStatusFetchCount = this.statuses.length - oldLength
+          this.lastQuery = query
         })
         })
     },
     },
     resultCount (tabName) {
     resultCount (tabName) {

+ 34 - 8
src/components/search/search.vue

@@ -22,7 +22,7 @@
       </button>
       </button>
     </div>
     </div>
     <div
     <div
-      v-if="loading"
+      v-if="loading && statusesOffset == 0"
       class="text-center loading-icon"
       class="text-center loading-icon"
     >
     >
       <FAIcon
       <FAIcon
@@ -55,12 +55,6 @@
     </div>
     </div>
     <div class="panel-body">
     <div class="panel-body">
       <div v-if="currenResultTab === 'statuses'">
       <div v-if="currenResultTab === 'statuses'">
-        <div
-          v-if="visibleStatuses.length === 0 && !loading && loaded"
-          class="search-result-heading"
-        >
-          <h4>{{ $t('search.no_results') }}</h4>
-        </div>
         <Status
         <Status
           v-for="status in visibleStatuses"
           v-for="status in visibleStatuses"
           :key="status.id"
           :key="status.id"
@@ -71,6 +65,33 @@
           :statusoid="status"
           :statusoid="status"
           :no-heading="false"
           :no-heading="false"
         />
         />
+        <button
+          v-if="!loading && loaded && lastStatusFetchCount > 0"
+          class="more-statuses-button button-unstyled -link -fullwidth"
+          @click.prevent="search(searchTerm, 'statuses')"
+        >
+          <div class="new-status-notification text-center">
+            {{ $t('search.load_more') }}
+          </div>
+        </button>
+        <div
+          v-else-if="loading && statusesOffset > 0"
+          class="text-center loading-icon"
+        >
+          <FAIcon
+            icon="circle-notch"
+            spin
+            size="lg"
+          />
+        </div>
+        <div
+          v-if="(visibleStatuses.length === 0 || lastStatusFetchCount === 0) && !loading && loaded"
+          class="search-result-heading"
+        >
+          <h4>
+            {{ visibleStatuses.length === 0 ? $t('search.no_results') : $t('search.no_more_results') }}
+          </h4>
+        </div>
       </div>
       </div>
       <div v-else-if="currenResultTab === 'people'">
       <div v-else-if="currenResultTab === 'people'">
         <div
         <div
@@ -208,6 +229,11 @@
     color: $fallback--text;
     color: $fallback--text;
     color: var(--text, $fallback--text);
     color: var(--text, $fallback--text);
   }
   }
-}
+  }
+
+  .more-statuses-button {
+    height: 3.5em;
+    line-height: 3.5em;
+  }
 
 
 </style>
 </style>

+ 3 - 1
src/i18n/en.json

@@ -986,7 +986,9 @@
     "hashtags": "Hashtags",
     "hashtags": "Hashtags",
     "person_talking": "{count} person talking",
     "person_talking": "{count} person talking",
     "people_talking": "{count} people talking",
     "people_talking": "{count} people talking",
-    "no_results": "No results"
+    "no_results": "No results",
+    "no_more_results": "No more results",
+    "load_more": "Load more results"
   },
   },
   "password_reset": {
   "password_reset": {
     "forgot_password": "Forgot password?",
     "forgot_password": "Forgot password?",

+ 2 - 2
src/modules/statuses.js

@@ -761,8 +761,8 @@ const statuses = {
       rootState.api.backendInteractor.fetchRebloggedByUsers({ id })
       rootState.api.backendInteractor.fetchRebloggedByUsers({ id })
         .then(rebloggedByUsers => commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser }))
         .then(rebloggedByUsers => commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser }))
     },
     },
-    search (store, { q, resolve, limit, offset, following }) {
-      return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following })
+    search (store, { q, resolve, limit, offset, following, type }) {
+      return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following, type })
         .then((data) => {
         .then((data) => {
           store.commit('addNewUsers', data.accounts)
           store.commit('addNewUsers', data.accounts)
           store.commit('addNewStatuses', { statuses: data.statuses })
           store.commit('addNewStatuses', { statuses: data.statuses })

+ 5 - 1
src/services/api/api.service.js

@@ -1278,7 +1278,7 @@ const searchUsers = ({ credentials, query }) => {
     .then((data) => data.map(parseUser))
     .then((data) => data.map(parseUser))
 }
 }
 
 
-const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
+const search2 = ({ credentials, q, resolve, limit, offset, following, type }) => {
   let url = MASTODON_SEARCH_2
   let url = MASTODON_SEARCH_2
   const params = []
   const params = []
 
 
@@ -1302,6 +1302,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => {
     params.push(['following', true])
     params.push(['following', true])
   }
   }
 
 
+  if (type) {
+    params.push(['following', type])
+  }
+
   params.push(['with_relationships', true])
   params.push(['with_relationships', true])
 
 
   const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
   const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')