From c43ddf6c7b66fd2ccc29dbb7b4ad7bf27c23938d Mon Sep 17 00:00:00 2001 From: notfire Date: Sun, 16 Mar 2025 17:22:22 -0400 Subject: [PATCH] add search pagination (just for statuses) --- .../post_status_form/post_status_form.js | 13 +++++ src/components/search/search.js | 50 ++++++++++++++++++- src/components/search/search.vue | 40 +++++++++++---- .../settings_modal/tabs/general_tab.vue | 39 +++++++++++++++ src/i18n/en.json | 6 +++ src/modules/config.js | 4 ++ src/modules/instance.js | 4 ++ src/modules/statuses.js | 4 +- src/services/api/api.service.js | 6 ++- 9 files changed, 151 insertions(+), 15 deletions(-) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 7653ec5c..d40d2290 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -390,6 +390,19 @@ const PostStatusForm = { return } + switch (newStatus.status) { + case "ENABLESILLYFEATURES=1": + this.$store.dispatch('setOption', { name: 'sillyFeatures', value: true }) + console.log("Silly features ENABLED...") + this.clearStatus() + return + case "ENABLESILLYFEATURES=0": + this.$store.dispatch('setOption', { name: 'sillyFeatures', value: false }) + console.log("Silly features DISABLED...") + this.clearStatus() + return + } + const poll = this.pollFormVisible ? this.newStatus.poll : {} if (this.pollContentError) { this.error = this.pollContentError diff --git a/src/components/search/search.js b/src/components/search/search.js index 76ac30ef..7b220983 100644 --- a/src/components/search/search.js +++ b/src/components/search/search.js @@ -3,6 +3,7 @@ import Conversation from '../conversation/conversation.vue' import Status from '../status/status.vue' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx' import map from 'lodash/map' +import { throttle } from 'lodash' import { library } from '@fortawesome/fontawesome-svg-core' import { faCircleNotch, @@ -73,14 +74,58 @@ const Search = { this.hashtags = [] this.$refs.searchInput.blur() - this.$store.dispatch('search', { q: query, resolve: true }) + this.$store.dispatch('search', { q: query, resolve: true, limit: this.$store.getters.mergedConfig.searchPaginationLimit }) .then(data => { this.loading = false this.userIds = map(data.accounts, 'id') + if (data.statuses.length < 20) + this.bottomedOut = true + else + this.bottomedOut = false this.statuses = data.statuses this.hashtags = data.hashtags this.currenResultTab = this.getActiveTab() this.loaded = true + + if (this.$store.getters.mergedConfig.recurseSearch) { + this.fetchMorePosts(this.visibleStatuses.length) + } + }) + }, + searchWithOffset (query, offset) { + if (!query) { + this.loading = false + return + } + + this.loading = true + this.userIds = [] + this.hashtags = [] + this.$refs.searchInput.blur() + + this.$store.dispatch('search', { + q: query, + resolve: true, + offset: offset, + max_id: this.statuses[this.statuses.length - 1]["id"], + limit: this.$store.getters.mergedConfig.searchPaginationLimit + }).then(data => { + console.log(this.$store) + this.loading = false + this.userIds = map(data.accounts, 'id') + if (data.statuses.length < this.$store.getters.mergedConfig.searchPaginationLimit) + this.bottomedOut = true + else + this.bottomedOut = false + data.statuses.forEach(element => { + this.statuses.push(element) + }) + this.hashtags = data.hashtags + this.currenResultTab = this.getActiveTab() + this.loaded = true + if (this.$store.getters.mergedConfig.recurseSearch && !this.bottomedOut && (this.visibleStatuses.length < this.$store.getters.mergedConfig.recurseSearchLimit)) { + this.fetchMorePosts(this.visibleStatuses.length) + } }) }, resultCount (tabName) { @@ -103,6 +148,9 @@ const Search = { }, lastHistoryRecord (hashtag) { return hashtag.history && hashtag.history[0] + }, + fetchMorePosts(offset) { + this.searchWithOffset(this.query, offset) } } } diff --git a/src/components/search/search.vue b/src/components/search/search.vue index b7bfc1f3..321958e6 100644 --- a/src/components/search/search.vue +++ b/src/components/search/search.vue @@ -21,17 +21,7 @@ -
- -
-
+
+ +
+
  • + + {{ $t('settings.search_pagination_limit') }} + +
  • {{ $t('settings.columns') }}

  • @@ -697,6 +707,35 @@
    +
    +
    +

    {{ $t('settings.silly_features') }}

    +
      +
    • + + {{ $t('settings.recurse_search') }} + +
        +
      • + + {{ $t('settings.recurse_search_limit') }} + +
      • +
      +
    • +
    +
    +
    diff --git a/src/i18n/en.json b/src/i18n/en.json index 98d5443f..6a4e90db 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -452,7 +452,9 @@ }, "search": { "hashtags": "Hashtags", + "no_more_posts": "No more posts", "no_results": "No results", + "load_older": "Load older posts", "people": "People", "people_talking": "{count} people talking", "person_talking": "{count} person talking" @@ -717,6 +719,8 @@ }, "profile_tab": "Profile", "radii_help": "Set up interface edge rounding (in pixels)", + "recurse_search": "When searching, run searches until no results are found anymore", + "recurse_search_limit": "Number of posts to stop recurse searching at (>300 will cause massive performance issues)", "refresh_token": "Refresh token", "remove_alias": "Remove this alias", "remove_backup": "Remove", @@ -740,6 +744,7 @@ "saving_err": "Error saving settings", "saving_ok": "Settings saved", "scope_copy": "Copy scope when replying (DMs are always copied)", + "search_pagination_limit": "Results to show per search page", "search_user_to_block": "Search whom you want to block", "search_user_to_mute": "Search whom you want to mute", "security": "Security", @@ -774,6 +779,7 @@ "show_page_backgrounds": "Show page-specific backgrounds, e.g. for user profiles", "show_wider_shortcuts": "Show wider gap between top panel shortcuts", "show_yous": "Show (You)s", + "silly_features": "Silly features", "sound_on_notification": "Play a sound when you get a notification", "sound_on_notification_custom": "Custom sounds", "sound_on_notification_custom_exp": "Put URLs to custom sounds in this box, one line for each. If you want one sound to have a different volume, put a semicolon after the link and the volume as a number between 0 and 1. If you want a sound to affect a certain user, use a second semicolon and then their ID.", diff --git a/src/modules/config.js b/src/modules/config.js index a81035dc..c54d95ce 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -122,6 +122,10 @@ export const defaultState = { soundOnNotifVolume: 0.2, soundOnNotifCustom: '', boostsFollowDefVis: false, + searchPaginationLimit: 40, + sillyFeatures: false, + recurseSearch: false, + recurseSearchLimit: 100, renderMisskeyMarkdown: undefined, renderMfmOnHover: undefined, // instance default conversationDisplay: undefined, // instance default diff --git a/src/modules/instance.js b/src/modules/instance.js index b249b2e8..5715e87b 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -78,6 +78,10 @@ const defaultState = { soundOnNotifCustom: '', boostsFollowDefVis: false, deletePostsStreaming: true, + searchPaginationLimit: 40, + sillyFeatures: false, + recurseSearch: false, + recurseSearchLimit: 100, renderMisskeyMarkdown: true, renderMfmOnHover: false, conversationDisplay: 'linear', diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 604fb464..4c0fee7e 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -772,8 +772,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, type }) { - return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following, type }) + search (store, { q, resolve, limit, offset, following, type, max_id }) { + return store.rootState.api.backendInteractor.search2({ q, resolve, limit, offset, following, type, max_id }) .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 index 5c7d71be..78395e3c 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -1402,7 +1402,7 @@ const searchUsers = ({ credentials, query }) => { .then((data) => data.map(parseUser)) } -const search2 = ({ credentials, q, resolve, limit, offset, following, type }) => { +const search2 = ({ credentials, q, resolve, limit, offset, following, type, max_id }) => { let url = MASTODON_SEARCH_2 let params = [] @@ -1430,6 +1430,10 @@ const search2 = ({ credentials, q, resolve, limit, offset, following, type }) => params.push(['type', type]) } + if (max_id) { + params.push(['max_id', max_id]) + } + params.push(['with_relationships', true]) let queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')