import FollowCard from '../follow_card/follow_card.vue' 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 { library } from '@fortawesome/fontawesome-svg-core' import { faCircleNotch, faSearch } from '@fortawesome/free-solid-svg-icons' import { uniqBy } from 'lodash' library.add( faCircleNotch, faSearch ) const Search = { components: { FollowCard, Conversation, Status, TabSwitcher }, props: [ 'query' ], data () { return { loadedInitially: false, loading: false, searchTerm: this.query || '', userIds: [], statuses: [], media: [], hashtags: [], currenResultTab: 'statuses', preferredTab : 'statuses', statusesOffset: 0, lastStatusFetchCount: 0, mediaOffset: 0, lastMediaFetchCount: 0, lastQuery: '' } }, computed: { users () { return this.userIds.map(userId => this.$store.getters.findUser(userId)) }, visibleStatuses () { const allStatusesObject = this.$store.state.statuses.allStatusesObject return this.statuses.filter(status => allStatusesObject[status.id] && !allStatusesObject[status.id].deleted ) }, visibleMedia () { const allStatusesObject = this.$store.state.statuses.allStatusesObject return this.media.filter(status => allStatusesObject[status.id] && !allStatusesObject[status.id].deleted ) }, canSearchMediaPosts () { return this.$store.state.instance.searchTypeMediaEnabled === true } }, mounted () { this.search(this.query) }, watch: { query (newValue) { this.searchTerm = newValue this.search(newValue) } }, methods: { newQuery (query) { this.$router.push({ name: 'search', query: { query } }) this.$refs.searchInput.focus() }, search (query, searchType = null) { if (!query) { this.loading = false return } const isNewSearch = this.lastQuery !== query this.loading = true this.$refs.searchInput.blur() if (isNewSearch) { this.userIds = [] this.hashtags = [] this.statuses = [] this.media = [] this.statusesOffset = 0 this.lastStatusFetchCount = 0 this.mediaOffset = 0 this.lastMediaFetchCount = 0 } let searchOffset if (searchType === 'statuses') { searchOffset = this.statusesOffset } else if (searchType === 'media') { searchOffset = this.mediaOffset } this.$store.dispatch('search', { q: query, resolve: true, offset: searchOffset, 'type': searchType, }) .then(data => { this.loading = false let oldStasusesLength = this.statuses.length let oldMediaLength = this.media.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') if ('media' in data) { this.media = uniqBy(this.media.concat(data.media), 'id') } this.hashtags = this.hashtags.concat(data.hashtags) if (isNewSearch) { this.currenResultTab = this.getActiveTab() } this.loadedInitially = true if (!searchType || searchType === 'statuses') { // 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 - oldStasusesLength } if (!searchType || searchType === 'media') { this.mediaOffset = this.media.length this.lastMediaFetchCount = this.media.length - oldMediaLength } this.lastQuery = query }) }, resultCount (tabName) { const length = this[tabName].length if (length === 0 || !this.loadedInitially) { return '' } if ( (tabName === 'visibleStatuses' && this.lastStatusFetchCount !== 0) || (tabName === 'visibleMedia' && this.lastMediaFetchCount !== 0) ) { return ` (${length}+)` } return ` (${length})` }, onResultTabSwitch (key) { this.currenResultTab = key this.preferredTab = key this.loading = false }, getActiveTab () { const available = { statuses: this.visibleStatuses.length > 0, media: this.visibleMedia.length > 0, people: this.users.length > 0, hashtags: this.hashtags.length > 0, } if (available[this.preferredTab]) { return this.preferredTab } const tabOrder = ['statuses', 'media', 'people', 'hashtags'] for (const tab of tabOrder) { if (available[tab]) { return tab } } return 'statuses' }, lastHistoryRecord (hashtag) { return hashtag.history && hashtag.history[0] } } } export default Search