diff --git a/app/javascript/mastodon/actions/search.js b/app/javascript/mastodon/actions/search.js index 21fd54076..7aea346e6 100644 --- a/app/javascript/mastodon/actions/search.js +++ b/app/javascript/mastodon/actions/search.js @@ -1,3 +1,7 @@ +import { fromJS } from 'immutable'; + +import { searchHistory } from 'mastodon/settings'; + import api from '../api'; import { fetchRelationships } from './accounts'; @@ -15,8 +19,7 @@ export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST'; export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS'; export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL'; -export const SEARCH_RESULT_CLICK = 'SEARCH_RESULT_CLICK'; -export const SEARCH_RESULT_FORGET = 'SEARCH_RESULT_FORGET'; +export const SEARCH_HISTORY_UPDATE = 'SEARCH_HISTORY_UPDATE'; export function changeSearch(value) { return { @@ -170,16 +173,34 @@ export const openURL = (value, history, onFailure) => (dispatch, getState) => { }); }; -export const clickSearchResult = (q, type) => ({ - type: SEARCH_RESULT_CLICK, +export const clickSearchResult = (q, type) => (dispatch, getState) => { + const previous = getState().getIn(['search', 'recent']); + const me = getState().getIn(['meta', 'me']); + const current = previous.add(fromJS({ type, q })).takeLast(4); - result: { - type, - q, - }, + searchHistory.set(me, current.toJS()); + dispatch(updateSearchHistory(current)); +}; + +export const forgetSearchResult = q => (dispatch, getState) => { + const previous = getState().getIn(['search', 'recent']); + const me = getState().getIn(['meta', 'me']); + const current = previous.filterNot(result => result.get('q') === q); + + searchHistory.set(me, current.toJS()); + dispatch(updateSearchHistory(current)); +}; + +export const updateSearchHistory = recent => ({ + type: SEARCH_HISTORY_UPDATE, + recent, }); -export const forgetSearchResult = q => ({ - type: SEARCH_RESULT_FORGET, - q, -}); +export const hydrateSearch = () => (dispatch, getState) => { + const me = getState().getIn(['meta', 'me']); + const history = searchHistory.get(me); + + if (history !== null) { + dispatch(updateSearchHistory(history)); + } +}; \ No newline at end of file diff --git a/app/javascript/mastodon/actions/store.js b/app/javascript/mastodon/actions/store.js index 6b0743439..682b0f5db 100644 --- a/app/javascript/mastodon/actions/store.js +++ b/app/javascript/mastodon/actions/store.js @@ -2,6 +2,7 @@ import { Iterable, fromJS } from 'immutable'; import { hydrateCompose } from './compose'; import { importFetchedAccounts } from './importer'; +import { hydrateSearch } from './search'; export const STORE_HYDRATE = 'STORE_HYDRATE'; export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY'; @@ -20,6 +21,7 @@ export function hydrateStore(rawState) { }); dispatch(hydrateCompose()); + dispatch(hydrateSearch()); dispatch(importFetchedAccounts(Object.values(rawState.accounts))); }; } diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx index 53e1db9d4..7e1d8b760 100644 --- a/app/javascript/mastodon/features/compose/components/search.jsx +++ b/app/javascript/mastodon/features/compose/components/search.jsx @@ -16,6 +16,17 @@ const messages = defineMessages({ placeholderSignedIn: { id: 'search.search_or_paste', defaultMessage: 'Search or paste URL' }, }); +const labelForRecentSearch = search => { + switch(search.get('type')) { + case 'account': + return `@${search.get('q')}`; + case 'hashtag': + return `#${search.get('q')}`; + default: + return search.get('q'); + } +}; + class Search extends PureComponent { static contextTypes = { @@ -187,12 +198,16 @@ class Search extends PureComponent { }; handleRecentSearchClick = search => { + const { onChange } = this.props; const { router } = this.context; if (search.get('type') === 'account') { router.history.push(`/@${search.get('q')}`); } else if (search.get('type') === 'hashtag') { router.history.push(`/tags/${search.get('q')}`); + } else { + onChange(search.get('q')); + this._submit(search.get('type')); } this._unfocus(); @@ -221,11 +236,15 @@ class Search extends PureComponent { } _submit (type) { - const { onSubmit, openInRoute } = this.props; + const { onSubmit, openInRoute, value, onClickSearchResult } = this.props; const { router } = this.context; onSubmit(type); + if (value) { + onClickSearchResult(value, type); + } + if (openInRoute) { router.history.push('/search'); } @@ -243,7 +262,7 @@ class Search extends PureComponent { const { recent } = this.props; return recent.toArray().map(search => ({ - label: search.get('type') === 'account' ? `@${search.get('q')}` : `#${search.get('q')}`, + label: labelForRecentSearch(search), action: () => this.handleRecentSearchClick(search), @@ -359,7 +378,7 @@ class Search extends PureComponent { {searchEnabled ? (