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({
|
getDiscussions({
|
||||||
roomId, offset, count, text = ''
|
roomId, offset, count, text
|
||||||
}) {
|
}) {
|
||||||
const params = {
|
const params = {
|
||||||
roomId,
|
roomId,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable react/prop-types */
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FlatList } from 'react-native';
|
import { FlatList } from 'react-native';
|
||||||
|
@ -18,10 +17,11 @@ import * as List from '../containers/List';
|
||||||
import BackgroundContainer from '../containers/BackgroundContainer';
|
import BackgroundContainer from '../containers/BackgroundContainer';
|
||||||
import { isIOS } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import { getHeaderTitlePosition } from '../containers/Header';
|
import { getHeaderTitlePosition } from '../containers/Header';
|
||||||
import SearchHeader from './ThreadMessagesView/SearchHeader';
|
|
||||||
import { useTheme } from '../theme';
|
import { useTheme } from '../theme';
|
||||||
import Message from '../containers/message';
|
import Message from '../containers/message';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import SearchHeader from '../containers/SearchHeader';
|
||||||
|
|
||||||
const API_FETCH_COUNT = 25;
|
const API_FETCH_COUNT = 25;
|
||||||
|
|
||||||
|
@ -31,19 +31,22 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
const autoTranslate = route.params?.autoTranslate;
|
const autoTranslate = route.params?.autoTranslate;
|
||||||
const autoTranslateLanguage = route.params?.autoTranslateLanguage;
|
const autoTranslateLanguage = route.params?.autoTranslateLanguage;
|
||||||
const navToRoomInfo = route.params?.navToRoomInfo;
|
const navToRoomInfo = route.params?.navToRoomInfo;
|
||||||
|
|
||||||
const user = useSelector(state => state.login?.user);
|
const user = useSelector(state => state.login?.user);
|
||||||
const baseUrl = useSelector(state => state.server.server);
|
const baseUrl = useSelector(state => state.server.server);
|
||||||
const useRealName = useSelector(state => state.settings.UI_Use_Real_Name);
|
const useRealName = useSelector(state => state.settings.UI_Use_Real_Name);
|
||||||
const Message_TimeFormat = useSelector(state => state.settings.Message_TimeFormat);
|
const Message_TimeFormat = useSelector(state => state.settings.Message_TimeFormat);
|
||||||
const isMasterDetail = useSelector(state => state.app.isMasterDetail);
|
const isMasterDetail = useSelector(state => state.app.isMasterDetail);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [discussions, setDiscussions] = useState([]);
|
const [discussions, setDiscussions] = useState([]);
|
||||||
const [search, setSearch] = useState([]);
|
const [search, setSearch] = useState([]);
|
||||||
const [isSearching, setIsSearching] = useState(false);
|
const [isSearching, setIsSearching] = useState(false);
|
||||||
|
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
const load = async() => {
|
const load = async(text = '') => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,8 +55,9 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.getDiscussions({
|
const result = await RocketChat.getDiscussions({
|
||||||
roomId: rid,
|
roomId: rid,
|
||||||
offset: discussions.length,
|
offset: isSearching ? search.length : discussions.length,
|
||||||
count: API_FETCH_COUNT
|
count: API_FETCH_COUNT,
|
||||||
|
text
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
@ -71,22 +75,8 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSearchChangeText = debounce(async(text) => {
|
const onSearchChangeText = debounce(async(text) => {
|
||||||
setLoading(true);
|
setIsSearching(true);
|
||||||
try {
|
await load(text);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
const onCancelSearchPress = () => {
|
const onCancelSearchPress = () => {
|
||||||
|
@ -111,7 +101,14 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</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: {
|
headerTitleContainerStyle: {
|
||||||
left: headerTitlePosition.left,
|
left: headerTitlePosition.left,
|
||||||
right: headerTitlePosition.right
|
right: headerTitlePosition.right
|
||||||
|
@ -199,7 +196,7 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
windowSize={10}
|
windowSize={10}
|
||||||
initialNumToRender={7}
|
initialNumToRender={7}
|
||||||
removeClippedSubviews={isIOS}
|
removeClippedSubviews={isIOS}
|
||||||
onEndReached={() => discussions.length > 25 ?? load()}
|
onEndReached={() => discussions.length > API_FETCH_COUNT ?? load()}
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
ListFooterComponent={loading ? <ActivityIndicator theme={theme} /> : null}
|
ListFooterComponent={loading ? <ActivityIndicator theme={theme} /> : null}
|
||||||
scrollIndicatorInsets={{ right: 1 }}
|
scrollIndicatorInsets={{ right: 1 }}
|
||||||
|
@ -210,7 +207,10 @@ const DiscussionMessagesView = ({ navigation, route }) => {
|
||||||
|
|
||||||
DiscussionMessagesView.propTypes = {
|
DiscussionMessagesView.propTypes = {
|
||||||
navigation: PropTypes.object,
|
navigation: PropTypes.object,
|
||||||
route: PropTypes.object
|
route: PropTypes.object,
|
||||||
|
item: PropTypes.shape({
|
||||||
|
msg: PropTypes.string
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DiscussionMessagesView;
|
export default DiscussionMessagesView;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { connect } from 'react-redux';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import RoomHeader from '../containers/RoomHeader';
|
import RoomHeader from '../containers/RoomHeader';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import SearchHeader from './ThreadMessagesView/SearchHeader';
|
|
||||||
import log, { events, logEvent } from '../utils/log';
|
import log, { events, logEvent } from '../utils/log';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
import { getUserSelector } from '../selectors/login';
|
import { getUserSelector } from '../selectors/login';
|
||||||
|
@ -29,6 +29,7 @@ import { withActionSheet } from '../containers/ActionSheet';
|
||||||
import { deleteRoom as deleteRoomAction } from '../actions/room';
|
import { deleteRoom as deleteRoomAction } from '../actions/room';
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
|
import SearchHeader from '../containers/SearchHeader';
|
||||||
|
|
||||||
const API_FETCH_COUNT = 25;
|
const API_FETCH_COUNT = 25;
|
||||||
const PERMISSION_DELETE_C = 'delete-c';
|
const PERMISSION_DELETE_C = 'delete-c';
|
||||||
|
@ -162,7 +163,9 @@ class TeamChannelsView extends React.Component {
|
||||||
|
|
||||||
setHeader = () => {
|
setHeader = () => {
|
||||||
const { isSearching, showCreate, data } = this.state;
|
const { isSearching, showCreate, data } = this.state;
|
||||||
const { navigation, isMasterDetail, insets } = this.props;
|
const {
|
||||||
|
navigation, isMasterDetail, insets, theme
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const { team } = this;
|
const { team } = this;
|
||||||
if (!team) {
|
if (!team) {
|
||||||
|
@ -182,7 +185,14 @@ class TeamChannelsView extends React.Component {
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</HeaderButton.Container>
|
||||||
),
|
),
|
||||||
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} />,
|
headerTitle: () => (
|
||||||
|
<SearchHeader
|
||||||
|
onSearchChangeText={this.onSearchChangeText}
|
||||||
|
placeholder='Search Channels'
|
||||||
|
theme={theme}
|
||||||
|
testID='team-channels-view-search-header'
|
||||||
|
/>
|
||||||
|
),
|
||||||
headerTitleContainerStyle: {
|
headerTitleContainerStyle: {
|
||||||
left: headerTitlePosition.left,
|
left: headerTitlePosition.left,
|
||||||
right: headerTitlePosition.right
|
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 { isIOS } from '../../utils/deviceInfo';
|
||||||
import { getBadgeColor, makeThreadName } from '../../utils/room';
|
import { getBadgeColor, makeThreadName } from '../../utils/room';
|
||||||
import { getHeaderTitlePosition } from '../../containers/Header';
|
import { getHeaderTitlePosition } from '../../containers/Header';
|
||||||
import SearchHeader from './SearchHeader';
|
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
import { LISTENER } from '../../containers/Toast';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
|
import SearchHeader from '../../containers/SearchHeader';
|
||||||
|
|
||||||
const API_FETCH_COUNT = 50;
|
const API_FETCH_COUNT = 50;
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ class ThreadMessagesView extends React.Component {
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</HeaderButton.Container>
|
||||||
),
|
),
|
||||||
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} />,
|
headerTitle: () => <SearchHeader onSearchChangeText={this.onSearchChangeText} placeholder='Search' theme={theme} testID='thread-messages-view-search-header' />,
|
||||||
headerTitleContainerStyle: {
|
headerTitleContainerStyle: {
|
||||||
left: headerTitlePosition.left,
|
left: headerTitlePosition.left,
|
||||||
right: headerTitlePosition.right
|
right: headerTitlePosition.right
|
||||||
|
|
Loading…
Reference in New Issue