Rocket.Chat.ReactNative/app/views/DiscussionsView/index.tsx

205 lines
5.6 KiB
TypeScript
Raw Normal View History

import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
2022-01-24 19:18:59 +00:00
import { FlatList, StyleSheet } from 'react-native';
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
import { HeaderBackButton } from '@react-navigation/elements';
2021-10-13 21:09:50 +00:00
import { RouteProp } from '@react-navigation/core';
import { IMessageFromServer, TThreadModel } from '../../definitions';
import { ChatsStackParamList } from '../../stacks/types';
import ActivityIndicator from '../../containers/ActivityIndicator';
import I18n from '../../i18n';
import StatusBar from '../../containers/StatusBar';
import log from '../../lib/methods/helpers/log';
import { isIOS, useDebounce } from '../../lib/methods/helpers';
import SafeAreaView from '../../containers/SafeAreaView';
import * as HeaderButton from '../../containers/HeaderButton';
import * as List from '../../containers/List';
import BackgroundContainer from '../../containers/BackgroundContainer';
import { useTheme } from '../../theme';
import SearchHeader from '../../containers/SearchHeader';
import Item from './Item';
import { Services } from '../../lib/services';
import { useAppSelector } from '../../lib/hooks';
2021-09-03 19:50:18 +00:00
2021-09-16 18:16:02 +00:00
const API_FETCH_COUNT = 50;
2022-01-24 19:18:59 +00:00
const styles = StyleSheet.create({
contentContainer: {
marginBottom: 30
}
});
interface IDiscussionsViewProps {
navigation: StackNavigationProp<ChatsStackParamList, 'DiscussionsView'>;
route: RouteProp<ChatsStackParamList, 'DiscussionsView'>;
item: TThreadModel;
}
const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): React.ReactElement => {
const rid = route.params?.rid;
const t = route.params?.t;
const baseUrl = useAppSelector(state => state.server?.server);
const isMasterDetail = useAppSelector(state => state.app?.isMasterDetail);
const [loading, setLoading] = useState(false);
const [discussions, setDiscussions] = useState<IMessageFromServer[]>([]);
const [search, setSearch] = useState<IMessageFromServer[]>([]);
const [isSearching, setIsSearching] = useState(false);
const total = useRef(0);
const searchText = useRef('');
const offset = useRef(0);
const { colors } = useTheme();
const load = async () => {
2021-07-21 17:29:22 +00:00
if (loading) {
return;
}
setLoading(true);
try {
const result = await Services.getDiscussions({
2021-09-03 19:50:18 +00:00
roomId: rid,
offset: offset.current,
count: API_FETCH_COUNT,
text: searchText.current
2021-09-03 19:50:18 +00:00
});
if (result.success) {
offset.current += result.count;
total.current = result.total;
2021-09-03 19:50:18 +00:00
if (isSearching) {
setSearch(prevState => (offset.current ? [...prevState, ...result.messages] : result.messages));
2021-09-03 19:50:18 +00:00
} else {
setDiscussions(result.messages);
}
}
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 = useDebounce((text: string) => {
setIsSearching(true);
setSearch([]);
searchText.current = text;
offset.current = 0;
load();
}, 500);
2021-07-21 17:29:22 +00:00
const onCancelSearchPress = () => {
setIsSearching(false);
2021-10-13 21:09:50 +00:00
setSearch([]);
searchText.current = '';
offset.current = 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) {
2021-10-13 21:09:50 +00:00
options = {
headerTitleAlign: 'left',
headerTitleContainerStyle: { flex: 1, marginHorizontal: 0, marginRight: 15, maxWidth: undefined },
headerRightContainerStyle: { flexGrow: 0 },
headerLeft: () => (
<HeaderButton.Container left>
2021-09-16 18:16:02 +00:00
<HeaderButton.Item iconName='close' onPress={onCancelSearchPress} />
</HeaderButton.Container>
),
headerTitle: () => (
<SearchHeader onSearchChangeText={onSearchChangeText} testID='discussion-messages-view-search-header' />
),
headerRight: () => null
};
2021-10-13 21:09:50 +00:00
return options;
}
2021-10-13 21:09:50 +00:00
options = {
headerTitleAlign: 'center',
headerTitle: I18n.t('Discussions'),
headerTitleContainerStyle: {},
headerRightContainerStyle: { flexGrow: 1 },
headerLeft: () => (
2022-11-16 13:26:37 +00:00
<HeaderBackButton
labelVisible={false}
onPress={() => navigation.pop()}
feat: mobile color normalization (#5616) * chore: remove auxiliaryText color * chore: remove titleText * chore: password colors change * chore: use fontDefault on ActionSheet item * wip: type * chore: set custom icon default color * remove tintActive color * only set color when checked * remove icon color * remove tintActive * chore: remove STATUS_COLORS * chore: remove mentions colors * chore: remove switch color * chore: background color * chore: auxiliaryBackground * chore: one local colors * wip: some colors * wip: colors * wip: colors * wip: end colors * test: update * chore: fix some colors * chore: fix lint * chore: back to text props * chore: fix ts errors * revert * chore: fix lint * test: update snapshot * update storybook * cocoapods * fix app theme color * remove unused color * fix login service button color * remove unused color * unused backgroundColor * fix background color * fix transparent color * fix background color * wip: key * fix color * chore: revert to 1 tick * test: update * chore: use same color as front end * test: update * fix radius * fix background color * fix wrong color * change some colors * chore: update stories * chore: fix button style * chore: fix item color * lint * update snapshot * link * remove background color * change send to channel color * call icons * video conf colors * fix app default color * bottom sheet * remove background * two factor color * update tests * feat: add force-logout stream listener * remove icon colors * improve badge color * update tests * fix header colors * fix collapsible icon color * imagePreview color * wip * update test * lint --------- Co-authored-by: Diego Mello <diegolmello@gmail.com>
2024-04-18 10:19:54 +00:00
tintColor={colors.fontSecondaryInfo}
2022-11-16 13:26:37 +00:00
testID='header-back'
/>
),
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
}, []);
useLayoutEffect(() => {
2021-07-21 17:29:22 +00:00
const options = setHeader();
navigation.setOptions(options);
2021-07-21 20:23:34 +00:00
}, [navigation, isSearching]);
const onDiscussionPress = (item: TThreadModel) => {
if (item.drid && item.t) {
navigation.push('RoomView', {
rid: item.drid,
prid: item.rid,
name: item.msg,
t
});
}
};
const renderItem = ({ item }: { item: IMessageFromServer }) => (
<Item
{...{
item,
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')} />;
}
2022-01-31 21:21:26 +00:00
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._id}
feat: mobile color normalization (#5616) * chore: remove auxiliaryText color * chore: remove titleText * chore: password colors change * chore: use fontDefault on ActionSheet item * wip: type * chore: set custom icon default color * remove tintActive color * only set color when checked * remove icon color * remove tintActive * chore: remove STATUS_COLORS * chore: remove mentions colors * chore: remove switch color * chore: background color * chore: auxiliaryBackground * chore: one local colors * wip: some colors * wip: colors * wip: colors * wip: end colors * test: update * chore: fix some colors * chore: fix lint * chore: back to text props * chore: fix ts errors * revert * chore: fix lint * test: update snapshot * update storybook * cocoapods * fix app theme color * remove unused color * fix login service button color * remove unused color * unused backgroundColor * fix background color * fix transparent color * fix background color * wip: key * fix color * chore: revert to 1 tick * test: update * chore: use same color as front end * test: update * fix radius * fix background color * fix wrong color * change some colors * chore: update stories * chore: fix button style * chore: fix item color * lint * update snapshot * link * remove background color * change send to channel color * call icons * video conf colors * fix app default color * bottom sheet * remove background * two factor color * update tests * feat: add force-logout stream listener * remove icon colors * improve badge color * update tests * fix header colors * fix collapsible icon color * imagePreview color * wip * update test * lint --------- Co-authored-by: Diego Mello <diegolmello@gmail.com>
2024-04-18 10:19:54 +00:00
style={{ backgroundColor: colors.surfaceRoom }}
contentContainerStyle={styles.contentContainer}
onEndReachedThreshold={0.5}
removeClippedSubviews={isIOS}
onEndReached={() => isSearching && offset.current < total.current && load()}
ItemSeparatorComponent={List.Separator}
ListFooterComponent={loading ? <ActivityIndicator /> : null}
2021-08-23 01:51:22 +00:00
scrollIndicatorInsets={{ right: 1 }}
/>
</SafeAreaView>
);
};
2021-09-16 18:16:02 +00:00
export default DiscussionsView;