[FIX] Spotlight (#1719)
This commit is contained in:
parent
3a87872415
commit
58e5781ed2
|
@ -37,7 +37,7 @@ const styles = StyleSheet.create({
|
|||
...sharedStyles.textRegular
|
||||
},
|
||||
cancel: {
|
||||
marginRight: 10
|
||||
marginRight: 15
|
||||
},
|
||||
cancelText: {
|
||||
...sharedStyles.textRegular,
|
||||
|
|
|
@ -565,18 +565,28 @@ const RocketChat = {
|
|||
RocketChat.spotlight(searchText, usernames, { users: filterUsers, rooms: filterRooms }),
|
||||
new Promise((resolve, reject) => this.oldPromise = reject)
|
||||
]);
|
||||
|
||||
data = data.concat(users.map(user => ({
|
||||
...user,
|
||||
rid: user.username,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
})), rooms.map(room => ({
|
||||
rid: room._id,
|
||||
...room,
|
||||
search: true
|
||||
})));
|
||||
if (filterUsers) {
|
||||
data = data.concat(users.map(user => ({
|
||||
...user,
|
||||
rid: user.username,
|
||||
name: user.username,
|
||||
t: 'd',
|
||||
search: true
|
||||
})));
|
||||
}
|
||||
if (filterRooms) {
|
||||
rooms.forEach((room) => {
|
||||
// Check if it exists on local database
|
||||
const index = data.findIndex(item => item.rid === room._id);
|
||||
if (index === -1) {
|
||||
data.push({
|
||||
rid: room._id,
|
||||
...room,
|
||||
search: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
delete this.oldPromise;
|
||||
return data;
|
||||
|
|
|
@ -38,6 +38,7 @@ class RoomsListHeaderView extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
handleCommands = ({ event }) => {
|
||||
if (handleCommandOpenServerDropdown(event)) {
|
||||
this.onPress();
|
||||
|
@ -79,7 +80,7 @@ class RoomsListHeaderView extends PureComponent {
|
|||
connecting={connecting}
|
||||
isFetching={isFetching}
|
||||
onPress={this.onPress}
|
||||
onSearchChangeText={text => this.onSearchChangeText(text)}
|
||||
onSearchChangeText={this.onSearchChangeText}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import DisclosureIndicator from '../../../containers/DisclosureIndicator';
|
|||
import { themes } from '../../../constants/colors';
|
||||
import { withTheme } from '../../../theme';
|
||||
|
||||
const Directory = React.memo(({ goDirectory, theme }) => {
|
||||
const Directory = React.memo(({ goDirectory, theme, searching }) => {
|
||||
if (searching > 0) {
|
||||
return null;
|
||||
}
|
||||
const color = { color: themes[theme].headerSecondaryText };
|
||||
return (
|
||||
<Touch
|
||||
|
@ -33,6 +36,7 @@ const Directory = React.memo(({ goDirectory, theme }) => {
|
|||
});
|
||||
|
||||
Directory.propTypes = {
|
||||
searching: PropTypes.bool,
|
||||
goDirectory: PropTypes.func,
|
||||
theme: PropTypes.string
|
||||
};
|
||||
|
|
|
@ -5,7 +5,9 @@ import SearchBox from '../../../containers/SearchBox';
|
|||
import { isIOS } from '../../../utils/deviceInfo';
|
||||
import { withTheme } from '../../../theme';
|
||||
|
||||
const SearchBar = React.memo(({ theme, onChangeSearchText, inputRef }) => {
|
||||
const SearchBar = React.memo(({
|
||||
theme, onChangeSearchText, inputRef, searching, onCancelSearchPress, onSearchFocus
|
||||
}) => {
|
||||
if (isIOS) {
|
||||
return (
|
||||
<SearchBox
|
||||
|
@ -13,6 +15,9 @@ const SearchBar = React.memo(({ theme, onChangeSearchText, inputRef }) => {
|
|||
testID='rooms-list-view-search'
|
||||
inputRef={inputRef}
|
||||
theme={theme}
|
||||
hasCancel={searching}
|
||||
onCancelPress={onCancelSearchPress}
|
||||
onFocus={onSearchFocus}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -21,8 +26,11 @@ const SearchBar = React.memo(({ theme, onChangeSearchText, inputRef }) => {
|
|||
|
||||
SearchBar.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
searching: PropTypes.bool,
|
||||
inputRef: PropTypes.func,
|
||||
onChangeSearchText: PropTypes.func
|
||||
onChangeSearchText: PropTypes.func,
|
||||
onCancelSearchPress: PropTypes.func,
|
||||
onSearchFocus: PropTypes.func
|
||||
};
|
||||
|
||||
export default withTheme(SearchBar);
|
||||
|
|
|
@ -11,9 +11,9 @@ import { withTheme } from '../../../theme';
|
|||
|
||||
|
||||
const Sort = React.memo(({
|
||||
searchLength, sortBy, toggleSort, theme
|
||||
searching, sortBy, toggleSort, theme
|
||||
}) => {
|
||||
if (searchLength > 0) {
|
||||
if (searching > 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
|
@ -36,7 +36,7 @@ const Sort = React.memo(({
|
|||
});
|
||||
|
||||
Sort.propTypes = {
|
||||
searchLength: PropTypes.number,
|
||||
searching: PropTypes.bool,
|
||||
sortBy: PropTypes.string,
|
||||
theme: PropTypes.string,
|
||||
toggleSort: PropTypes.func
|
||||
|
|
|
@ -6,22 +6,37 @@ import Directory from './Directory';
|
|||
import Sort from './Sort';
|
||||
|
||||
const ListHeader = React.memo(({
|
||||
searchLength, sortBy, onChangeSearchText, toggleSort, goDirectory, inputRef
|
||||
searching,
|
||||
sortBy,
|
||||
onChangeSearchText,
|
||||
toggleSort,
|
||||
goDirectory,
|
||||
inputRef,
|
||||
onCancelSearchPress,
|
||||
onSearchFocus
|
||||
}) => (
|
||||
<>
|
||||
<SearchBar onChangeSearchText={onChangeSearchText} inputRef={inputRef} />
|
||||
<Directory goDirectory={goDirectory} />
|
||||
<Sort searchLength={searchLength} sortBy={sortBy} toggleSort={toggleSort} />
|
||||
<SearchBar
|
||||
inputRef={inputRef}
|
||||
searching={searching}
|
||||
onChangeSearchText={onChangeSearchText}
|
||||
onCancelSearchPress={onCancelSearchPress}
|
||||
onSearchFocus={onSearchFocus}
|
||||
/>
|
||||
<Directory searching={searching} goDirectory={goDirectory} />
|
||||
<Sort searching={searching} sortBy={sortBy} toggleSort={toggleSort} />
|
||||
</>
|
||||
));
|
||||
|
||||
ListHeader.propTypes = {
|
||||
searchLength: PropTypes.number,
|
||||
searching: PropTypes.bool,
|
||||
sortBy: PropTypes.string,
|
||||
onChangeSearchText: PropTypes.func,
|
||||
toggleSort: PropTypes.func,
|
||||
goDirectory: PropTypes.func,
|
||||
inputRef: PropTypes.func
|
||||
inputRef: PropTypes.func,
|
||||
onCancelSearchPress: PropTypes.func,
|
||||
onSearchFocus: PropTypes.func
|
||||
};
|
||||
|
||||
export default ListHeader;
|
||||
|
|
|
@ -101,23 +101,21 @@ const keyExtractor = item => item.rid;
|
|||
class RoomsListView extends React.Component {
|
||||
static navigationOptions = ({ navigation, screenProps }) => {
|
||||
const searching = navigation.getParam('searching');
|
||||
const cancelSearchingAndroid = navigation.getParam(
|
||||
'cancelSearchingAndroid'
|
||||
);
|
||||
const cancelSearch = navigation.getParam('cancelSearch', () => {});
|
||||
const onPressItem = navigation.getParam('onPressItem', () => {});
|
||||
const initSearchingAndroid = navigation.getParam(
|
||||
'initSearchingAndroid',
|
||||
const initSearching = navigation.getParam(
|
||||
'initSearching',
|
||||
() => {}
|
||||
);
|
||||
|
||||
return {
|
||||
...themedHeader(screenProps.theme),
|
||||
headerLeft: searching ? (
|
||||
headerLeft: searching && isAndroid ? (
|
||||
<CustomHeaderButtons left>
|
||||
<Item
|
||||
title='cancel'
|
||||
iconName='cross'
|
||||
onPress={cancelSearchingAndroid}
|
||||
onPress={cancelSearch}
|
||||
/>
|
||||
</CustomHeaderButtons>
|
||||
) : (
|
||||
|
@ -127,13 +125,13 @@ class RoomsListView extends React.Component {
|
|||
/>
|
||||
),
|
||||
headerTitle: <RoomsListHeaderView />,
|
||||
headerRight: searching ? null : (
|
||||
headerRight: searching && isAndroid ? null : (
|
||||
<CustomHeaderButtons>
|
||||
{isAndroid ? (
|
||||
<Item
|
||||
title='search'
|
||||
iconName='magnifier'
|
||||
onPress={initSearchingAndroid}
|
||||
onPress={initSearching}
|
||||
/>
|
||||
) : null}
|
||||
<Item
|
||||
|
@ -200,8 +198,8 @@ class RoomsListView extends React.Component {
|
|||
const { navigation, closeServerDropdown } = this.props;
|
||||
navigation.setParams({
|
||||
onPressItem: this._onPressItem,
|
||||
initSearchingAndroid: this.initSearchingAndroid,
|
||||
cancelSearchingAndroid: this.cancelSearchingAndroid
|
||||
initSearching: this.initSearching,
|
||||
cancelSearch: this.cancelSearch
|
||||
});
|
||||
if (isTablet) {
|
||||
EventEmitter.addEventListener(KEY_COMMAND, this.handleCommands);
|
||||
|
@ -247,7 +245,7 @@ class RoomsListView extends React.Component {
|
|||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const { allChats } = this.state;
|
||||
const { allChats, searching } = this.state;
|
||||
// eslint-disable-next-line react/destructuring-assignment
|
||||
const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]);
|
||||
if (propsUpdated) {
|
||||
|
@ -262,6 +260,10 @@ class RoomsListView extends React.Component {
|
|||
this.shouldUpdate = true;
|
||||
}
|
||||
|
||||
if (nextState.searching !== searching) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Abort if it's not focused
|
||||
if (!nextProps.navigation.isFocused()) {
|
||||
return false;
|
||||
|
@ -269,16 +271,12 @@ class RoomsListView extends React.Component {
|
|||
|
||||
const {
|
||||
loading,
|
||||
searching,
|
||||
width,
|
||||
search
|
||||
} = this.state;
|
||||
if (nextState.loading !== loading) {
|
||||
return true;
|
||||
}
|
||||
if (nextState.searching !== searching) {
|
||||
return true;
|
||||
}
|
||||
if (nextState.width !== width) {
|
||||
return true;
|
||||
}
|
||||
|
@ -452,29 +450,50 @@ class RoomsListView extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
initSearchingAndroid = () => {
|
||||
initSearching = () => {
|
||||
const { openSearchHeader, navigation } = this.props;
|
||||
this.setState({ searching: true });
|
||||
navigation.setParams({ searching: true });
|
||||
openSearchHeader();
|
||||
this.internalSetState({ searching: true });
|
||||
if (isAndroid) {
|
||||
navigation.setParams({ searching: true });
|
||||
openSearchHeader();
|
||||
}
|
||||
};
|
||||
|
||||
cancelSearchingAndroid = () => {
|
||||
cancelSearch = () => {
|
||||
const { searching } = this.state;
|
||||
const { closeSearchHeader, navigation } = this.props;
|
||||
|
||||
if (!searching) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isIOS && this.inputRef) {
|
||||
this.inputRef.blur();
|
||||
this.inputRef.clear();
|
||||
}
|
||||
if (isAndroid) {
|
||||
const { closeSearchHeader, navigation } = this.props;
|
||||
this.setState({ searching: false });
|
||||
navigation.setParams({ searching: false });
|
||||
closeSearchHeader();
|
||||
this.internalSetState({ search: [] });
|
||||
}
|
||||
Keyboard.dismiss();
|
||||
|
||||
this.setState({ searching: false, search: [] }, () => {
|
||||
setTimeout(() => {
|
||||
const offset = isAndroid ? 0 : SCROLL_OFFSET;
|
||||
if (this.scroll.scrollTo) {
|
||||
this.scroll.scrollTo({ x: 0, y: offset, animated: true });
|
||||
} else if (this.scroll.scrollToOffset) {
|
||||
this.scroll.scrollToOffset({ offset });
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
};
|
||||
|
||||
handleBackPress = () => {
|
||||
const { searching } = this.state;
|
||||
const { appStart } = this.props;
|
||||
if (searching) {
|
||||
this.cancelSearchingAndroid();
|
||||
this.cancelSearch();
|
||||
return true;
|
||||
}
|
||||
appStart('background');
|
||||
|
@ -483,10 +502,19 @@ class RoomsListView extends React.Component {
|
|||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
search = debounce(async(text) => {
|
||||
const { searching } = this.state;
|
||||
const result = await RocketChat.search({ text });
|
||||
// if the search was cancelled before the promise is resolved
|
||||
if (!searching) {
|
||||
return;
|
||||
}
|
||||
this.internalSetState({
|
||||
search: result
|
||||
search: result,
|
||||
searching: true
|
||||
});
|
||||
if (this.scroll && this.scroll.scrollTo) {
|
||||
this.scroll.scrollTo({ x: 0, y: 0, animated: true });
|
||||
}
|
||||
}, 300);
|
||||
|
||||
getRoomTitle = item => RocketChat.getRoomTitle(item)
|
||||
|
@ -494,8 +522,8 @@ class RoomsListView extends React.Component {
|
|||
getRoomAvatar = item => RocketChat.getRoomAvatar(item)
|
||||
|
||||
goRoom = (item) => {
|
||||
this.cancelSearchingAndroid();
|
||||
const { navigation } = this.props;
|
||||
this.cancelSearch();
|
||||
this.item = item;
|
||||
navigation.navigate('RoomView', {
|
||||
rid: item.rid,
|
||||
|
@ -678,21 +706,29 @@ class RoomsListView extends React.Component {
|
|||
};
|
||||
|
||||
onRefresh = () => {
|
||||
const { searching } = this.state;
|
||||
const { roomsRequest } = this.props;
|
||||
if (searching) {
|
||||
return;
|
||||
}
|
||||
roomsRequest({ allData: true });
|
||||
}
|
||||
|
||||
getScrollRef = ref => (this.scroll = ref);
|
||||
|
||||
getInputRef = ref => (this.inputRef = ref);
|
||||
|
||||
renderListHeader = () => {
|
||||
const { search } = this.state;
|
||||
const { searching } = this.state;
|
||||
const { sortBy } = this.props;
|
||||
return (
|
||||
<ListHeader
|
||||
inputRef={(ref) => { this.inputRef = ref; }}
|
||||
searchLength={search.length}
|
||||
inputRef={this.getInputRef}
|
||||
searching={searching}
|
||||
sortBy={sortBy}
|
||||
onChangeSearchText={this.search}
|
||||
onCancelSearchPress={this.cancelSearch}
|
||||
onSearchFocus={this.initSearching}
|
||||
toggleSort={this.toggleSort}
|
||||
goDirectory={this.goDirectory}
|
||||
/>
|
||||
|
@ -768,7 +804,7 @@ class RoomsListView extends React.Component {
|
|||
|
||||
renderScroll = () => {
|
||||
const {
|
||||
loading, chats, search
|
||||
loading, chats, search, searching
|
||||
} = this.state;
|
||||
const { theme, refreshing } = this.props;
|
||||
|
||||
|
@ -779,8 +815,8 @@ class RoomsListView extends React.Component {
|
|||
return (
|
||||
<FlatList
|
||||
ref={this.getScrollRef}
|
||||
data={search.length ? search : chats}
|
||||
extraData={search.length ? search : chats}
|
||||
data={searching ? search : chats}
|
||||
extraData={searching ? search : chats}
|
||||
contentOffset={isIOS ? { x: 0, y: SCROLL_OFFSET } : {}}
|
||||
keyExtractor={keyExtractor}
|
||||
style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
|
|
Loading…
Reference in New Issue