Convert SearchHeader to reusable component and minor tweaks to DiscussionMessagesView
This commit is contained in:
parent
ad612e6073
commit
91dedfb620
|
@ -0,0 +1,52 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { withDimensions } from '../dimensions';
|
||||
import { isIOS, isTablet } from '../utils/deviceInfo';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from '../views/Styles';
|
||||
import TextInput from '../presentation/TextInput';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
marginLeft: 0
|
||||
},
|
||||
title: {
|
||||
...sharedStyles.textSemibold
|
||||
}
|
||||
});
|
||||
|
||||
const SearchHeader = ({
|
||||
onSearchChangeText, placeholder, theme, testID, width, height
|
||||
}) => {
|
||||
const isLight = theme === 'light';
|
||||
const isLandscape = width > height;
|
||||
const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1;
|
||||
const titleFontSize = 16 * scale;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput
|
||||
autoFocus
|
||||
style={[styles.title, isLight && { color: themes[theme].headerTitleColor }, { fontSize: titleFontSize }]}
|
||||
placeholder={placeholder}
|
||||
onChangeText={onSearchChangeText}
|
||||
theme={theme}
|
||||
testID={testID}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
SearchHeader.propTypes = {
|
||||
onSearchChangeText: PropTypes.func.isRequired,
|
||||
placeholder: PropTypes.string.isRequired,
|
||||
theme: PropTypes.string,
|
||||
testID: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number
|
||||
};
|
||||
export default withDimensions(SearchHeader);
|
|
@ -799,7 +799,7 @@ const RocketChat = {
|
|||
});
|
||||
},
|
||||
getDiscussions({
|
||||
roomId, offset, count, text = ''
|
||||
roomId, offset, count, text
|
||||
}) {
|
||||
const params = {
|
||||
roomId,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable react/prop-types */
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FlatList } from 'react-native';
|
||||
|
@ -18,10 +17,11 @@ import * as List from '../containers/List';
|
|||
import BackgroundContainer from '../containers/BackgroundContainer';
|
||||
import { isIOS } from '../utils/deviceInfo';
|
||||
import { getHeaderTitlePosition } from '../containers/Header';
|
||||
import SearchHeader from './ThreadMessagesView/SearchHeader';
|
||||
|
||||
import { useTheme } from '../theme';
|
||||
import Message from '../containers/message';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import SearchHeader from '../containers/SearchHeader';
|
||||
|
||||
const API_FETCH_COUNT = 25;
|
||||
|
||||
|
@ -31,19 +31,22 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
const autoTranslate = route.params?.autoTranslate;
|
||||
const autoTranslateLanguage = route.params?.autoTranslateLanguage;
|
||||
const navToRoomInfo = route.params?.navToRoomInfo;
|
||||
|
||||
const user = useSelector(state => state.login?.user);
|
||||
const baseUrl = useSelector(state => state.server.server);
|
||||
const useRealName = useSelector(state => state.settings.UI_Use_Real_Name);
|
||||
const Message_TimeFormat = useSelector(state => state.settings.Message_TimeFormat);
|
||||
const isMasterDetail = useSelector(state => state.app.isMasterDetail);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [discussions, setDiscussions] = useState([]);
|
||||
const [search, setSearch] = useState([]);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
|
||||
const { theme } = useTheme();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const load = async() => {
|
||||
const load = async(text = '') => {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
@ -52,8 +55,9 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
try {
|
||||
const result = await RocketChat.getDiscussions({
|
||||
roomId: rid,
|
||||
offset: discussions.length,
|
||||
count: API_FETCH_COUNT
|
||||
offset: isSearching ? search.length : discussions.length,
|
||||
count: API_FETCH_COUNT,
|
||||
text
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
|
@ -71,22 +75,8 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
};
|
||||
|
||||
const onSearchChangeText = debounce(async(text) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await RocketChat.getDiscussions({
|
||||
roomId: rid,
|
||||
offset: search.length,
|
||||
count: API_FETCH_COUNT,
|
||||
text
|
||||
});
|
||||
if (result.success) {
|
||||
setSearch(result.messages);
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
log(e);
|
||||
setLoading(false);
|
||||
}
|
||||
setIsSearching(true);
|
||||
await load(text);
|
||||
}, 300);
|
||||
|
||||
const onCancelSearchPress = () => {
|
||||
|
@ -111,7 +101,14 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
/>
|
||||
</HeaderButton.Container>
|
||||
),
|
||||
headerTitle: () => <SearchHeader placeholder='Search Messages' onSearchChangeText={onSearchChangeText} />,
|
||||
headerTitle: () => (
|
||||
<SearchHeader
|
||||
placeholder='Search Messages'
|
||||
onSearchChangeText={onSearchChangeText}
|
||||
theme={theme}
|
||||
testID='discussion-messages-view-search-header'
|
||||
/>
|
||||
),
|
||||
headerTitleContainerStyle: {
|
||||
left: headerTitlePosition.left,
|
||||
right: headerTitlePosition.right
|
||||
|
@ -199,7 +196,7 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
windowSize={10}
|
||||
initialNumToRender={7}
|
||||
removeClippedSubviews={isIOS}
|
||||
onEndReached={() => discussions.length > 25 ?? load()}
|
||||
onEndReached={() => discussions.length > API_FETCH_COUNT ?? load()}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
ListFooterComponent={loading ? <ActivityIndicator theme={theme} /> : null}
|
||||
scrollIndicatorInsets={{ right: 1 }}
|
||||
|
@ -210,7 +207,10 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
|||
|
||||
DiscussionMessagesView.propTypes = {
|
||||
navigation: PropTypes.object,
|
||||
route: PropTypes.object
|
||||
route: PropTypes.object,
|
||||
item: PropTypes.shape({
|
||||
msg: PropTypes.string
|
||||
})
|
||||
};
|
||||
|
||||
export default DiscussionMessagesView;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { connect } from 'react-redux';
|
|||
import StatusBar from '../containers/StatusBar';
|
||||
import RoomHeader from '../containers/RoomHeader';
|
||||
import { withTheme } from '../theme';
|
||||
import SearchHeader from './ThreadMessagesView/SearchHeader';
|
||||
|
||||
import log, { events, logEvent } from '../utils/log';
|
||||
import database from '../lib/database';
|
||||
import { getUserSelector } from '../selectors/login';
|
||||
|
@ -29,6 +29,7 @@ import { withActionSheet } from '../containers/ActionSheet';
|
|||
import { deleteRoom as deleteRoomAction } from '../actions/room';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import { themes } from '../constants/colors';
|
||||
import SearchHeader from '../containers/SearchHeader';
|
||||
|
||||
const API_FETCH_COUNT = 25;
|
||||
const PERMISSION_DELETE_C = 'delete-c';
|
||||
|
@ -162,7 +163,9 @@ class TeamChannelsView extends React.Component {
|
|||
|
||||
setHeader = () => {
|
||||
const { isSearching, showCreate, data } = this.state;
|
||||
const { navigation, isMasterDetail, insets } = this.props;
|
||||
const {
|
||||
navigation, isMasterDetail, insets, theme
|
||||
} = this.props;
|
||||
|
||||
const { team } = this;
|
||||
if (!team) {
|
||||
|
@ -182,7 +185,14 @@ class TeamChannelsView extends React.Component {
|
|||
/>
|
||||
</HeaderButton.Container>
|
||||
),
|
||||
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} />,
|
||||
headerTitle: () => (
|
||||
<SearchHeader
|
||||
onSearchChangeText={this.onSearchChangeText}
|
||||
placeholder='Search Channels'
|
||||
theme={theme}
|
||||
testID='team-channels-view-search-header'
|
||||
/>
|
||||
),
|
||||
headerTitleContainerStyle: {
|
||||
left: headerTitlePosition.left,
|
||||
right: headerTitlePosition.right
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useTheme, withTheme } from '../../theme';
|
||||
import sharedStyles from '../Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
import TextInput from '../../presentation/TextInput';
|
||||
import { isTablet, isIOS } from '../../utils/deviceInfo';
|
||||
import { useOrientation } from '../../dimensions';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
marginLeft: 0
|
||||
},
|
||||
title: {
|
||||
...sharedStyles.textSemibold
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: it might be useful to refactor this component for reusage
|
||||
const SearchHeader = ({ onSearchChangeText, placeholder }) => {
|
||||
const { theme } = useTheme();
|
||||
const titleColorStyle = { color: themes[theme].headerTitleColor };
|
||||
const isLight = theme === 'light';
|
||||
const { isLandscape } = useOrientation();
|
||||
const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1;
|
||||
const titleFontSize = 16 * scale;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput
|
||||
autoFocus
|
||||
style={[styles.title, isLight && titleColorStyle, { fontSize: titleFontSize }]}
|
||||
placeholder={placeholder || 'Search'}
|
||||
onChangeText={onSearchChangeText}
|
||||
theme={theme}
|
||||
testID='thread-messages-view-search-header'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
SearchHeader.propTypes = {
|
||||
onSearchChangeText: PropTypes.func,
|
||||
placeholder: PropTypes.string
|
||||
};
|
||||
export default withTheme(SearchHeader);
|
|
@ -32,9 +32,9 @@ import BackgroundContainer from '../../containers/BackgroundContainer';
|
|||
import { isIOS } from '../../utils/deviceInfo';
|
||||
import { getBadgeColor, makeThreadName } from '../../utils/room';
|
||||
import { getHeaderTitlePosition } from '../../containers/Header';
|
||||
import SearchHeader from './SearchHeader';
|
||||
import EventEmitter from '../../utils/events';
|
||||
import { LISTENER } from '../../containers/Toast';
|
||||
import SearchHeader from '../../containers/SearchHeader';
|
||||
|
||||
const API_FETCH_COUNT = 50;
|
||||
|
||||
|
@ -113,7 +113,7 @@ class ThreadMessagesView extends React.Component {
|
|||
/>
|
||||
</HeaderButton.Container>
|
||||
),
|
||||
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} />,
|
||||
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} placeholder='Search' theme={theme} testID='thread-messages-view-search-header' />,
|
||||
headerTitleContainerStyle: {
|
||||
left: headerTitlePosition.left,
|
||||
right: headerTitlePosition.right
|
||||
|
|
Loading…
Reference in New Issue