logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: d1885d45e79e313644d24a8741a20265099a129b
parent 72a5eaf40af20275a052a25b7aa911d3ef4bdcd7
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date:   Mon, 21 Nov 2022 19:48:24 +0000

Merge branch 'search-pagination' into 'develop'

Implement loading more statuses when searching

See merge request pleroma/pleroma-fe!1410

Diffstat:

Msrc/components/search/search.js39++++++++++++++++++++++++++++++---------
Msrc/components/search/search.vue42++++++++++++++++++++++++++++++++++--------
Msrc/i18n/en.json4+++-
Msrc/modules/statuses.js4++--
Msrc/services/api/api.service.js6+++++-
5 files changed, 74 insertions(+), 21 deletions(-)

diff --git a/src/components/search/search.js b/src/components/search/search.js @@ -8,6 +8,7 @@ import { faCircleNotch, faSearch } from '@fortawesome/free-solid-svg-icons' +import { uniqBy } from 'lodash' library.add( faCircleNotch, @@ -32,7 +33,11 @@ const Search = { userIds: [], statuses: [], hashtags: [], - currenResultTab: 'statuses' + currenResultTab: 'statuses', + + statusesOffset: 0, + lastStatusFetchCount: 0, + lastQuery: '' } }, computed: { @@ -61,26 +66,42 @@ const Search = { this.$router.push({ name: 'search', query: { query } }) this.$refs.searchInput.focus() }, - search (query) { + search (query, searchType = null) { if (!query) { this.loading = false return } this.loading = true - this.userIds = [] - this.statuses = [] - this.hashtags = [] 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 => { 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.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) { diff --git a/src/components/search/search.vue b/src/components/search/search.vue @@ -22,7 +22,7 @@ </button> </div> <div - v-if="loading" + v-if="loading && statusesOffset == 0" class="text-center loading-icon" > <FAIcon @@ -55,12 +55,6 @@ </div> <div class="panel-body"> <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 v-for="status in visibleStatuses" :key="status.id" @@ -71,6 +65,33 @@ :statusoid="status" :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 v-else-if="currenResultTab === 'people'"> <div @@ -208,6 +229,11 @@ color: $fallback--text; color: var(--text, $fallback--text); } -} + } + + .more-statuses-button { + height: 3.5em; + line-height: 3.5em; + } </style> diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -986,7 +986,9 @@ "hashtags": "Hashtags", "person_talking": "{count} person 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": { "forgot_password": "Forgot password?", diff --git a/src/modules/statuses.js b/src/modules/statuses.js @@ -761,8 +761,8 @@ const statuses = { rootState.api.backendInteractor.fetchRebloggedByUsers({ id }) .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) => { store.commit('addNewUsers', data.accounts) store.commit('addNewStatuses', { statuses: data.statuses }) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js @@ -1278,7 +1278,7 @@ const searchUsers = ({ credentials, query }) => { .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 const params = [] @@ -1302,6 +1302,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following }) => { params.push(['following', true]) } + if (type) { + params.push(['following', type]) + } + params.push(['with_relationships', true]) const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')