Add support for searching media status
w/ some refactors i've also tried to maintain support for backends that don't have media status search support
This commit is contained in:
parent
20cf8f978b
commit
4306c9ff6c
3 changed files with 125 additions and 30 deletions
|
@ -27,16 +27,20 @@ const Search = {
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loaded: false,
|
loadedInitially: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
searchTerm: this.query || '',
|
searchTerm: this.query || '',
|
||||||
|
mediaSearchSupported: false,
|
||||||
userIds: [],
|
userIds: [],
|
||||||
statuses: [],
|
statuses: [],
|
||||||
|
media: [],
|
||||||
hashtags: [],
|
hashtags: [],
|
||||||
currenResultTab: 'statuses',
|
currenResultTab: 'statuses',
|
||||||
|
|
||||||
statusesOffset: 0,
|
statusesOffset: 0,
|
||||||
lastStatusFetchCount: 0,
|
lastStatusFetchCount: 0,
|
||||||
|
mediaOffset: 0,
|
||||||
|
lastMediaFetchCount: 0,
|
||||||
lastQuery: ''
|
lastQuery: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -50,6 +54,13 @@ const Search = {
|
||||||
return this.statuses.filter(status =>
|
return this.statuses.filter(status =>
|
||||||
allStatusesObject[status.id] && !allStatusesObject[status.id].deleted
|
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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -72,61 +83,92 @@ const Search = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isNewSearch = this.lastQuery !== query
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.$refs.searchInput.blur()
|
this.$refs.searchInput.blur()
|
||||||
if (this.lastQuery !== query) {
|
if (isNewSearch) {
|
||||||
this.userIds = []
|
this.userIds = []
|
||||||
this.hashtags = []
|
this.hashtags = []
|
||||||
this.statuses = []
|
this.statuses = []
|
||||||
|
this.media = []
|
||||||
|
|
||||||
this.statusesOffset = 0
|
this.statusesOffset = 0
|
||||||
this.lastStatusFetchCount = 0
|
this.lastStatusFetchCount = 0
|
||||||
|
this.mediaOffset = 0
|
||||||
|
this.lastMediaFetchCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.dispatch('search', { q: query, resolve: true, offset: this.statusesOffset, 'type': searchType })
|
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 => {
|
.then(data => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
||||||
let oldLength = this.statuses.length
|
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
|
// 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.userIds = this.userIds.concat(map(data.accounts, 'id'))
|
||||||
this.statuses = uniqBy(this.statuses.concat(data.statuses), 'id')
|
this.statuses = uniqBy(this.statuses.concat(data.statuses), 'id')
|
||||||
|
if ('media' in data) {
|
||||||
|
this.mediaSearchSupported = true
|
||||||
|
this.media = uniqBy(this.media.concat(data.media), 'id')
|
||||||
|
}
|
||||||
this.hashtags = this.hashtags.concat(data.hashtags)
|
this.hashtags = this.hashtags.concat(data.hashtags)
|
||||||
|
|
||||||
this.currenResultTab = this.getActiveTab()
|
if (isNewSearch) {
|
||||||
this.loaded = true
|
this.currenResultTab = this.getActiveTab()
|
||||||
|
}
|
||||||
|
this.loadedInitially = true
|
||||||
|
|
||||||
// Offset from whatever we already have
|
if (!searchType || searchType === 'statuses') {
|
||||||
this.statusesOffset = this.statuses.length
|
// Offset from whatever we already have
|
||||||
// Because the amount of new statuses can actually be zero, compare to old lenght instead
|
this.statusesOffset = this.statuses.length
|
||||||
this.lastStatusFetchCount = this.statuses.length - oldLength
|
// 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
|
this.lastQuery = query
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
resultCount (tabName) {
|
resultCount (tabName) {
|
||||||
const length = this[tabName].length
|
const length = this[tabName].length
|
||||||
return (
|
|
||||||
length === 0
|
if (length === 0 || !this.loadedInitially) {
|
||||||
? ''
|
return ''
|
||||||
: ` (${
|
}
|
||||||
length + (
|
|
||||||
tabName === "visibleStatuses" &&
|
if (
|
||||||
this.lastStatusFetchCount !== 0 &&
|
(tabName === 'visibleStatuses' && this.lastStatusFetchCount !== 0) ||
|
||||||
!this.loading &&
|
(tabName === 'visibleMedia' && this.lastMediaFetchCount !== 0)
|
||||||
this.loaded
|
) {
|
||||||
? '+'
|
return ` (${length}+)`
|
||||||
: ''
|
}
|
||||||
)
|
|
||||||
})`
|
return ` (${length})`
|
||||||
)
|
|
||||||
},
|
},
|
||||||
onResultTabSwitch (key) {
|
onResultTabSwitch (key) {
|
||||||
this.currenResultTab = key
|
this.currenResultTab = key
|
||||||
|
this.loading = false
|
||||||
},
|
},
|
||||||
getActiveTab () {
|
getActiveTab () {
|
||||||
if (this.visibleStatuses.length > 0) {
|
if (this.visibleStatuses.length > 0) {
|
||||||
return 'statuses'
|
return 'statuses'
|
||||||
|
} else if (this.visibleMedia.length > 0) {
|
||||||
|
return 'media'
|
||||||
} else if (this.users.length > 0) {
|
} else if (this.users.length > 0) {
|
||||||
return 'people'
|
return 'people'
|
||||||
} else if (this.hashtags.length > 0) {
|
} else if (this.hashtags.length > 0) {
|
||||||
|
|
|
@ -24,7 +24,13 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="loading && statusesOffset == 0"
|
v-if="
|
||||||
|
loading &&
|
||||||
|
visibleStatuses.length === 0 &&
|
||||||
|
visibleMedia.length === 0 &&
|
||||||
|
users.length === 0 &&
|
||||||
|
hashtags.length === 0
|
||||||
|
"
|
||||||
class="text-center loading-icon"
|
class="text-center loading-icon"
|
||||||
>
|
>
|
||||||
<FAIcon
|
<FAIcon
|
||||||
|
@ -33,7 +39,7 @@
|
||||||
size="lg"
|
size="lg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="loaded">
|
<div v-else-if="loadedInitially">
|
||||||
<div class="search-nav-heading">
|
<div class="search-nav-heading">
|
||||||
<tab-switcher
|
<tab-switcher
|
||||||
ref="tabSwitcher"
|
ref="tabSwitcher"
|
||||||
|
@ -44,6 +50,11 @@
|
||||||
key="statuses"
|
key="statuses"
|
||||||
:label="$t('user_card.statuses') + resultCount('visibleStatuses')"
|
:label="$t('user_card.statuses') + resultCount('visibleStatuses')"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
v-if="mediaSearchSupported"
|
||||||
|
key="media"
|
||||||
|
:label="$t('user_card.media') + resultCount('visibleMedia')"
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
key="people"
|
key="people"
|
||||||
:label="$t('search.people') + resultCount('users')"
|
:label="$t('search.people') + resultCount('users')"
|
||||||
|
@ -68,7 +79,7 @@
|
||||||
:no-heading="false"
|
:no-heading="false"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="!loading && loaded && lastStatusFetchCount > 0"
|
v-if="!loading && loadedInitially && lastStatusFetchCount > 0"
|
||||||
class="more-statuses-button button-unstyled -link -fullwidth"
|
class="more-statuses-button button-unstyled -link -fullwidth"
|
||||||
@click.prevent="search(searchTerm, 'statuses')"
|
@click.prevent="search(searchTerm, 'statuses')"
|
||||||
>
|
>
|
||||||
|
@ -87,7 +98,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="(visibleStatuses.length === 0 || lastStatusFetchCount === 0) && !loading && loaded"
|
v-if="(visibleStatuses.length === 0 || lastStatusFetchCount === 0) && !loading && loadedInitially"
|
||||||
class="search-result-heading"
|
class="search-result-heading"
|
||||||
>
|
>
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -95,9 +106,48 @@
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="currenResultTab === 'media'">
|
||||||
|
<Status
|
||||||
|
v-for="media in visibleMedia"
|
||||||
|
:key="media.id"
|
||||||
|
:collapsable="false"
|
||||||
|
:expandable="false"
|
||||||
|
:compact="false"
|
||||||
|
class="search-result"
|
||||||
|
:statusoid="media"
|
||||||
|
:no-heading="false"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="!loading && loadedInitially && lastMediaFetchCount > 0"
|
||||||
|
class="more-statuses-button button-unstyled -link -fullwidth"
|
||||||
|
@click.prevent="search(searchTerm, 'media')"
|
||||||
|
>
|
||||||
|
<div class="new-status-notification text-center">
|
||||||
|
{{ $t('search.load_more') }}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
v-else-if="loading && mediaOffset > 0"
|
||||||
|
class="text-center loading-icon"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
icon="circle-notch"
|
||||||
|
spin
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="(visibleMedia.length === 0 || lastMediaFetchCount === 0) && !loading && loadedInitially"
|
||||||
|
class="search-result-heading"
|
||||||
|
>
|
||||||
|
<h4>
|
||||||
|
{{ visibleMedia.length === 0 ? $t('search.no_results') : $t('search.no_more_results') }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-else-if="currenResultTab === 'people'">
|
<div v-else-if="currenResultTab === 'people'">
|
||||||
<div
|
<div
|
||||||
v-if="users.length === 0 && !loading && loaded"
|
v-if="users.length === 0 && !loading && loadedInitially"
|
||||||
class="search-result-heading"
|
class="search-result-heading"
|
||||||
>
|
>
|
||||||
<h4>{{ $t('search.no_results') }}</h4>
|
<h4>{{ $t('search.no_results') }}</h4>
|
||||||
|
@ -111,7 +161,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="currenResultTab === 'hashtags'">
|
<div v-else-if="currenResultTab === 'hashtags'">
|
||||||
<div
|
<div
|
||||||
v-if="hashtags.length === 0 && !loading && loaded"
|
v-if="hashtags.length === 0 && !loading && loadedInitially"
|
||||||
class="search-result-heading"
|
class="search-result-heading"
|
||||||
>
|
>
|
||||||
<h4>{{ $t('search.no_results') }}</h4>
|
<h4>{{ $t('search.no_results') }}</h4>
|
||||||
|
|
|
@ -1424,6 +1424,9 @@ const search2 = ({ credentials, q, resolve, limit, offset, following, type }) =>
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
data.accounts = data.accounts.slice(0, limit).map(u => parseUser(u))
|
data.accounts = data.accounts.slice(0, limit).map(u => parseUser(u))
|
||||||
data.statuses = data.statuses.slice(0, limit).map(s => parseStatus(s))
|
data.statuses = data.statuses.slice(0, limit).map(s => parseStatus(s))
|
||||||
|
if ('media' in data) {
|
||||||
|
data.media = data.media.slice(0, limit).map(s => parseStatus(s))
|
||||||
|
}
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue