M app/javascript/flavours/glitch/actions/search.js => app/javascript/flavours/glitch/actions/search.js +33 -12
@@ 1,3 1,7 @@
+import { fromJS } from 'immutable';
+
+import { searchHistory } from 'flavours/glitch/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 {
@@ 165,16 168,34 @@ export const openURL = routerHistory => (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);
-export const forgetSearchResult = q => ({
- type: SEARCH_RESULT_FORGET,
- q,
+ searchHistory.set(me, current.toJS());
+ dispatch(updateSearchHistory(current));
+};
+
+export const updateSearchHistory = recent => ({
+ type: SEARCH_HISTORY_UPDATE,
+ recent,
});
+
+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
M app/javascript/flavours/glitch/actions/store.js => app/javascript/flavours/glitch/actions/store.js +2 -0
@@ 2,6 2,7 @@ import { Iterable, fromJS } from 'immutable';
import { hydrateCompose } from './compose';
import { importFetchedAccounts } from './importer';
+import { hydrateSearch } from './search';
import { saveSettings } from './settings';
export const STORE_HYDRATE = 'STORE_HYDRATE';
@@ 34,6 35,7 @@ export function hydrateStore(rawState) {
});
dispatch(hydrateCompose());
+ dispatch(hydrateSearch());
dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
dispatch(saveSettings());
};
M app/javascript/flavours/glitch/features/compose/components/search.jsx => app/javascript/flavours/glitch/features/compose/components/search.jsx +22 -4
@@ 18,7 18,17 @@ const messages = defineMessages({
placeholderSignedIn: { id: 'search.search_or_paste', defaultMessage: 'Search or paste URL' },
});
-// The component.
+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 = {
@@ 198,12 208,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();
@@ 232,11 246,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');
}
@@ 254,7 272,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),
@@ 368,7 386,7 @@ class Search extends PureComponent {
{searchEnabled ? (
<div className='search__popout__menu'>
{this.defaultOptions.map(({ key, label, action }, i) => (
- <button key={key} onMouseDown={action} className={classNames('search__popout__menu__item', { selected: selectedOption === (options.length + i) })}>
+ <button key={key} onMouseDown={action} className={classNames('search__popout__menu__item', { selected: selectedOption === ((options.length || recent.size) + i) })}>
{label}
</button>
))}
M app/javascript/flavours/glitch/features/compose/containers/search_container.js => app/javascript/flavours/glitch/features/compose/containers/search_container.js +1 -1
@@ 15,7 15,7 @@ import Search from '../components/search';
const mapStateToProps = state => ({
value: state.getIn(['search', 'value']),
submitted: state.getIn(['search', 'submitted']),
- recent: state.getIn(['search', 'recent']),
+ recent: state.getIn(['search', 'recent']).reverse(),
});
const mapDispatchToProps = dispatch => ({
M app/javascript/flavours/glitch/reducers/search.js => app/javascript/flavours/glitch/reducers/search.js +3 -6
@@ 14,8 14,7 @@ import {
SEARCH_SHOW,
SEARCH_EXPAND_REQUEST,
SEARCH_EXPAND_SUCCESS,
- SEARCH_RESULT_CLICK,
- SEARCH_RESULT_FORGET,
+ SEARCH_HISTORY_UPDATE,
} from 'flavours/glitch/actions/search';
const initialState = ImmutableMap({
@@ 73,10 72,8 @@ export default function search(state = initialState, action) {
case SEARCH_EXPAND_SUCCESS:
const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id);
return state.updateIn(['results', action.searchType], list => list.union(results));
- case SEARCH_RESULT_CLICK:
- return state.update('recent', set => set.add(fromJS(action.result)));
- case SEARCH_RESULT_FORGET:
- return state.update('recent', set => set.filterNot(result => result.get('q') === action.q));
+ case SEARCH_HISTORY_UPDATE:
+ return state.set('recent', ImmutableOrderedSet(fromJS(action.recent)));
default:
return state;
}
M app/javascript/flavours/glitch/settings.js => app/javascript/flavours/glitch/settings.js +1 -0
@@ 46,3 46,4 @@ export default class Settings {
export const pushNotificationsSetting = new Settings('mastodon_push_notification_data');
export const tagHistory = new Settings('mastodon_tag_history');
export const bannerSettings = new Settings('mastodon_banner_settings');
+export const searchHistory = new Settings('mastodon_search_history');<
\ No newline at end of file