vn-verdnaturachat/app/views/DiscussionsView/index.tsx

230 lines
6.1 KiB
TypeScript
Raw Normal View History

2021-07-21 17:29:22 +00:00
import React, { useEffect, useState } from 'react';
import { FlatList } from 'react-native';
import { useSelector } from 'react-redux';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
2021-10-13 21:09:50 +00:00
import { HeaderBackButton, StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
import { RouteProp } from '@react-navigation/core';
import { SubscriptionType } from '../../definitions';
import { ChatsStackParamList } from '../../stacks/types';
import ActivityIndicator from '../../containers/ActivityIndicator';
import I18n from '../../i18n';
import StatusBar from '../../containers/StatusBar';
import log from '../../utils/log';
import debounce from '../../utils/debounce';
import { themes } from '../../constants/colors';
import SafeAreaView from '../../containers/SafeAreaView';
import * as HeaderButton from '../../containers/HeaderButton';
import * as List from '../../containers/List';
import BackgroundContainer from '../../containers/BackgroundContainer';
import { isIOS } from '../../utils/deviceInfo';
import { getHeaderTitlePosition } from '../../containers/Header';
import { useTheme } from '../../theme';
import RocketChat from '../../lib/rocketchat';
import SearchHeader from '../../containers/SearchHeader';
import { TThreadModel } from '../../definitions/IThread';
import Item from './Item';
import styles from './styles';
2021-09-03 19:50:18 +00:00
2021-09-16 18:16:02 +00:00
const API_FETCH_COUNT = 50;
interface IDiscussionsViewProps {
navigation: StackNavigationProp<ChatsStackParamList, 'DiscussionsView'>;
route: RouteProp<ChatsStackParamList, 'DiscussionsView'>;
item: TThreadModel;
}
2021-11-04 18:25:05 +00:00
interface IDiscussionsViewState {
login: {
user: {
id: string;
token: string;
};
};
server: {
server: string;
};
settings: {
UI_Use_Real_Name: boolean;
Message_TimeFormat: string;
};
app: {
isMasterDetail: boolean;
};
}
const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Element => {
const rid = route.params?.rid;
2021-11-04 18:25:05 +00:00
const user = useSelector((state: IDiscussionsViewState) => state.login?.user);
const baseUrl = useSelector((state: IDiscussionsViewState) => state.server?.server);
const isMasterDetail = useSelector((state: IDiscussionsViewState) => state.app?.isMasterDetail);
const [loading, setLoading] = useState(false);
const [discussions, setDiscussions] = useState([]);
2021-09-03 19:50:18 +00:00
const [search, setSearch] = useState([]);
const [isSearching, setIsSearching] = useState(false);
2021-09-16 18:16:02 +00:00
const [total, setTotal] = useState(0);
const [searchTotal, setSearchTotal] = useState(0);
2021-07-21 17:29:22 +00:00
const { theme } = useTheme();
const insets = useSafeAreaInsets();
2021-09-16 18:16:02 +00:00
const load = async (text = '') => {
2021-07-21 17:29:22 +00:00
if (loading) {
return;
}
setLoading(true);
try {
2021-09-03 19:50:18 +00:00
const result = await RocketChat.getDiscussions({
roomId: rid,
offset: isSearching ? search.length : discussions.length,
count: API_FETCH_COUNT,
text
2021-09-03 19:50:18 +00:00
});
if (result.success) {
if (isSearching) {
setSearch(result.messages);
setSearchTotal(result.total);
2021-09-03 19:50:18 +00:00
} else {
setDiscussions(result.messages);
2021-09-16 18:16:02 +00:00
setTotal(result.total);
2021-09-03 19:50:18 +00:00
}
}
setLoading(false);
} catch (e) {
log(e);
2021-09-03 19:50:18 +00:00
setLoading(false);
}
2021-07-21 17:29:22 +00:00
};
const onSearchChangeText = debounce(async (text: string) => {
setIsSearching(true);
await load(text);
}, 300);
2021-07-21 17:29:22 +00:00
const onCancelSearchPress = () => {
setIsSearching(false);
2021-10-13 21:09:50 +00:00
setSearch([]);
setSearchTotal(0);
2021-07-21 17:29:22 +00:00
};
const onSearchPress = () => {
setIsSearching(true);
};
const setHeader = () => {
2021-10-13 21:09:50 +00:00
let options: Partial<StackNavigationOptions>;
if (isSearching) {
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight: 1 });
2021-10-13 21:09:50 +00:00
options = {
headerTitleAlign: 'left',
headerLeft: () => (
<HeaderButton.Container left>
2021-09-16 18:16:02 +00:00
<HeaderButton.Item iconName='close' onPress={onCancelSearchPress} />
</HeaderButton.Container>
),
headerTitle: () => (
<SearchHeader
placeholder='Search Messages'
onSearchChangeText={onSearchChangeText}
testID='discussion-messages-view-search-header'
/>
),
headerTitleContainerStyle: {
left: headerTitlePosition.left,
right: headerTitlePosition.right
},
headerRight: () => null
};
2021-10-13 21:09:50 +00:00
return options;
}
2021-10-13 21:09:50 +00:00
options = {
headerLeft: () => (
2021-10-13 21:12:02 +00:00
<HeaderBackButton labelVisible={false} onPress={() => navigation.pop()} tintColor={themes[theme!].headerTintColor} />
),
headerTitleAlign: 'center',
2021-07-21 17:29:22 +00:00
headerTitle: I18n.t('Discussions'),
headerTitleContainerStyle: {
left: null,
right: null
},
headerRight: () => (
<HeaderButton.Container>
<HeaderButton.Item iconName='search' onPress={onSearchPress} />
</HeaderButton.Container>
)
};
if (isMasterDetail) {
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} />;
}
return options;
};
useEffect(() => {
2021-07-21 17:29:22 +00:00
load();
2021-07-21 20:23:34 +00:00
}, []);
useEffect(() => {
2021-07-21 17:29:22 +00:00
const options = setHeader();
navigation.setOptions(options);
2021-07-21 20:23:34 +00:00
}, [navigation, isSearching]);
2021-09-16 18:16:02 +00:00
const onDiscussionPress = debounce(
(item: TThreadModel) => {
2021-09-16 18:16:02 +00:00
navigation.push('RoomView', {
rid: item.drid!,
2021-09-16 18:16:02 +00:00
prid: item.rid,
name: item.msg,
t: item.rid! === 'GENERAL' ? SubscriptionType.CHANNEL : SubscriptionType.GROUP
2021-09-16 18:16:02 +00:00
});
},
1000,
true
);
const renderItem = ({ item }: { item: TThreadModel }) => (
<Item
{...{
item,
user,
navigation,
baseUrl
}}
onPress={onDiscussionPress}
2021-07-21 17:29:22 +00:00
/>
);
if (!discussions?.length) {
2021-09-16 18:16:02 +00:00
return <BackgroundContainer loading={loading} text={I18n.t('No_discussions')} />;
}
return (
2021-09-17 19:26:48 +00:00
<SafeAreaView testID='discussions-view'>
<StatusBar />
<FlatList
2021-09-03 19:50:18 +00:00
data={isSearching ? search : discussions}
renderItem={renderItem}
keyExtractor={(item: any) => item.msg}
2021-11-04 19:44:52 +00:00
style={{ backgroundColor: themes[theme!].backgroundColor }}
contentContainerStyle={styles.contentContainer}
onEndReachedThreshold={0.5}
maxToRenderPerBatch={5}
windowSize={10}
initialNumToRender={7}
removeClippedSubviews={isIOS}
onEndReached={() => (searchTotal || total) > API_FETCH_COUNT ?? load()}
ItemSeparatorComponent={List.Separator}
ListFooterComponent={loading ? <ActivityIndicator theme={theme} /> : null}
2021-08-23 01:51:22 +00:00
scrollIndicatorInsets={{ right: 1 }}
/>
</SafeAreaView>
);
};
2021-09-16 18:16:02 +00:00
export default DiscussionsView;