~cytrogen/masto-fe

7384015505838d10431e34db5b5f50d6f2f66aee — Eugen Rochko 2 years ago 263d601
[Glitch] Add recent searches in web UI

Port 9b2bc3d1de301c686208b43a8efef5bc808f8e4e to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
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