kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Create AccountSearch component to do more than AutosuggestAccountInput
rodzic
b0b13e9e59
commit
a02112a1c8
|
@ -0,0 +1,83 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import AutosuggestAccountInput from 'soapbox/components/autosuggest_account_input';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'account_search.placeholder', defaultMessage: 'Search for an account' },
|
||||
});
|
||||
|
||||
export default @injectIntl
|
||||
class AccountSearch extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
value: '',
|
||||
}
|
||||
|
||||
isEmpty = () => {
|
||||
const { value } = this.state;
|
||||
return !(value.length > 0);
|
||||
}
|
||||
|
||||
clearState = () => {
|
||||
this.setState({ value: '' });
|
||||
}
|
||||
|
||||
handleChange = ({ target }) => {
|
||||
this.setState({ value: target.value });
|
||||
}
|
||||
|
||||
handleSelected = accountId => {
|
||||
this.clearState();
|
||||
this.props.onSelected(accountId);
|
||||
}
|
||||
|
||||
handleClear = e => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this.isEmpty()) {
|
||||
this.setState({ value: '' });
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
if (e.key === 'Escape') {
|
||||
document.querySelector('.ui').parentElement.focus();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, onSelected, ...rest } = this.props;
|
||||
const { value } = this.state;
|
||||
const isEmpty = this.isEmpty();
|
||||
|
||||
return (
|
||||
<div className='search search--account'>
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.placeholder)}</span>
|
||||
<AutosuggestAccountInput
|
||||
className='search__input'
|
||||
placeholder={intl.formatMessage(messages.placeholder)}
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onSelected={this.handleSelected}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
{...rest}
|
||||
/>
|
||||
</label>
|
||||
<div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
|
||||
<Icon src={require('@tabler/icons/icons/search.svg')} className={classNames('svg-icon--search', { active: isEmpty })} />
|
||||
<Icon src={require('@tabler/icons/icons/backspace.svg')} className={classNames('svg-icon--backspace', { active: !isEmpty })} aria-label={intl.formatMessage(messages.placeholder)} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,34 +4,29 @@ import PropTypes from 'prop-types';
|
|||
import { CancelToken } from 'axios';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { connect } from 'react-redux';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||
import { accountSearch } from 'soapbox/actions/accounts';
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
const noOp = () => {};
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'autosuggest_account_input.default_placeholder', defaultMessage: 'Search for an account' },
|
||||
});
|
||||
|
||||
export default @connect()
|
||||
@injectIntl
|
||||
class AutosuggestAccountInput extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSelected: PropTypes.func.isRequired,
|
||||
limit: PropTypes.number,
|
||||
value: PropTypes.string.isRequired,
|
||||
limit: PropTypes.number.isRequired,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
value: '',
|
||||
limit: 4,
|
||||
}
|
||||
|
||||
state = {
|
||||
text: '',
|
||||
accountIds: ImmutableOrderedSet(),
|
||||
}
|
||||
|
||||
|
@ -43,6 +38,10 @@ class AutosuggestAccountInput extends ImmutablePureComponent {
|
|||
return this.source;
|
||||
}
|
||||
|
||||
clearResults = () => {
|
||||
this.setState({ accountIds: ImmutableOrderedSet() });
|
||||
}
|
||||
|
||||
handleAccountSearch = throttle(q => {
|
||||
const { dispatch, limit } = this.props;
|
||||
const source = this.refreshCancelToken();
|
||||
|
@ -58,23 +57,28 @@ class AutosuggestAccountInput extends ImmutablePureComponent {
|
|||
|
||||
}, 900, { leading: true, trailing: true })
|
||||
|
||||
handleChange = ({ target }) => {
|
||||
this.handleAccountSearch(target.value);
|
||||
this.setState({ text: target.value });
|
||||
handleChange = e => {
|
||||
this.handleAccountSearch(e.target.value);
|
||||
this.props.onChange(e);
|
||||
}
|
||||
|
||||
handleSelected = (tokenStart, lastToken, accountId) => {
|
||||
this.props.onSelected(accountId);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.value === '' && prevProps.value !== '') {
|
||||
this.clearResults();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, ...rest } = this.props;
|
||||
const { text, accountIds } = this.state;
|
||||
const { intl, value, onChange, ...rest } = this.props;
|
||||
const { accountIds } = this.state;
|
||||
|
||||
return (
|
||||
<AutosuggestInput
|
||||
placeholder={intl.formatMessage(messages.placeholder)}
|
||||
value={text}
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
suggestions={accountIds.toList()}
|
||||
onSuggestionsFetchRequested={noOp}
|
||||
|
|
|
@ -8,10 +8,11 @@ import { expandDirectTimeline } from '../../actions/timelines';
|
|||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import { connectDirectStream } from '../../actions/streaming';
|
||||
import { directComposeById } from 'soapbox/actions/compose';
|
||||
import AutosuggestAccountInput from 'soapbox/components/autosuggest_account_input';
|
||||
import AccountSearch from 'soapbox/components/account_search';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.direct', defaultMessage: 'Direct messages' },
|
||||
searchPlaceholder: { id: 'direct.search_placeholder', defaultMessage: 'Search for an account to message…' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
@ -62,7 +63,10 @@ class DirectTimeline extends React.PureComponent {
|
|||
onPin={this.handlePin}
|
||||
/>
|
||||
|
||||
<AutosuggestAccountInput onSelected={this.handleSuggestion} />
|
||||
<AccountSearch
|
||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
||||
onSelected={this.handleSuggestion}
|
||||
/>
|
||||
|
||||
<StatusListContainer
|
||||
scrollKey='direct_timeline'
|
||||
|
|
|
@ -167,9 +167,12 @@
|
|||
|
||||
.search-page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.column {
|
||||
.search {
|
||||
padding: 10px 15px;
|
||||
background-color: var(--foreground-color);
|
||||
border-bottom: 1px solid hsla(var(--primary-text-color_hsl), 0.2);
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue