Fix and Improve searching

This commit is contained in:
Rafael 2021-12-07 11:51:55 -03:00 committed by Thomas Zarebczan
parent e8e1c7e3b4
commit c2a3698015
8 changed files with 44 additions and 19 deletions

View file

@ -3,7 +3,7 @@ import { doResolveUris } from 'redux/actions/claims';
import { MAX_LIVESTREAM_COMMENTS } from 'constants/livestream'; import { MAX_LIVESTREAM_COMMENTS } from 'constants/livestream';
import { selectChannelMentionData } from 'redux/selectors/comments'; import { selectChannelMentionData } from 'redux/selectors/comments';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import { doSetSearchResults } from 'redux/actions/search'; import { doSetMentionSearchResults } from 'redux/actions/search';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import TextareaWithSuggestions from './view'; import TextareaWithSuggestions from './view';
@ -13,7 +13,14 @@ const select = (state, props) => {
const uri = `lbry:/${pathname.replaceAll(':', '#')}`; const uri = `lbry:/${pathname.replaceAll(':', '#')}`;
const data = selectChannelMentionData(state, uri, maxComments); const data = selectChannelMentionData(state, uri, maxComments);
const { canonicalCommentors, canonicalCreatorUri, canonicalSubscriptions, commentorUris, canonicalSearch } = data; const {
canonicalCommentors,
canonicalCreatorUri,
canonicalSearch,
canonicalSubscriptions,
commentorUris,
hasNewResolvedResults,
} = data;
return { return {
canonicalCommentors, canonicalCommentors,
@ -21,13 +28,14 @@ const select = (state, props) => {
canonicalSearch, canonicalSearch,
canonicalSubscriptions, canonicalSubscriptions,
commentorUris, commentorUris,
hasNewResolvedResults,
showMature: selectShowMatureContent(state), showMature: selectShowMatureContent(state),
}; };
}; };
const perform = (dispatch) => ({ const perform = (dispatch) => ({
doResolveUris: (uris) => dispatch(doResolveUris(uris, true)), doResolveUris: (uris) => dispatch(doResolveUris(uris, true)),
doSetSearchResults: (uris) => dispatch(doSetSearchResults(uris)), doSetMentionSearchResults: (uris) => dispatch(doSetMentionSearchResults(uris)),
}); });
export default withRouter(connect(select, perform)(TextareaWithSuggestions)); export default withRouter(connect(select, perform)(TextareaWithSuggestions));

View file

