logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe
commit: e9b452575b9a5ef87808898086771ae806fc3a8b
parent: 0c064105841608c93649992eeb609e63b73ad595
Author: Shpuld Shpludson <shp@cock.li>
Date:   Mon, 15 Jul 2019 16:42:27 +0000

Merge branch 'new-search' into 'develop'

New search

See merge request pleroma/pleroma-fe!832

Diffstat:

Msrc/App.js12++++++------
Msrc/App.vue6+++---
Msrc/boot/routes.js4++--
Asrc/components/search/search.js98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/search/search.vue211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/search_bar/search_bar.js27+++++++++++++++++++++++++++
Asrc/components/search_bar/search_bar.vue73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/components/side_drawer/side_drawer.vue4++--
Msrc/components/tab_switcher/tab_switcher.js12++++++++++--
Dsrc/components/user_finder/user_finder.js20--------------------
Dsrc/components/user_finder/user_finder.vue67-------------------------------------------------------------------
Dsrc/components/user_search/user_search.js49-------------------------------------------------
Dsrc/components/user_search/user_search.vue57---------------------------------------------------------
Msrc/i18n/en.json8++++++++
Msrc/i18n/ru.json10+++++++++-
Msrc/modules/statuses.js8++++++++
Msrc/services/api/api.service.js54++++++++++++++++++++++++++++++++++++++++++------------
Msrc/services/backend_interactor_service/backend_interactor_service.js6+++---
18 files changed, 502 insertions(+), 224 deletions(-)

