[Gekidou MM-44940] Add autocomplete to navigation search (#6516)

* implement so that autocomplete will track the collapsable header

* add search screen

* move autocomplete to it's own view and add zindex to the view so it sits
atop the modifiers and results

* remove unused imports

* - remove console.log
- paddingTop is optional

* remove comments

* remove commented code

* - use a more reasonable zindex value. On more than in Nav Header
- use consts for autocomplete padding top

* remvoe search screen button

* - add dependencies

* - remove search button

* - not needed

* move autocomplete zindex to constant

* - move autocomplete directly below NavigationHeader
- adjust distance from search box

* - remove setXX from dependencies
- remove useMemo because only returning the component

* remove these changes. after placing autocomplete correcting in the
search component, this works as expected

* without this setting, ios has the issue where autocomplete is open,
transparent, and has height.  The user cannot click any modifiers.

* - need usememot for autocomplete
- add isSearch to remote runSearch function as option to hit the search
  for autocomplete API option
- Initial component needs handleTextChange callback to set the
  cursorPosition correctly

* use ternary operator
This commit is contained in:
Jason Frerich
2022-08-05 07:15:12 -05:00
committed by GitHub
parent ba5c49d9fc
commit aec0ccb105
4 changed files with 39 additions and 12 deletions

View File

@@ -1147,7 +1147,7 @@ export async function switchToLastChannel(serverUrl: string, teamId?: string) {
}
}
export async function searchChannels(serverUrl: string, term: string) {
export async function searchChannels(serverUrl: string, term: string, isSearch = false) {
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
if (!database) {
return {error: `${serverUrl} database not found`};
@@ -1162,7 +1162,8 @@ export async function searchChannels(serverUrl: string, term: string) {
try {
const currentTeamId = await getCurrentTeamId(database);
const channels = await client.autocompleteChannels(currentTeamId, term);
const autoCompleteFunc = isSearch ? client.autocompleteChannelsForSearch : client.autocompleteChannels;
const channels = await autoCompleteFunc(currentTeamId, term);
return {channels};
} catch (error) {
return {error};

View File

@@ -55,6 +55,7 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
type Props = {
cursorPosition: number;
postInputTop: number;
paddingTop?: number;
rootId?: string;
channelId?: string;
fixedBottomPosition?: boolean;
@@ -72,6 +73,7 @@ type Props = {
const Autocomplete = ({
cursorPosition,
postInputTop,
paddingTop,
rootId,
channelId,
isSearch = false,
@@ -124,10 +126,10 @@ const Autocomplete = ({
s.push(style.shadow);
}
if (isSearch) {
s.push(style.base, style.searchContainer, {height: maxListHeight});
s.push(style.base, paddingTop ? {top: paddingTop} : style.searchContainer, {maxHeight: maxListHeight});
}
return s;
}, [style, isSearch && maxListHeight, hasElements]);
}, [style, isSearch && maxListHeight, paddingTop]);
const containerStyles = useMemo(() => {
const s = [];

View File

@@ -218,7 +218,7 @@ const ChannelMention = ({
const runSearch = useMemo(() => debounce(async (sUrl: string, term: string) => {
setLoading(true);
const {channels: receivedChannels, error} = await searchChannels(sUrl, term);
const {channels: receivedChannels, error} = await searchChannels(sUrl, term, isSearch);
setUseLocal(Boolean(error));
if (error) {

View File

@@ -10,6 +10,7 @@ import {Edge, SafeAreaView} from 'react-native-safe-area-context';
import {addSearchToTeamSearchHistory} from '@actions/local/team';
import {searchPosts, searchFiles} from '@actions/remote/search';
import Autocomplete from '@components/autocomplete';
import FreezeScreen from '@components/freeze_screen';
import Loading from '@components/loading';
import NavigationHeader from '@components/navigation_header';
@@ -33,6 +34,9 @@ const emptyChannelIds: string[] = [];
const dummyData = [1];
const AutocompletePaddingTop = -4;
const AutocompleteZindex = 11;
type Props = {
teamId: string;
}
@@ -69,6 +73,7 @@ const SearchScreen = ({teamId}: Props) => {
const serverUrl = useServerUrl();
const searchTerm = (nav.getState().routes[stateIndex].params as any)?.searchTerm;
const [cursorPosition, setCursorPosition] = useState(searchTerm?.length);
const [searchValue, setSearchValue] = useState<string>(searchTerm);
const [searchTeamId, setSearchTeamId] = useState<string>(teamId);
const [selectedTab, setSelectedTab] = useState<TabType>(TabTypes.MESSAGES);
@@ -88,11 +93,16 @@ const SearchScreen = ({teamId}: Props) => {
const {scrollPaddingTop, scrollRef, scrollValue, onScroll, headerHeight, hideHeader} = useCollapsibleHeader<FlatList>(true, onSnap);
const handleTextChange = useCallback((newValue: string) => {
setSearchValue(newValue);
setCursorPosition(newValue.length);
}, []);
const handleClearSearch = useCallback(() => {
setSearchValue('');
handleTextChange('');
setLastSearchedValue('');
setFilter(FileFilters.ALL);
}, []);
}, [handleTextChange]);
const handleCancelSearch = useCallback(() => {
handleClearSearch();
@@ -127,9 +137,9 @@ const SearchScreen = ({teamId}: Props) => {
}, [handleSearch, searchTeamId, searchValue]);
const handleRecentSearch = useCallback((text: string) => {
setSearchValue(text);
handleTextChange(text);
handleSearch(searchTeamId, text);
}, [handleSearch, searchTeamId]);
}, [handleSearch, handleTextChange, searchTeamId]);
const handleFilterChange = useCallback(async (filterValue: FileFilter) => {
setLoading(true);
@@ -159,11 +169,11 @@ const SearchScreen = ({teamId}: Props) => {
<Initial
searchValue={searchValue}
setRecentValue={handleRecentSearch}
setSearchValue={setSearchValue}
setSearchValue={handleTextChange}
setTeamId={setSearchTeamId}
teamId={searchTeamId}
/>
), [searchValue, searchTeamId, handleRecentSearch]);
), [searchValue, searchTeamId, handleRecentSearch, handleTextChange]);
const resultsComponent = useMemo(() => (
<Results
@@ -229,6 +239,17 @@ const SearchScreen = ({teamId}: Props) => {
/>
);
}
const autocomplete = useMemo(() => (
<Autocomplete
paddingTop={AutocompletePaddingTop}
postInputTop={0}
updateValue={handleTextChange}
cursorPosition={cursorPosition}
value={searchValue}
isSearch={true}
hasFilesAttached={false}
/>
), [cursorPosition, handleTextChange, searchValue]);
return (
<FreezeScreen freeze={!isFocused}>
@@ -239,7 +260,7 @@ const SearchScreen = ({teamId}: Props) => {
hasSearch={true}
scrollValue={scrollValue}
hideHeader={hideHeader}
onChangeText={setSearchValue}
onChangeText={handleTextChange}
onSubmitEditing={onSubmit}
blurOnSubmit={true}
placeholder={intl.formatMessage({id: 'screen.search.placeholder', defaultMessage: 'Search messages & files'})}
@@ -247,6 +268,9 @@ const SearchScreen = ({teamId}: Props) => {
onCancel={handleCancelSearch}
defaultValue={searchValue}
/>
<Animated.View style={[top, {zIndex: AutocompleteZindex}]}>
{autocomplete}
</Animated.View>
<SafeAreaView
style={styles.flex}
edges={EDGES}