Add search options to search popout in web UI (#26662)

This commit is contained in:
Eugen Rochko 2023-08-28 13:18:39 +02:00 committed by GitHub
parent 67166de865
commit bceb893159
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 5 deletions

View file

@ -1,7 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage, FormattedList } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
@ -45,6 +45,16 @@ class Search extends PureComponent {
options: [], options: [],
}; };
defaultOptions = [
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:') } },
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:') } },
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:') } },
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:') } },
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:') } },
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:') } },
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:') } },
];
setRef = c => { setRef = c => {
this.searchForm = c; this.searchForm = c;
}; };
@ -70,7 +80,7 @@ class Search extends PureComponent {
handleKeyDown = (e) => { handleKeyDown = (e) => {
const { selectedOption } = this.state; const { selectedOption } = this.state;
const options = this._getOptions(); const options = this._getOptions().concat(this.defaultOptions);
switch(e.key) { switch(e.key) {
case 'Escape': case 'Escape':
@ -100,11 +110,9 @@ class Search extends PureComponent {
if (selectedOption === -1) { if (selectedOption === -1) {
this._submit(); this._submit();
} else if (options.length > 0) { } else if (options.length > 0) {
options[selectedOption].action(); options[selectedOption].action(e);
} }
this._unfocus();
break; break;
case 'Delete': case 'Delete':
if (selectedOption > -1 && options.length > 0) { if (selectedOption > -1 && options.length > 0) {
@ -147,6 +155,7 @@ class Search extends PureComponent {
router.history.push(`/tags/${query}`); router.history.push(`/tags/${query}`);
onClickSearchResult(query, 'hashtag'); onClickSearchResult(query, 'hashtag');
this._unfocus();
}; };
handleAccountClick = () => { handleAccountClick = () => {
@ -157,6 +166,7 @@ class Search extends PureComponent {
router.history.push(`/@${query}`); router.history.push(`/@${query}`);
onClickSearchResult(query, 'account'); onClickSearchResult(query, 'account');
this._unfocus();
}; };
handleURLClick = () => { handleURLClick = () => {
@ -164,6 +174,7 @@ class Search extends PureComponent {
const { value, onOpenURL } = this.props; const { value, onOpenURL } = this.props;
onOpenURL(value, router.history); onOpenURL(value, router.history);
this._unfocus();
}; };
handleStatusSearch = () => { handleStatusSearch = () => {
@ -182,6 +193,8 @@ class Search extends PureComponent {
} else if (search.get('type') === 'hashtag') { } else if (search.get('type') === 'hashtag') {
router.history.push(`/tags/${search.get('q')}`); router.history.push(`/tags/${search.get('q')}`);
} }
this._unfocus();
}; };
handleForgetRecentSearchClick = search => { handleForgetRecentSearchClick = search => {
@ -194,6 +207,18 @@ class Search extends PureComponent {
document.querySelector('.ui').parentElement.focus(); document.querySelector('.ui').parentElement.focus();
} }
_insertText (text) {
const { value, onChange } = this.props;
if (value === '') {
onChange(text);
} else if (value[value.length - 1] === ' ') {
onChange(`${value}${text}`);
} else {
onChange(`${value} ${text}`);
}
}
_submit (type) { _submit (type) {
const { onSubmit, openInRoute } = this.props; const { onSubmit, openInRoute } = this.props;
const { router } = this.context; const { router } = this.context;
@ -203,6 +228,8 @@ class Search extends PureComponent {
if (openInRoute) { if (openInRoute) {
router.history.push('/search'); router.history.push('/search');
} }
this._unfocus();
} }
_getOptions () { _getOptions () {
@ -325,6 +352,16 @@ class Search extends PureComponent {
</div> </div>
</> </>
)} )}
<h4><FormattedMessage id='search_popout.options' defaultMessage='Search options' /></h4>
<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) })}>
{label}
</button>
))}
</div>
</div> </div>
</div> </div>
); );

View file

@ -586,8 +586,12 @@
"search.quick_action.open_url": "Open URL in Mastodon", "search.quick_action.open_url": "Open URL in Mastodon",
"search.quick_action.status_search": "Posts matching {x}", "search.quick_action.status_search": "Posts matching {x}",
"search.search_or_paste": "Search or paste URL", "search.search_or_paste": "Search or paste URL",
"search_popout.language_code": "ISO language code",
"search_popout.options": "Search options",
"search_popout.quick_actions": "Quick actions", "search_popout.quick_actions": "Quick actions",
"search_popout.recent": "Recent searches", "search_popout.recent": "Recent searches",
"search_popout.specific_date": "specific date",
"search_popout.user": "user",
"search_results.accounts": "Profiles", "search_results.accounts": "Profiles",
"search_results.all": "All", "search_results.all": "All",
"search_results.hashtags": "Hashtags", "search_results.hashtags": "Hashtags",

View file

@ -4991,6 +4991,12 @@ a.status-card {
} }
&__menu { &__menu {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
&__message { &__message {
color: $dark-text-color; color: $dark-text-color;
padding: 0 10px; padding: 0 10px;