@ -4,11 +4,12 @@ import { matchSorter } from 'match-sorter';
import { SEARCH_OPTIONS } from 'constants/search'; import { SEARCH_OPTIONS } from 'constants/search';
import * as KEYCODES from 'constants/keycodes'; import * as KEYCODES from 'constants/keycodes';
import Autocomplete from '@mui/material/Autocomplete'; import Autocomplete from '@mui/material/Autocomplete';
import BusyIndicator from 'component/common/busy-indicator';
import EMOJIS from 'emoji-dictionary'; import EMOJIS from 'emoji-dictionary';
import Popper from '@mui/material/Popper';
import React from 'react'; import React from 'react';
import TextareaSuggestionsItem from 'component/textareaSuggestionsItem'; import TextareaSuggestionsItem from 'component/textareaSuggestionsItem';
import TextField from '@mui/material/TextField'; import TextField from '@mui/material/TextField';
import Popper from '@mui/material/Popper';
import useLighthouse from 'effects/use-lighthouse'; import useLighthouse from 'effects/use-lighthouse';
import useThrottle from 'effects/use-throttle'; import useThrottle from 'effects/use-throttle';
@ -42,6 +43,7 @@ type Props = {
className?: string, className?: string,
commentorUris?: Array<string>, commentorUris?: Array<string>,
disabled?: boolean, disabled?: boolean,
hasNewResolvedResults?: boolean,
id: string, id: string,
inputRef: any, inputRef: any,
isLivestream?: boolean, isLivestream?: boolean,
@ -52,7 +54,7 @@ type Props = {
uri?: string, uri?: string,
value: any, value: any,
doResolveUris: (Array<string>) => void, doResolveUris: (Array<string>) => void,
doSetSearchResults: (Array<string>) => void, doSetMentionSearchResults: (Array<string>) => void,
onBlur: (any) => any, onBlur: (any) => any,
onChange: (any) => any, onChange: (any) => any,
onFocus: (any) => any, onFocus: (any) => any,
@ -67,6 +69,7 @@ export default function TextareaWithSuggestions(props: Props) {
className, className,
commentorUris, commentorUris,
disabled, disabled,
hasNewResolvedResults,
id, id,
inputRef, inputRef,
isLivestream, isLivestream,
@ -76,7 +79,7 @@ export default function TextareaWithSuggestions(props: Props) {
type, type,
value: messageValue, value: messageValue,
doResolveUris, doResolveUris,
doSetSearchResults, doSetMentionSearchResults,
onBlur, onBlur,
onChange, onChange,
onFocus, onFocus,
@ -101,7 +104,8 @@ export default function TextareaWithSuggestions(props: Props) {
const hasMinLength = suggestionTerm && isMention && suggestionTerm.length >= LIGHTHOUSE_MIN_CHARACTERS; const hasMinLength = suggestionTerm && isMention && suggestionTerm.length >= LIGHTHOUSE_MIN_CHARACTERS;
const isTyping = isMention && debouncedTerm !== suggestionTerm; const isTyping = isMention && debouncedTerm !== suggestionTerm;
const showPlaceholder = isMention && (isTyping || loading); const showPlaceholder =
isMention && (isTyping || loading || (results && results.length > 0 && !hasNewResolvedResults));
const shouldFilter = (uri, previous) => uri !== canonicalCreatorUri && (!previous || !previous.includes(uri)); const shouldFilter = (uri, previous) => uri !== canonicalCreatorUri && (!previous || !previous.includes(uri));
const filteredCommentors = canonicalCommentors && canonicalCommentors.filter((uri) => shouldFilter(uri)); const filteredCommentors = canonicalCommentors && canonicalCommentors.filter((uri) => shouldFilter(uri));
@ -271,9 +275,9 @@ export default function TextareaWithSuggestions(props: Props) {
const arrayResults = JSON.parse(stringifiedResults); const arrayResults = JSON.parse(stringifiedResults);
if (arrayResults && arrayResults.length > 0) { if (arrayResults && arrayResults.length > 0) {
doResolveUris(arrayResults); doResolveUris(arrayResults);
doSetSearchResults(arrayResults); doSetMentionSearchResults(arrayResults);
} }
}, [doResolveUris, doSetSearchResults, stringifiedResults]); }, [doResolveUris, doSetMentionSearchResults, stringifiedResults]);
// Disable sending on Enter on Livestream chat // Disable sending on Enter on Livestream chat
React.useEffect(() => { React.useEffect(() => {
@ -355,7 +359,7 @@ export default function TextareaWithSuggestions(props: Props) {
id={id} id={id}
inputValue={messageValue} inputValue={messageValue}
loading={!allMatches || allMatches.length === 0 || showPlaceholder} loading={!allMatches || allMatches.length === 0 || showPlaceholder}
loadingText={results || showPlaceholder ? __('Searching...') : __('Nothing found')} loadingText={showPlaceholder ? <BusyIndicator message={__('Searching...')} /> : __('Nothing found')}
onBlur={() => onBlur && onBlur()} onBlur={() => onBlur && onBlur()}
/* Different from onInputChange, onChange is only used for the selected value, /* Different from onInputChange, onChange is only used for the selected value,
so here it is acting simply as a selection handler (see it as onSelect) */ so here it is acting simply as a selection handler (see it as onSelect) */
@ -366,7 +370,7 @@ export default function TextareaWithSuggestions(props: Props) {
onInputChange={(event, value, reason) => reason === 'input' && handleInputChange(value)} onInputChange={(event, value, reason) => reason === 'input' && handleInputChange(value)}
onOpen={() => suggestionTerm && setClose(false)} onOpen={() => suggestionTerm && setClose(false)}
/* 'open' is for the popper box component, set to check for a valid term /* 'open' is for the popper box component, set to check for a valid term
or else it will be displayed all the time as empty */ or else it will be displayed all the time as empty (no options) */
open={!!suggestionTerm && !shouldClose} open={!!suggestionTerm && !shouldClose}
options={allOptionsGrouped} options={allOptionsGrouped}
renderGroup={({ group, children }) => renderGroup(group, children)} renderGroup={({ group, children }) => renderGroup(group, children)}

View file

@ -230,7 +230,7 @@ export const SEARCH_SUCCESS = 'SEARCH_SUCCESS';
export const SEARCH_FAIL = 'SEARCH_FAIL'; export const SEARCH_FAIL = 'SEARCH_FAIL';
export const UPDATE_SEARCH_OPTIONS = 'UPDATE_SEARCH_OPTIONS'; export const UPDATE_SEARCH_OPTIONS = 'UPDATE_SEARCH_OPTIONS';
export const UPDATE_SEARCH_SUGGESTIONS = 'UPDATE_SEARCH_SUGGESTIONS'; export const UPDATE_SEARCH_SUGGESTIONS = 'UPDATE_SEARCH_SUGGESTIONS';
export const SET_SEARCH_RESULTS = 'SET_SEARCH_RESULTS'; export const SET_MENTION_SEARCH_RESULTS = 'SET_MENTION_SEARCH_RESULTS';
// Settings // Settings
export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED'; export const DAEMON_SETTINGS_RECEIVED = 'DAEMON_SETTINGS_RECEIVED';

View file

@ -147,9 +147,9 @@ export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptio
} }
}; };
export const doSetSearchResults = (uris: Array<string>) => (dispatch: Dispatch) => { export const doSetMentionSearchResults = (uris: Array<string>) => (dispatch: Dispatch) => {
dispatch({ dispatch({
type: ACTIONS.SET_SEARCH_RESULTS, type: ACTIONS.SET_MENTION_SEARCH_RESULTS,
data: { uris }, data: { uris },
}); });
}; };

View file

@ -68,7 +68,7 @@ export default handleActions(
}; };
}, },
[ACTIONS.SET_SEARCH_RESULTS]: (state: SearchState, action: SearchSuccess): SearchState => ({ [ACTIONS.SET_MENTION_SEARCH_RESULTS]: (state: SearchState, action: SearchSuccess): SearchState => ({
...state, ...state,
results: action.data.uris, results: action.data.uris,
}), }),

View file

@ -3,7 +3,7 @@ import { createSelector } from 'reselect';
import { createCachedSelector } from 're-reselect'; import { createCachedSelector } from 're-reselect';
import { selectMutedChannels } from 'redux/selectors/blocked'; import { selectMutedChannels } from 'redux/selectors/blocked';
import { selectShowMatureContent } from 'redux/selectors/settings'; import { selectShowMatureContent } from 'redux/selectors/settings';
import { selectSearchResults } from 'redux/selectors/search'; import { selectMentionSearchResults } from 'redux/selectors/search';
import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc'; import { selectBlacklistedOutpointMap, selectFilteredOutpointMap } from 'lbryinc';
import { import {
selectClaimsById, selectClaimsById,
@ -398,7 +398,7 @@ export const selectChannelMentionData = createCachedSelector(
selectClaimsById, selectClaimsById,
selectTopLevelCommentsForUri, selectTopLevelCommentsForUri,
selectSubscriptionUris, selectSubscriptionUris,
selectSearchResults, selectMentionSearchResults,
(uri, claimIdsByUri, claimsById, topLevelComments, subscriptionUris, searchUris) => { (uri, claimIdsByUri, claimsById, topLevelComments, subscriptionUris, searchUris) => {
let canonicalCreatorUri; let canonicalCreatorUri;
const commentorUris = []; const commentorUris = [];
@ -437,6 +437,7 @@ export const selectChannelMentionData = createCachedSelector(
} }
}); });
let hasNewResolvedResults = false;
if (searchUris && searchUris.length > 0) { if (searchUris && searchUris.length > 0) {
searchUris.forEach((uri) => { searchUris.forEach((uri) => {
// Update: canonicalSubscriptions // Update: canonicalSubscriptions
@ -446,8 +447,16 @@ export const selectChannelMentionData = createCachedSelector(
canonicalSearch.push(claim.canonical_url); canonicalSearch.push(claim.canonical_url);
} }
}); });
hasNewResolvedResults = canonicalSearch.length > 0;
} }
return { canonicalCommentors, canonicalCreatorUri, canonicalSubscriptions, commentorUris, canonicalSearch }; return {
canonicalCommentors,
canonicalCreatorUri,
canonicalSubscriptions,
commentorUris,
hasNewResolvedResults,
canonicalSearch,
};
} }
)((state, uri, maxCount) => `${String(uri)}:${maxCount}`); )((state, uri, maxCount) => `${String(uri)}:${maxCount}`);

View file

@ -32,7 +32,7 @@ export const selectSearchResultByQuery: (state: State) => { [string]: Array<stri
selectState(state).resultsByQuery; selectState(state).resultsByQuery;
export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = (state) => export const selectHasReachedMaxResultsLength: (state: State) => { [boolean]: Array<boolean> } = (state) =>
selectState(state).hasReachedMaxResultsLength; selectState(state).hasReachedMaxResultsLength;
export const selectSearchResults: (state: State) => Array<string> = (state) => selectState(state).results; export const selectMentionSearchResults: (state: State) => Array<string> = (state) => selectState(state).results;
export const makeSelectSearchUrisForQuery = (query: string): ((state: State) => Array<string>) => export const makeSelectSearchUrisForQuery = (query: string): ((state: State) => Array<string>) =>
createSelector(selectSearchResultByQuery, (byQuery) => { createSelector(selectSearchResultByQuery, (byQuery) => {

View file

@ -86,3 +86,7 @@
.textareaSuggestions__topSeparator { .textareaSuggestions__topSeparator {
@extend .wunderbar__top-separator; @extend .wunderbar__top-separator;
} }
.MuiAutocomplete-loading {
color: var(--color-text) !important;
}