diff --git a/src/App.js b/src/App.js @@ -1,7 +1,7 @@ import UserPanel from './components/user_panel/user_panel.vue' import NavPanel from './components/nav_panel/nav_panel.vue' import Notifications from './components/notifications/notifications.vue' -import UserFinder from './components/user_finder/user_finder.vue' +import SearchBar from './components/search_bar/search_bar.vue' import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue' import FeaturesPanel from './components/features_panel/features_panel.vue' import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue' @@ -19,7 +19,7 @@ export default { UserPanel, NavPanel, Notifications, - UserFinder, + SearchBar, InstanceSpecificPanel, FeaturesPanel, WhoToFollowPanel, @@ -32,7 +32,7 @@ export default { }, data: () => ({ mobileActivePanel: 'timeline', - finderHidden: true, + searchBarHidden: true, supportsMask: window.CSS && window.CSS.supports && ( window.CSS.supports('mask-size', 'contain') || window.CSS.supports('-webkit-mask-size', 'contain') || @@ -70,7 +70,7 @@ export default { logoBgStyle () { return Object.assign({ 'margin': `${this.$store.state.instance.logoMargin} 0`, - opacity: this.finderHidden ? 1 : 0 + opacity: this.searchBarHidden ? 1 : 0 }, this.enableMask ? {} : { 'background-color': this.enableMask ? '' : 'transparent' }) @@ -101,8 +101,8 @@ export default { this.$router.replace('/main/public') this.$store.dispatch('logout') }, - onFinderToggled (hidden) { - this.finderHidden = hidden + onSearchBarToggled (hidden) { + this.searchBarHidden = hidden }, updateMobileState () { const mobileLayout = windowWidth() <= 800 diff --git a/src/App.vue b/src/App.vue @@ -38,9 +38,9 @@ </router-link> </div> <div class="item right"> - <user-finder - class="button-icon nav-icon mobile-hidden" - @toggled="onFinderToggled" + <search-bar + class="nav-icon mobile-hidden" + @toggled="onSearchBarToggled" /> <router-link class="mobile-hidden" diff --git a/src/boot/routes.js b/src/boot/routes.js @@ -6,12 +6,12 @@ import ConversationPage from 'components/conversation-page/conversation-page.vue import Interactions from 'components/interactions/interactions.vue' import DMs from 'components/dm_timeline/dm_timeline.vue' import UserProfile from 'components/user_profile/user_profile.vue' +import Search from 'components/search/search.vue' import Settings from 'components/settings/settings.vue' import Registration from 'components/registration/registration.vue' import UserSettings from 'components/user_settings/user_settings.vue' import FollowRequests from 'components/follow_requests/follow_requests.vue' import OAuthCallback from 'components/oauth_callback/oauth_callback.vue' -import UserSearch from 'components/user_search/user_search.vue' import Notifications from 'components/notifications/notifications.vue' import AuthForm from 'components/auth_form/auth_form.js' import ChatPanel from 'components/chat_panel/chat_panel.vue' @@ -45,7 +45,7 @@ export default (store) => { { name: 'login', path: '/login', component: AuthForm }, { name: 'chat', path: '/chat', component: ChatPanel, props: () => ({ floating: false }) }, { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) }, - { name: 'user-search', path: '/user-search', component: UserSearch, props: (route) => ({ query: route.query.query }) }, + { name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) }, { name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow }, { name: 'about', path: '/about', component: About }, { name: 'user-profile', path: '/(users/)?:name', component: UserProfile } diff --git a/src/components/search/search.js b/src/components/search/search.js @@ -0,0 +1,98 @@ +import FollowCard from '../follow_card/follow_card.vue' +import Conversation from '../conversation/conversation.vue' +import Status from '../status/status.vue' +import map from 'lodash/map' + +const Search = { + components: { + FollowCard, + Conversation, + Status + }, + props: [ + 'query' + ], + data () { + return { + loaded: false, + loading: false, + searchTerm: this.query || '', + userIds: [], + statuses: [], + hashtags: [], + currenResultTab: 'statuses' + } + }, + 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 + ) + } + }, + 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) { + if (!query) { + this.loading = false + return + } + + this.loading = true + this.userIds = [] + this.statuses = [] + this.hashtags = [] + this.$refs.searchInput.blur() + + this.$store.dispatch('search', { q: query, resolve: true }) + .then(data => { + this.loading = false + this.userIds = map(data.accounts, 'id') + this.statuses = data.statuses + this.hashtags = data.hashtags + this.currenResultTab = this.getActiveTab() + this.loaded = true + }) + }, + resultCount (tabName) { + const length = this[tabName].length + return length === 0 ? '' : ` (${length})` + }, + onResultTabSwitch (_index, dataset) { + this.currenResultTab = dataset.filter + }, + getActiveTab () { + if (this.visibleStatuses.length > 0) { + return 'statuses' + } else if (this.users.length > 0) { + return 'people' + } else if (this.hashtags.length > 0) { + return 'hashtags' + } + + return 'statuses' + }, + lastHistoryRecord (hashtag) { + return hashtag.history && hashtag.history[0] + } + } +} + +export default Search diff --git a/src/components/search/search.vue b/src/components/search/search.vue @@ -0,0 +1,211 @@ +<template> + <div class="panel panel-default"> + <div class="panel-heading"> + <div class="title"> + {{ $t('nav.search') }} + </div> + </div> + <div class="search-input-container"> + <input + ref="searchInput" + v-model="searchTerm" + class="search-input" + :placeholder="$t('nav.search')" + @keyup.enter="newQuery(searchTerm)" + > + <button + class="btn search-button" + @click="newQuery(searchTerm)" + > + <i class="icon-search" /> + </button> + </div> + <div + v-if="loading" + class="text-center loading-icon" + > + <i class="icon-spin3 animate-spin" /> + </div> + <div v-else-if="loaded"> + <div class="search-nav-heading"> + <tab-switcher + ref="tabSwitcher" + :on-switch="onResultTabSwitch" + :custom-active="currenResultTab" + > + <span + data-tab-dummy + data-filter="statuses" + :label="$t('user_card.statuses') + resultCount('visibleStatuses')" + /> + <span + data-tab-dummy + data-filter="people" + :label="$t('search.people') + resultCount('users')" + /> + <span + data-tab-dummy + data-filter="hashtags" + :label="$t('search.hashtags') + resultCount('hashtags')" + /> + </tab-switcher> + </div> + </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" + :collapsable="false" + :expandable="false" + :compact="false" + class="search-result" + :statusoid="status" + :no-heading="false" + /> + </div> + <div v-else-if="currenResultTab === 'people'"> + <div + v-if="users.length === 0 && !loading && loaded" + class="search-result-heading" + > + <h4>{{ $t('search.no_results') }}</h4> + </div> + <FollowCard + v-for="user in users" + :key="user.id" + :user="user" + class="list-item search-result" + /> + </div> + <div v-else-if="currenResultTab === 'hashtags'"> + <div + v-if="hashtags.length === 0 && !loading && loaded" + class="search-result-heading" + > + <h4>{{ $t('search.no_results') }}</h4> + </div> + <div + v-for="hashtag in hashtags" + :key="hashtag.url" + class="status trend search-result" + > + <div class="hashtag"> + <router-link :to="{ name: 'tag-timeline', params: { tag: hashtag.name } }"> + #{{ hashtag.name }} + </router-link> + <div v-if="lastHistoryRecord(hashtag)"> + <span v-if="lastHistoryRecord(hashtag).accounts == 1"> + {{ $t('search.person_talking', { count: lastHistoryRecord(hashtag).accounts }) }} + </span> + <span v-else> + {{ $t('search.people_talking', { count: lastHistoryRecord(hashtag).accounts }) }} + </span> + </div> + </div> + <div + v-if="lastHistoryRecord(hashtag)" + class="count" + > + {{ lastHistoryRecord(hashtag).uses }} + </div> + </div> + </div> + </div> + <div class="search-result-footer text-center panel-footer faint" /> + </div> +</template> + +<script src="./search.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.search-result-heading { + color: $fallback--faint; + color: var(--faint, $fallback--faint); + padding: 0.75rem; + text-align: center; +} + +@media all and (max-width: 800px) { + .search-nav-heading { + .tab-switcher .tabs .tab-wrapper { + display: block; + justify-content: center; + flex: 1 1 auto; + text-align: center; + } + } +} + +.search-result { + box-sizing: border-box; + border-bottom: 1px solid; + border-color: $fallback--border; + border-color: var(--border, $fallback--border); +} + +.search-result-footer { + border-width: 1px 0 0 0; + border-style: solid; + border-color: var(--border, $fallback--border); + padding: 10px; + background-color: $fallback--fg; + background-color: var(--panel, $fallback--fg); +} + +.search-input-container { + padding: 0.8rem; + display: flex; + justify-content: center; + + .search-input { + width: 100%; + line-height: 1.125rem; + font-size: 1rem; + padding: 0.5rem; + box-sizing: border-box; + } + + .search-button { + margin-left: 0.5em; + } +} + +.loading-icon { + padding: 1em; +} + +.trend { + display: flex; + align-items: center; + + .hashtag { + flex: 1 1 auto; + color: $fallback--text; + color: var(--text, $fallback--text); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .count { + flex: 0 0 auto; + width: 2rem; + font-size: 1.5rem; + line-height: 2.25rem; + font-weight: 500; + text-align: center; + color: $fallback--text; + color: var(--text, $fallback--text); + } +} + +</style> diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js @@ -0,0 +1,27 @@ +const SearchBar = { + data: () => ({ + searchTerm: undefined, + hidden: true, + error: false, + loading: false + }), + watch: { + '$route': function (route) { + if (route.name === 'search') { + this.searchTerm = route.query.query + } + } + }, + methods: { + find (searchTerm) { + this.$router.push({ name: 'search', query: { query: searchTerm } }) + this.$refs.searchInput.focus() + }, + toggleHidden () { + this.hidden = !this.hidden + this.$emit('toggled', this.hidden) + } + } +} + +export default SearchBar diff --git a/src/components/search_bar/search_bar.vue b/src/components/search_bar/search_bar.vue @@ -0,0 +1,73 @@ +<template> + <div> + <div class="search-bar-container"> + <i + v-if="loading" + class="icon-spin4 finder-icon animate-spin-slow" + /> + <a + v-if="hidden" + href="#" + :title="$t('nav.search')" + ><i + class="button-icon icon-search" + @click.prevent.stop="toggleHidden" + /></a> + <template v-else> + <input + id="search-bar-input" + ref="searchInput" + v-model="searchTerm" + class="search-bar-input" + :placeholder="$t('nav.search')" + type="text" + @keyup.enter="find(searchTerm)" + > + <button + class="btn search-button" + @click="find(searchTerm)" + > + <i class="icon-search" /> + </button> + <i + class="button-icon icon-cancel" + @click.prevent.stop="toggleHidden" + /> + </template> + </div> + </div> +</template> + +<script src="./search_bar.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.search-bar-container { + max-width: 100%; + display: inline-flex; + align-items: baseline; + vertical-align: baseline; + justify-content: flex-end; + + .search-bar-input, + .search-button { + height: 29px; + } + + .search-bar-input { + // TODO: do this properly without a rough guesstimate of 2 icons + paddings + max-width: calc(100% - 30px - 30px - 20px); + } + + .search-button { + margin-left: .5em; + margin-right: .5em; + } + + .icon-cancel { + cursor: pointer; + } +} + +</style> diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue @@ -100,8 +100,8 @@ </ul> <ul> <li @click="toggleDrawer"> - <router-link :to="{ name: 'user-search' }"> - {{ $t("nav.user_search") }} + <router-link :to="{ name: 'search' }"> + {{ $t("nav.search") }} </router-link> </li> <li diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js @@ -4,7 +4,7 @@ import './tab_switcher.scss' export default Vue.component('tab-switcher', { name: 'TabSwitcher', - props: ['renderOnlyFocused', 'onSwitch'], + props: ['renderOnlyFocused', 'onSwitch', 'customActive'], data () { return { active: this.$slots.default.findIndex(_ => _.tag) @@ -24,6 +24,14 @@ export default Vue.component('tab-switcher', { } this.active = index } + }, + isActiveTab (index) { + const customActiveIndex = this.$slots.default.findIndex(slot => { + const dataFilter = slot.data && slot.data.attrs && slot.data.attrs['data-filter'] + return this.customActive && this.customActive === dataFilter + }) + + return customActiveIndex > -1 ? customActiveIndex === index : index === this.active } }, render (h) { @@ -33,7 +41,7 @@ export default Vue.component('tab-switcher', { const classesTab = ['tab'] const classesWrapper = ['tab-wrapper'] - if (index === this.active) { + if (this.isActiveTab(index)) { classesTab.push('active') classesWrapper.push('active') } diff --git a/src/components/user_finder/user_finder.js b/src/components/user_finder/user_finder.js @@ -1,20 +0,0 @@ -const UserFinder = { - data: () => ({ - username: undefined, - hidden: true, - error: false, - loading: false - }), - methods: { - findUser (username) { - this.$router.push({ name: 'user-search', query: { query: username } }) - this.$refs.userSearchInput.focus() - }, - toggleHidden () { - this.hidden = !this.hidden - this.$emit('toggled', this.hidden) - } - } -} - -export default UserFinder diff --git a/src/components/user_finder/user_finder.vue b/src/components/user_finder/user_finder.vue @@ -1,67 +0,0 @@ -<template> - <div> - <div class="user-finder-container"> - <i - v-if="loading" - class="icon-spin4 user-finder-icon animate-spin-slow" - /> - <a - v-if="hidden" - href="#" - :title="$t('finder.find_user')" - ><i - class="icon-user-plus user-finder-icon" - @click.prevent.stop="toggleHidden" - /></a> - <template v-else> - <input - id="user-finder-input" - ref="userSearchInput" - v-model="username" - class="user-finder-input" - :placeholder="$t('finder.find_user')" - type="text" - @keyup.enter="findUser(username)" - > - <button - class="btn search-button" - @click="findUser(username)" - > - <i class="icon-search" /> - </button> - <i - class="button-icon icon-cancel user-finder-icon" - @click.prevent.stop="toggleHidden" - /> - </template> - </div> - </div> -</template> - -<script src="./user_finder.js"></script> - -<style lang="scss"> -@import '../../_variables.scss'; - -.user-finder-container { - max-width: 100%; - display: inline-flex; - align-items: baseline; - vertical-align: baseline; - - .user-finder-input, - .search-button { - height: 29px; - } - .user-finder-input { - // TODO: do this properly without a rough guesstimate of 2 icons + paddings - max-width: calc(100% - 30px - 30px - 20px); - } - - .search-button { - margin-left: .5em; - margin-right: .5em; - } -} - -</style> diff --git a/src/components/user_search/user_search.js b/src/components/user_search/user_search.js @@ -1,49 +0,0 @@ -import FollowCard from '../follow_card/follow_card.vue' -import map from 'lodash/map' - -const userSearch = { - components: { - FollowCard - }, - props: [ - 'query' - ], - data () { - return { - username: '', - userIds: [], - loading: false - } - }, - computed: { - users () { - return this.userIds.map(userId => this.$store.getters.findUser(userId)) - } - }, - mounted () { - this.search(this.query) - }, - watch: { - query (newV) { - this.search(newV) - } - }, - methods: { - newQuery (query) { - this.$router.push({ name: 'user-search', query: { query } }) - this.$refs.userSearchInput.focus() - }, - search (query) { - if (!query) { - return - } - this.loading = true - this.userIds = [] - this.$store.dispatch('searchUsers', query) - .then((res) => { this.userIds = map(res, 'id') }) - .finally(() => { this.loading = false }) - } - } -} - -export default userSearch diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue @@ -1,57 +0,0 @@ -<template> - <div class="user-search panel panel-default"> - <div class="panel-heading"> - {{ $t('nav.user_search') }} - </div> - <div class="user-search-input-container"> - <input - ref="userSearchInput" - v-model="username" - class="user-finder-input" - :placeholder="$t('finder.find_user')" - @keyup.enter="newQuery(username)" - > - <button - class="btn search-button" - @click="newQuery(username)" - > - <i class="icon-search" /> - </button> - </div> - <div - v-if="loading" - class="text-center loading-icon" - > - <i class="icon-spin3 animate-spin" /> - </div> - <div - v-else - class="panel-body" - > - <FollowCard - v-for="user in users" - :key="user.id" - :user="user" - class="list-item" - /> - </div> - </div> -</template> - -<script src="./user_search.js"></script> - -<style lang="scss"> -.user-search-input-container { - margin: 0.5em; - display: flex; - justify-content: center; - - .search-button { - margin-left: 0.5em; - } -} - -.loading-icon { - padding: 1em; -} -</style> diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -78,6 +78,7 @@ "timeline": "Timeline", "twkn": "The Whole Known Network", "user_search": "User Search", + "search": "Search", "who_to_follow": "Who to follow", "preferences": "Preferences" }, @@ -595,5 +596,12 @@ "GiB": "GiB", "TiB": "TiB" } + }, + "search": { + "people": "People", + "hashtags": "Hashtags", + "person_talking": "{count} person talking", + "people_talking": "{count} people talking", + "no_results": "No results" } } diff --git a/src/i18n/ru.json b/src/i18n/ru.json @@ -38,7 +38,8 @@ "interactions": "Взаимодействия", "public_tl": "Публичная лента", "timeline": "Лента", - "twkn": "Федеративная лента" + "twkn": "Федеративная лента", + "search": "Поиск" }, "notifications": { "broken_favorite": "Неизвестный статус, ищем...", @@ -381,5 +382,12 @@ }, "user_profile": { "timeline_title": "Лента пользователя" + }, + "search": { + "people": "Люди", + "hashtags": "Хэштэги", + "person_talking": "Популярно у {count} человека", + "people_talking": "Популярно у {count} человек", + "no_results": "Ничего не найдено" } } diff --git a/src/modules/statuses.js b/src/modules/statuses.js @@ -602,6 +602,14 @@ const statuses = { fetchRepeats ({ rootState, commit }, id) { 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 }) + .then((data) => { + store.commit('addNewUsers', data.accounts) + store.commit('addNewStatuses', { statuses: data.statuses }) + return data + }) } }, mutations diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js @@ -67,7 +67,7 @@ const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials' const MASTODON_REPORT_USER_URL = '/api/v1/reports' const MASTODON_PIN_OWN_STATUS = id => `/api/v1/statuses/${id}/pin` const MASTODON_UNPIN_OWN_STATUS = id => `/api/v1/statuses/${id}/unpin` -const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search' +const MASTODON_SEARCH_2 = `/api/v2/search` const oldfetch = window.fetch @@ -853,16 +853,46 @@ const reportUser = ({ credentials, userId, statusIds, comment, forward }) => { }) } -const searchUsers = ({ credentials, query }) => { - return promisedRequest({ - url: MASTODON_USER_SEARCH_URL, - params: { - q: query, - resolve: true - }, - credentials - }) - .then((data) => data.map(parseUser)) +const search2 = ({ credentials, q, resolve, limit, offset, following }) => { + let url = MASTODON_SEARCH_2 + let params = [] + + if (q) { + params.push(['q', encodeURIComponent(q)]) + } + + if (resolve) { + params.push(['resolve', resolve]) + } + + if (limit) { + params.push(['limit', limit]) + } + + if (offset) { + params.push(['offset', offset]) + } + + if (following) { + params.push(['following', true]) + } + + let queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') + url += `?${queryString}` + + return fetch(url, { headers: authHeaders(credentials) }) + .then((data) => { + if (data.ok) { + return data + } + throw new Error('Error fetching search result', data) + }) + .then((data) => { return data.json() }) + .then((data) => { + data.accounts = data.accounts.slice(0, limit).map(u => parseUser(u)) + data.statuses = data.statuses.slice(0, limit).map(s => parseStatus(s)) + return data + }) } const apiService = { @@ -930,7 +960,7 @@ const apiService = { fetchRebloggedByUsers, reportUser, updateNotificationSettings, - searchUsers + search2 } export default apiService diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js @@ -148,8 +148,8 @@ const backendInteractorService = credentials => { const unfavorite = (id) => apiService.unfavorite({ id, credentials }) const retweet = (id) => apiService.retweet({ id, credentials }) const unretweet = (id) => apiService.unretweet({ id, credentials }) - - const searchUsers = (query) => apiService.searchUsers({ query, credentials }) + const search2 = ({ q, resolve, limit, offset, following }) => + apiService.search2({ credentials, q, resolve, limit, offset, following }) const backendInteractorServiceInstance = { fetchStatus, @@ -212,7 +212,7 @@ const backendInteractorService = credentials => { retweet, unretweet, updateNotificationSettings, - searchUsers + search2 } return backendInteractorServiceInstance