diff --git a/app/containers/Avatar/interfaces.ts b/app/containers/Avatar/interfaces.ts
index 692c4d0a..2ff48146 100644
--- a/app/containers/Avatar/interfaces.ts
+++ b/app/containers/Avatar/interfaces.ts
@@ -1,19 +1,19 @@
export interface IAvatar {
- server: string;
+ server?: string;
style: any;
text: string;
- avatar: string;
+ avatar?: string;
emoji: string;
size: number;
borderRadius: number;
- type: string;
- children: JSX.Element;
+ type?: string;
+ children?: JSX.Element;
user: {
id: string;
token: string;
};
theme: string;
- onPress(): void;
+ onPress?(): void;
getCustomEmoji(): any;
avatarETag: string;
isStatic: boolean;
diff --git a/app/containers/ThreadDetails.tsx b/app/containers/ThreadDetails.tsx
index 86f670f0..054d7595 100644
--- a/app/containers/ThreadDetails.tsx
+++ b/app/containers/ThreadDetails.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
@@ -41,8 +42,9 @@ const styles = StyleSheet.create({
interface IThreadDetails {
item: {
- tcount: number | string;
- replies: any;
+ tcount?: number | string;
+ dcount?: number | string;
+ replies?: any;
id: string;
};
user: {
@@ -50,16 +52,25 @@ interface IThreadDetails {
};
badgeColor: string;
toggleFollowThread: Function;
+ thread: boolean;
style: object;
theme: string;
}
-const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, theme }: IThreadDetails) => {
- let { tcount } = item;
- if (tcount >= 1000) {
- tcount = '+999';
- } else if (tcount >= 100) {
- tcount = '+99';
+const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, thread, style, theme }: IThreadDetails) => {
+ let { tcount, dcount } = item;
+ if (thread) {
+ if (tcount! >= 1000) {
+ tcount = '+999';
+ } else if (tcount! >= 100) {
+ tcount = '+99';
+ }
+ }
+
+ if (dcount! >= 1000) {
+ dcount = '+999';
+ } else if (dcount! >= 100) {
+ dcount = '+99';
}
let replies = item?.replies?.length ?? 0;
@@ -75,30 +86,34 @@ const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, them
-
+
- {tcount}
+ {thread ? tcount : dcount}
-
-
-
- {replies}
-
-
+ {thread ? (
+
+
+
+ {replies}
+
+
+ ) : null}
-
- {badgeColor ? : null}
- toggleFollowThread?.(isFollowing, item.id)}>
-
-
-
+ {thread ? (
+
+ {badgeColor ? : null}
+ toggleFollowThread?.(isFollowing, item.id)}>
+
+
+
+ ) : null}
);
};
diff --git a/app/containers/markdown/index.tsx b/app/containers/markdown/index.tsx
index d3ce8453..0aec122f 100644
--- a/app/containers/markdown/index.tsx
+++ b/app/containers/markdown/index.tsx
@@ -23,25 +23,25 @@ import { isValidURL } from '../../utils/url';
interface IMarkdownProps {
msg: string;
- getCustomEmoji: Function;
+ getCustomEmoji?: Function;
baseUrl: string;
username: string;
- tmid: string;
- isEdited: boolean;
- numberOfLines: number;
- customEmojis: boolean;
- useRealName: boolean;
- channels: {
+ tmid?: string;
+ isEdited?: boolean;
+ numberOfLines?: number;
+ customEmojis?: boolean;
+ useRealName?: boolean;
+ channels?: {
name: string;
_id: number;
}[];
- mentions: object[];
- navToRoomInfo: Function;
- preview: boolean;
- theme: string;
- testID: string;
- style: any;
- onLinkPress: Function;
+ mentions?: object[];
+ navToRoomInfo?: Function;
+ preview?: boolean;
+ theme?: string;
+ testID?: string;
+ style?: any;
+ onLinkPress?: Function;
}
type TLiteral = {
diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js
index b9af9e87..0604d6d4 100644
--- a/app/lib/rocketchat.js
+++ b/app/lib/rocketchat.js
@@ -807,21 +807,17 @@ const RocketChat = {
encrypted
});
},
- getDiscussions({
- roomId, offset, count, text
- }) {
+ getDiscussions({ roomId, offset, count, text }) {
const params = {
roomId,
offset,
count,
- text
+ ...(text && { text })
};
// RC 2.4.0
return this.sdk.get('chat.getDiscussions', params);
},
- createTeam({
- name, users, type, readOnly, broadcast, encrypted
- }) {
+ createTeam({ name, users, type, readOnly, broadcast, encrypted }) {
const params = {
name,
users,
diff --git a/app/views/DiscussionsView.js b/app/views/DiscussionsView/index.tsx
similarity index 57%
rename from app/views/DiscussionsView.js
rename to app/views/DiscussionsView/index.tsx
index e5286379..81881674 100644
--- a/app/views/DiscussionsView.js
+++ b/app/views/DiscussionsView/index.tsx
@@ -1,48 +1,76 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import React, { useEffect, useState } from 'react';
-import PropTypes from 'prop-types';
import { FlatList } from 'react-native';
import { useSelector } from 'react-redux';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { HeaderBackButton } from '@react-navigation/stack';
-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 Message from '../containers/message';
-import RocketChat from '../lib/rocketchat';
-import SearchHeader from '../containers/SearchHeader';
+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 Item from '../ThreadMessagesView/Item';
+import styles from './styles';
const API_FETCH_COUNT = 50;
-const DiscussionsView = ({ navigation, route }) => {
- const rid = route.params?.rid;
- const canAutoTranslate = route.params?.canAutoTranslate;
- const autoTranslate = route.params?.autoTranslate;
- const autoTranslateLanguage = route.params?.autoTranslateLanguage;
- const navToRoomInfo = route.params?.navToRoomInfo;
+interface IDiscussionsViewProps {
+ navigation: any;
+ route: {
+ params?: {
+ rid: string;
+ canAutoTranslate: boolean;
+ autoTranslate: boolean;
+ autoTranslateLanguage: string;
+ navToRoomInfo: Function;
+ };
+ };
+ item: {
+ msg: string;
+ };
+}
- 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);
+interface IState {
+ login?: {
+ user: object;
+ };
+ 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;
+
+ const user = useSelector((state: IState) => state.login?.user);
+ const baseUrl = useSelector((state: IState) => state.server?.server);
+ const useRealName = useSelector((state: IState) => state.settings?.UI_Use_Real_Name);
+ const isMasterDetail = useSelector((state: IState) => state.app?.isMasterDetail);
const [loading, setLoading] = useState(false);
const [discussions, setDiscussions] = useState([]);
const [search, setSearch] = useState([]);
const [isSearching, setIsSearching] = useState(false);
const [total, setTotal] = useState(0);
+ const [searchTotal, setSearchTotal] = useState(0);
const { theme } = useTheme();
const insets = useSafeAreaInsets();
@@ -64,7 +92,7 @@ const DiscussionsView = ({ navigation, route }) => {
if (result.success) {
if (isSearching) {
setSearch(result.messages);
- setTotal(result.total);
+ setSearchTotal(result.total);
} else {
setDiscussions(result.messages);
setTotal(result.total);
@@ -77,7 +105,7 @@ const DiscussionsView = ({ navigation, route }) => {
}
};
- const onSearchChangeText = debounce(async text => {
+ const onSearchChangeText = debounce(async (text: string) => {
setIsSearching(true);
await load(text);
}, 300);
@@ -119,25 +147,24 @@ const DiscussionsView = ({ navigation, route }) => {
const options = {
headerLeft: () => (
- navigation.pop()} tintColor={themes[theme].headerTintColor} />
+ navigation.pop()} tintColor={themes[theme!].headerTintColor} />
),
headerTitleAlign: 'center',
headerTitle: I18n.t('Discussions'),
headerTitleContainerStyle: {
left: null,
right: null
- }
+ },
+ headerRight: () => (
+
+
+
+ )
};
if (isMasterDetail) {
options.headerLeft = () => ;
}
-
- options.headerRight = () => (
-
-
-
- );
return options;
};
@@ -151,7 +178,7 @@ const DiscussionsView = ({ navigation, route }) => {
}, [navigation, isSearching]);
const onDiscussionPress = debounce(
- item => {
+ (item: any) => {
navigation.push('RoomView', {
rid: item.drid,
prid: item.rid,
@@ -163,20 +190,19 @@ const DiscussionsView = ({ navigation, route }) => {
true
);
- const renderItem = ({ item }) => (
- (
+
);
+
if (!discussions?.length) {
return ;
}
@@ -187,14 +213,15 @@ const DiscussionsView = ({ navigation, route }) => {
item.msg}
- style={{ backgroundColor: themes[theme].backgroundColor }}
+ keyExtractor={(item: any) => item.msg}
+ style={{ backgroundColor: themes[theme!].backgroundColor }}
+ contentContainerStyle={styles.contentContainer}
onEndReachedThreshold={0.5}
maxToRenderPerBatch={5}
windowSize={10}
initialNumToRender={7}
removeClippedSubviews={isIOS}
- onEndReached={() => total > API_FETCH_COUNT ?? load()}
+ onEndReached={() => (isSearching ? searchTotal > API_FETCH_COUNT ?? load() : total > API_FETCH_COUNT ?? load())}
ItemSeparatorComponent={List.Separator}
ListFooterComponent={loading ? : null}
scrollIndicatorInsets={{ right: 1 }}
@@ -203,12 +230,4 @@ const DiscussionsView = ({ navigation, route }) => {
);
};
-DiscussionsView.propTypes = {
- navigation: PropTypes.object,
- route: PropTypes.object,
- item: PropTypes.shape({
- msg: PropTypes.string
- })
-};
-
export default DiscussionsView;
diff --git a/app/views/DiscussionsView/styles.ts b/app/views/DiscussionsView/styles.ts
new file mode 100644
index 00000000..c6478a8b
--- /dev/null
+++ b/app/views/DiscussionsView/styles.ts
@@ -0,0 +1,7 @@
+import { StyleSheet } from 'react-native';
+
+export default StyleSheet.create({
+ contentContainer: {
+ marginBottom: 30
+ }
+});
diff --git a/app/views/ThreadMessagesView/Item.js b/app/views/ThreadMessagesView/Item.js
index 1caef2c2..f10abe27 100644
--- a/app/views/ThreadMessagesView/Item.js
+++ b/app/views/ThreadMessagesView/Item.js
@@ -56,7 +56,7 @@ const styles = StyleSheet.create({
}
});
-const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, toggleFollowThread }) => {
+const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, toggleFollowThread, thread }) => {
const username = (useRealName && item?.u?.name) || item?.u?.username;
let time;
if (item?.ts) {
@@ -66,19 +66,10 @@ const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, to
return (
onPress(item)}
- testID={`thread-messages-view-${item.msg}`}
+ testID={thread ? `thread-messages-view-${item.msg}` : `discussions-view-${item.msg}`}
style={{ backgroundColor: themes[theme].backgroundColor }}>
-
+
@@ -98,7 +89,13 @@ const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, to
/>
{badgeColor ? : null}
-
+
@@ -113,7 +110,8 @@ Item.propTypes = {
user: PropTypes.object,
badgeColor: PropTypes.string,
onPress: PropTypes.func,
- toggleFollowThread: PropTypes.func
+ toggleFollowThread: PropTypes.func,
+ thread: PropTypes.bool
};
export default withTheme(Item);
diff --git a/app/views/ThreadMessagesView/index.js b/app/views/ThreadMessagesView/index.js
index 99605899..5951ba8b 100644
--- a/app/views/ThreadMessagesView/index.js
+++ b/app/views/ThreadMessagesView/index.js
@@ -106,7 +106,14 @@ class ThreadMessagesView extends React.Component {
),
- headerTitle: () => ,
+ headerTitle: () => (
+
+ ),
headerTitleContainerStyle: {
left: headerTitlePosition.left,
right: headerTitlePosition.right
@@ -417,6 +424,7 @@ class ThreadMessagesView extends React.Component {
useRealName,
badgeColor
}}
+ thread
onPress={this.onThreadPress}
toggleFollowThread={this.toggleFollowThread}
/>