Merge branch 'develop' into update.enable-multiline-android-tablets

This commit is contained in:
Gerzon Z 2022-03-28 11:28:26 -04:00 committed by GitHub
commit ac61087940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 296 additions and 277 deletions

View File

@ -5,15 +5,15 @@ import { themes } from '../constants/colors';
import sharedStyles from '../views/Styles';
import scrollPersistTaps from '../utils/scrollPersistTaps';
import KeyboardView from '../presentation/KeyboardView';
import { useTheme } from '../theme';
import StatusBar from './StatusBar';
import AppVersion from './AppVersion';
import { isTablet } from '../utils/deviceInfo';
import SafeAreaView from './SafeAreaView';
interface IFormContainer extends ScrollViewProps {
theme: string;
testID: string;
children: React.ReactNode;
children: React.ReactElement | React.ReactElement[] | null;
}
const styles = StyleSheet.create({
@ -22,27 +22,31 @@ const styles = StyleSheet.create({
}
});
export const FormContainerInner = ({ children }: { children: React.ReactNode }): JSX.Element => (
export const FormContainerInner = ({ children }: { children: (React.ReactElement | null)[] }) => (
<View style={[sharedStyles.container, isTablet && sharedStyles.tabletScreenContent]}>{children}</View>
);
const FormContainer = ({ children, theme, testID, ...props }: IFormContainer): JSX.Element => (
<KeyboardView
style={{ backgroundColor: themes[theme].backgroundColor }}
contentContainerStyle={sharedStyles.container}
keyboardVerticalOffset={128}>
<StatusBar />
<ScrollView
style={sharedStyles.container}
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}
{...scrollPersistTaps}
{...props}>
<SafeAreaView testID={testID} style={{ backgroundColor: themes[theme].backgroundColor }}>
{children}
<AppVersion theme={theme} />
</SafeAreaView>
</ScrollView>
</KeyboardView>
);
const FormContainer = ({ children, testID, ...props }: IFormContainer) => {
const { theme } = useTheme();
return (
<KeyboardView
style={{ backgroundColor: themes[theme].backgroundColor }}
contentContainerStyle={sharedStyles.container}
keyboardVerticalOffset={128}>
<StatusBar />
<ScrollView
style={sharedStyles.container}
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}
{...scrollPersistTaps}
{...props}>
<SafeAreaView testID={testID} style={{ backgroundColor: themes[theme].backgroundColor }}>
{children}
<AppVersion theme={theme} />
</SafeAreaView>
</ScrollView>
</KeyboardView>
);
};
export default FormContainer;

View File

@ -11,7 +11,7 @@ const styles = StyleSheet.create({
});
interface IListContainer {
children: React.ReactNode;
children: (React.ReactElement | null)[] | React.ReactElement | null;
testID?: string;
}
const ListContainer = React.memo(({ children, ...props }: IListContainer) => (

View File

@ -25,6 +25,7 @@ interface IListHeader {
const ListHeader = React.memo(({ title, translateTitle = true }: IListHeader) => {
const { theme } = useTheme();
return (
<View style={styles.container}>
<Text style={[styles.title, { color: themes[theme].infoText }]} numberOfLines={1}>

View File

@ -3,11 +3,10 @@ import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
import { withTheme } from '../../theme';
import { useTheme } from '../../theme';
import { ICON_SIZE } from './constants';
interface IListIcon {
theme?: string;
name: string;
color?: string;
style?: StyleProp<ViewStyle>;
@ -21,12 +20,16 @@ const styles = StyleSheet.create({
}
});
const ListIcon = React.memo(({ theme, name, color, style, testID }: IListIcon) => (
<View style={[styles.icon, style]}>
<CustomIcon name={name} color={color ?? themes[theme!].auxiliaryText} size={ICON_SIZE} testID={testID} />
</View>
));
const ListIcon = React.memo(({ name, color, style, testID }: IListIcon) => {
const { theme } = useTheme();
return (
<View style={[styles.icon, style]}>
<CustomIcon name={name} color={color ?? themes[theme].auxiliaryText} size={ICON_SIZE} testID={testID} />
</View>
);
});
ListIcon.displayName = 'List.Icon';
export default withTheme(ListIcon);
export default ListIcon;

View File

@ -4,11 +4,11 @@ import { I18nManager, StyleSheet, Text, View } from 'react-native';
import Touch from '../../utils/touch';
import { themes } from '../../constants/colors';
import sharedStyles from '../../views/Styles';
import { withTheme } from '../../theme';
import { useTheme } from '../../theme';
import I18n from '../../i18n';
import { Icon } from '.';
import { BASE_HEIGHT, ICON_SIZE, PADDING_HORIZONTAL } from './constants';
import { withDimensions } from '../../dimensions';
import { useDimensions } from '../../dimensions';
import { CustomIcon } from '../../lib/Icons';
const styles = StyleSheet.create({
@ -59,13 +59,12 @@ interface IListItemContent {
left?: () => JSX.Element | null;
right?: () => JSX.Element | null;
disabled?: boolean;
theme: string;
testID?: string;
theme?: string;
color?: string;
translateTitle?: boolean;
translateSubtitle?: boolean;
showActionIndicator?: boolean;
fontScale?: number;
alert?: boolean;
}
@ -78,78 +77,85 @@ const Content = React.memo(
left,
right,
color,
theme,
fontScale,
alert,
translateTitle = true,
translateSubtitle = true,
showActionIndicator = false
}: IListItemContent) => (
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale! }]} testID={testID}>
{left ? <View style={styles.leftContainer}>{left()}</View> : null}
<View style={styles.textContainer}>
<View style={styles.textAlertContainer}>
<Text style={[styles.title, { color: color || themes[theme!].titleText }]} numberOfLines={1}>
{translateTitle ? I18n.t(title) : title}
</Text>
{alert ? (
<CustomIcon style={[styles.alertIcon, { color: themes[theme!].dangerColor }]} size={ICON_SIZE} name='info' />
showActionIndicator = false,
theme
}: IListItemContent) => {
const { fontScale } = useDimensions();
return (
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale }]} testID={testID}>
{left ? <View style={styles.leftContainer}>{left()}</View> : null}
<View style={styles.textContainer}>
<View style={styles.textAlertContainer}>
<Text style={[styles.title, { color: color || themes[theme].titleText }]} numberOfLines={1}>
{translateTitle ? I18n.t(title) : title}
</Text>
{alert ? (
<CustomIcon style={[styles.alertIcon, { color: themes[theme].dangerColor }]} size={ICON_SIZE} name='info' />
) : null}
</View>
{subtitle ? (
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>
{translateSubtitle ? I18n.t(subtitle) : subtitle}
</Text>
) : null}
</View>
{subtitle ? (
<Text style={[styles.subtitle, { color: themes[theme!].auxiliaryText }]} numberOfLines={1}>
{translateSubtitle ? I18n.t(subtitle) : subtitle}
</Text>
{right || showActionIndicator ? (
<View style={styles.rightContainer}>
{right ? right() : null}
{showActionIndicator ? <Icon name='chevron-right' style={styles.actionIndicator} /> : null}
</View>
) : null}
</View>
{right || showActionIndicator ? (
<View style={styles.rightContainer}>
{right ? right() : null}
{showActionIndicator ? <Icon name='chevron-right' style={styles.actionIndicator} /> : null}
</View>
) : null}
</View>
)
);
}
);
interface IListButtonPress {
onPress?: Function;
interface IListButtonPress extends IListItemButton {
onPress: Function;
}
interface IListItemButton extends IListButtonPress {
interface IListItemButton {
title?: string;
disabled?: boolean;
theme?: string;
theme: string;
backgroundColor?: string;
underlayColor?: string;
}
const Button = React.memo<IListItemButton>(({ onPress, backgroundColor, underlayColor, ...props }: IListItemButton) => (
const Button = React.memo(({ onPress, backgroundColor, underlayColor, ...props }: IListButtonPress) => (
<Touch
onPress={() => onPress!(props.title)}
style={{ backgroundColor: backgroundColor || themes[props.theme!].backgroundColor }}
onPress={() => onPress(props.title)}
style={{ backgroundColor: backgroundColor || themes[props.theme].backgroundColor }}
underlayColor={underlayColor}
enabled={!props.disabled}
theme={props.theme!}>
theme={props.theme}>
<Content {...props} />
</Touch>
));
interface IListItem extends IListItemContent, IListItemButton {
interface IListItem extends Omit<IListItemContent, 'theme'>, Omit<IListItemButton, 'theme'> {
backgroundColor?: string;
onPress?: Function;
}
const ListItem = React.memo<IListItem>(({ ...props }: IListItem) => {
const ListItem = React.memo(({ ...props }: IListItem) => {
const { theme } = useTheme();
if (props.onPress) {
return <Button {...props} />;
const { onPress } = props;
return <Button {...props} theme={theme} onPress={onPress} />;
}
return (
<View style={{ backgroundColor: props.backgroundColor || themes[props.theme!].backgroundColor }}>
<Content {...props} />
<View style={{ backgroundColor: props.backgroundColor || themes[theme].backgroundColor }}>
<Content {...props} theme={theme} />
</View>
);
});
ListItem.displayName = 'List.Item';
export default withTheme(withDimensions(ListItem));
export default ListItem;

View File

@ -1,7 +1,6 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { withTheme } from '../../theme';
import { Header } from '.';
const styles = StyleSheet.create({
@ -11,7 +10,7 @@ const styles = StyleSheet.create({
});
interface IListSection {
children: React.ReactNode;
children: (React.ReactElement | null)[] | React.ReactElement | null;
title?: string;
translateTitle?: boolean;
}
@ -25,4 +24,4 @@ const ListSection = React.memo(({ children, title, translateTitle }: IListSectio
ListSection.displayName = 'List.Section';
export default withTheme(ListSection);
export default ListSection;

View File

@ -2,7 +2,7 @@ import React from 'react';
import { StyleSheet, View, ViewStyle } from 'react-native';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import { useTheme } from '../../theme';
const styles = StyleSheet.create({
separator: {
@ -12,13 +12,14 @@ const styles = StyleSheet.create({
interface IListSeparator {
style?: ViewStyle;
theme?: string;
}
const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
<View style={[styles.separator, style, { backgroundColor: themes[theme!].separatorColor }]} />
));
const ListSeparator = React.memo(({ style }: IListSeparator) => {
const { theme } = useTheme();
return <View style={[styles.separator, style, { backgroundColor: themes[theme].separatorColor }]} />;
});
ListSeparator.displayName = 'List.Separator';
export default withTheme(ListSeparator);
export default ListSeparator;

View File

@ -7,6 +7,7 @@ import { themes } from '../../constants/colors';
import { MarkdownPreview } from '../markdown';
import RoomTypeIcon from '../RoomTypeIcon';
import { withTheme } from '../../theme';
import { TUserStatus } from '../../definitions';
const HIT_SLOP = {
top: 5,
@ -67,7 +68,7 @@ interface IRoomHeader {
prid: string;
tmid: string;
teamMain: boolean;
status: string;
status: TUserStatus;
theme?: string;
usersTyping: [];
isGroupChat: boolean;

View File

@ -2,7 +2,7 @@ import { dequal } from 'dequal';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { IApplicationState } from '../../definitions';
import { IApplicationState, TUserStatus } from '../../definitions';
import { withDimensions } from '../../dimensions';
import I18n from '../../i18n';
import RoomHeader from './RoomHeader';
@ -15,7 +15,7 @@ interface IRoomHeaderContainerProps {
tmid: string;
teamMain: boolean;
usersTyping: [];
status: string;
status: TUserStatus;
statusText: string;
connecting: boolean;
connected: boolean;
@ -140,7 +140,7 @@ const mapStateToProps = (state: IApplicationState, ownProps: any) => {
connecting: state.meteor.connecting || state.server.loading,
connected: state.meteor.connected,
usersTyping: state.usersTyping,
status,
status: status as TUserStatus,
statusText
};
};

View File

@ -5,6 +5,7 @@ import { CustomIcon } from '../lib/Icons';
import { STATUS_COLORS, themes } from '../constants/colors';
import Status from './Status/Status';
import { withTheme } from '../theme';
import { TUserStatus } from '../definitions';
const styles = StyleSheet.create({
icon: {
@ -17,7 +18,7 @@ interface IRoomTypeIcon {
type: string;
isGroupChat?: boolean;
teamMain?: boolean;
status?: string;
status?: TUserStatus;
size?: number;
style?: ViewStyle;
}
@ -31,9 +32,10 @@ const RoomTypeIcon = React.memo(({ type, isGroupChat, status, style, theme, team
const iconStyle = [styles.icon, { color }, style];
if (type === 'd' && !isGroupChat) {
return (
<Status style={[iconStyle, { color: STATUS_COLORS[status!] ?? STATUS_COLORS.offline }]} size={size} status={status!} />
);
if (!status) {
status = 'offline';
}
return <Status style={[iconStyle, { color: STATUS_COLORS[status] }]} size={size} status={status} />;
}
// TODO: move this to a separate function

View File

@ -3,15 +3,9 @@ import { StyleProp, TextStyle } from 'react-native';
import { CustomIcon } from '../../lib/Icons';
import { STATUS_COLORS } from '../../constants/colors';
import { IStatus } from './definition';
interface IStatus {
status: string;
size: number;
style?: StyleProp<TextStyle>;
testID?: string;
}
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: Omit<IStatus, 'id'>) => {
const name = `status-${status}`;
const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';

View File

@ -0,0 +1,9 @@
import { TextProps } from 'react-native';
import { TUserStatus } from '../../definitions';
export interface IStatus extends TextProps {
id: string;
size: number;
status: TUserStatus;
}

View File

@ -1,20 +1,15 @@
import React, { memo } from 'react';
import { connect } from 'react-redux';
import React from 'react';
import { useSelector } from 'react-redux';
import { IApplicationState, TUserStatus } from '../../definitions';
import Status from './Status';
import { IStatus } from './definition';
interface IStatusContainer {
style: any;
size: number;
status: string;
}
const StatusContainer = ({ id, style, size = 32, ...props }: Omit<IStatus, 'status'>): React.ReactElement => {
const status = useSelector((state: IApplicationState) =>
state.meteor.connected ? state.activeUsers[id] && state.activeUsers[id].status : 'loading'
) as TUserStatus;
return <Status size={size} style={style} status={status} {...props} />;
};
const StatusContainer = memo(({ style, size = 32, status }: IStatusContainer) => (
<Status size={size} style={style} status={status} />
));
const mapStateToProps = (state: any, ownProps: any) => ({
status: state.meteor.connected ? state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status : 'loading'
});
export default connect(mapStateToProps)(StatusContainer);
export default StatusContainer;

View File

@ -1,18 +1,19 @@
import React from 'react';
import { Text } from 'react-native';
import { StyleProp, Text, TextStyle } from 'react-native';
import { useTheme } from '../../theme';
import { themes } from '../../constants/colors';
import styles from './styles';
import { events, logEvent } from '../../utils/log';
import { IUserMention } from './interfaces';
interface IAtMention {
mention: string;
username?: string;
navToRoomInfo?: Function;
style?: any;
style?: StyleProp<TextStyle>[];
useRealName?: boolean;
mentions: any;
mentions?: IUserMention[];
}
const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, style = [], useRealName }: IAtMention) => {
@ -23,7 +24,7 @@ const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, styl
style={[
styles.mention,
{
color: themes[theme!].mentionGroupColor
color: themes[theme].mentionGroupColor
},
...style
]}>
@ -35,11 +36,11 @@ const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, styl
let mentionStyle = {};
if (mention === username) {
mentionStyle = {
color: themes[theme!].mentionMeColor
color: themes[theme].mentionMeColor
};
} else {
mentionStyle = {
color: themes[theme!].mentionOtherColor
color: themes[theme].mentionOtherColor
};
}
@ -64,7 +65,7 @@ const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, styl
);
}
return <Text style={[styles.text, { color: themes[theme!].bodyText }, ...style]}>{`@${mention}`}</Text>;
return <Text style={[styles.text, { color: themes[theme].bodyText }, ...style]}>{`@${mention}`}</Text>;
});
export default AtMention;

View File

@ -5,7 +5,7 @@ import { themes } from '../../constants/colors';
import styles from './styles';
interface IBlockQuote {
children: JSX.Element;
children: React.ReactElement | null;
theme: string;
}

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Text, TextStyle, StyleProp } from 'react-native';
import { StyleProp, Text, TextStyle } from 'react-native';
import { themes } from '../../constants/colors';
import { useTheme } from '../../theme';
@ -33,7 +33,7 @@ const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [] }: IH
style={[
styles.mention,
{
color: themes[theme!].mentionOtherColor
color: themes[theme].mentionOtherColor
},
...style
]}
@ -42,7 +42,7 @@ const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [] }: IH
</Text>
);
}
return <Text style={[styles.text, { color: themes[theme!].bodyText }, ...style]}>{`#${hashtag}`}</Text>;
return <Text style={[styles.text, { color: themes[theme].bodyText }, ...style]}>{`#${hashtag}`}</Text>;
});
export default Hashtag;

View File

@ -10,7 +10,7 @@ import openLink from '../../utils/openLink';
import { TOnLinkPress } from './interfaces';
interface ILink {
children: JSX.Element;
children: React.ReactElement | null;
link: string;
theme: string;
onLinkPress?: TOnLinkPress;

View File

@ -1,7 +1,7 @@
import React from 'react';
interface IList {
children: JSX.Element;
children: React.ReactElement[] | null;
ordered: boolean;
start: number;
tight: boolean;
@ -11,9 +11,8 @@ interface IList {
const List = React.memo(({ children, ordered, tight, start = 1, numberOfLines = 0 }: IList) => {
let bulletWidth = 15;
if (ordered) {
// @ts-ignore
const lastNumber = start + children.length - 1;
if (ordered && children) {
const lastNumber = start + children?.length - 1;
bulletWidth = 9 * lastNumber.toString().length + 7;
}

View File

@ -18,7 +18,7 @@ const style = StyleSheet.create({
});
interface IListItem {
children: JSX.Element;
children: React.ReactElement | null;
bulletWidth: number;
level: number;
ordered: boolean;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { StyleProp, Text, TextStyle } from 'react-native';
import { Text, TextStyle } from 'react-native';
import removeMarkdown from 'remove-markdown';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
@ -13,10 +13,10 @@ interface IMarkdownPreview {
msg?: string;
numberOfLines?: number;
testID?: string;
style?: StyleProp<TextStyle>[];
style?: TextStyle[];
}
const MarkdownPreview = ({ msg, numberOfLines = 1, testID, style = [] }: IMarkdownPreview): React.ReactElement | null => {
const MarkdownPreview = ({ msg, numberOfLines = 1, testID, style = [] }: IMarkdownPreview) => {
if (!msg) {
return null;
}

View File

@ -8,7 +8,7 @@ import I18n from '../../i18n';
import { themes } from '../../constants/colors';
interface ITable {
children: JSX.Element;
children: React.ReactElement | null;
numColumns: number;
theme: string;
}

View File

@ -6,7 +6,7 @@ import styles from './styles';
interface ITableCell {
align: '' | 'left' | 'center' | 'right';
children: JSX.Element;
children: React.ReactElement | null;
isLastCell: boolean;
theme: string;
}

View File

@ -5,7 +5,7 @@ import { themes } from '../../constants/colors';
import styles from './styles';
interface ITableRow {
children: JSX.Element;
children: React.ReactElement | null;
isLastRow: boolean;
theme: string;
}
@ -16,7 +16,7 @@ const TableRow = React.memo(({ isLastRow, children: _children, theme }: ITableRo
rowStyle.push(styles.rowBottomBorder);
}
const children: any = React.Children.toArray(_children);
const children = React.Children.toArray(_children) as React.ReactElement[];
children[children.length - 1] = React.cloneElement(children[children.length - 1], {
isLastCell: true
});

View File

@ -2,6 +2,7 @@ export interface IUserMention {
_id: string;
username: string;
name?: string;
type?: string;
}
export interface IUserChannel {

View File

@ -14,7 +14,7 @@ const styles = StyleSheet.create({
}
});
const BigEmoji = ({ value }: IBigEmojiProps): JSX.Element => (
const BigEmoji = ({ value }: IBigEmojiProps) => (
<View style={styles.container}>
{value.map(block => (
<Emoji value={block.value} isBigEmoji />

View File

@ -18,7 +18,7 @@ const styles = StyleSheet.create({
}
});
const Bold = ({ value }: IBoldProps): JSX.Element => (
const Bold = ({ value }: IBoldProps) => (
<Text style={styles.text}>
{value.map(block => {
switch (block.type) {

View File

@ -11,7 +11,7 @@ interface ICodeProps {
value: CodeProps['value'];
}
const Code = ({ value }: ICodeProps): JSX.Element => {
const Code = ({ value }: ICodeProps) => {
const { theme } = useTheme();
return (
@ -19,9 +19,9 @@ const Code = ({ value }: ICodeProps): JSX.Element => {
style={[
styles.codeBlock,
{
color: themes[theme!].bodyText,
backgroundColor: themes[theme!].bannerBackground,
borderColor: themes[theme!].borderColor
color: themes[theme].bodyText,
backgroundColor: themes[theme].bannerBackground,
borderColor: themes[theme].borderColor
}
]}>
{value.map(block => {

View File

@ -6,7 +6,7 @@ interface ICodeLineProps {
value: CodeLineProps['value'];
}
const CodeLine = ({ value }: ICodeLineProps): JSX.Element | null => {
const CodeLine = ({ value }: ICodeLineProps) => {
if (value.type !== 'PLAIN_TEXT') {
return null;
}

View File

@ -14,7 +14,7 @@ interface IEmojiProps {
isBigEmoji?: boolean;
}
const Emoji = ({ value, isBigEmoji }: IEmojiProps): JSX.Element => {
const Emoji = ({ value, isBigEmoji }: IEmojiProps) => {
const { theme } = useTheme();
const { baseUrl, getCustomEmoji } = useContext(MarkdownContext);
const emojiUnicode = shortnameToUnicode(`:${value.value}:`);
@ -23,7 +23,7 @@ const Emoji = ({ value, isBigEmoji }: IEmojiProps): JSX.Element => {
if (emoji) {
return <CustomEmoji baseUrl={baseUrl} style={[isBigEmoji ? styles.customEmojiBig : styles.customEmoji]} emoji={emoji} />;
}
return <Text style={[{ color: themes[theme!].bodyText }, isBigEmoji ? styles.textBig : styles.text]}>{emojiUnicode}</Text>;
return <Text style={[{ color: themes[theme].bodyText }, isBigEmoji ? styles.textBig : styles.text]}>{emojiUnicode}</Text>;
};
export default Emoji;

View File

@ -11,12 +11,12 @@ interface IHeadingProps {
level: HeadingProps['level'];
}
const Heading = ({ value, level }: IHeadingProps): JSX.Element => {
const Heading = ({ value, level }: IHeadingProps) => {
const { theme } = useTheme();
const textStyle = styles[`heading${level}`];
return (
<Text style={[textStyle, { color: themes[theme!].bodyText }]}>
<Text style={[textStyle, { color: themes[theme].bodyText }]}>
{value.map(block => {
switch (block.type) {
case 'PLAIN_TEXT':

View File

@ -31,11 +31,11 @@ const MessageImage = ({ img, theme }: TMessageImage) => (
/>
);
const Image = ({ value }: IImageProps): JSX.Element => {
const Image = ({ value }: IImageProps) => {
const { theme } = useTheme();
const { src } = value;
return <MessageImage img={src.value} theme={theme!} />;
return <MessageImage img={src.value} theme={theme} />;
};
export default Image;

View File

@ -19,7 +19,7 @@ interface IParagraphProps {
value: ParagraphProps['value'];
}
const Inline = ({ value }: IParagraphProps): JSX.Element => {
const Inline = ({ value }: IParagraphProps) => {
const { useRealName, username, navToRoomInfo, mentions, channels } = useContext(MarkdownContext);
return (
<Text style={styles.inline}>

View File

@ -10,7 +10,7 @@ interface IInlineCodeProps {
value: InlineCodeProps['value'];
}
const InlineCode = ({ value }: IInlineCodeProps): JSX.Element => {
const InlineCode = ({ value }: IInlineCodeProps) => {
const { theme } = useTheme();
return (
@ -18,9 +18,9 @@ const InlineCode = ({ value }: IInlineCodeProps): JSX.Element => {
style={[
styles.codeInline,
{
color: themes[theme!].bodyText,
backgroundColor: themes[theme!].bannerBackground,
borderColor: themes[theme!].borderColor
color: themes[theme].bodyText,
backgroundColor: themes[theme].bannerBackground,
borderColor: themes[theme].borderColor
}
]}>
{(block => {

View File

@ -17,7 +17,7 @@ const styles = StyleSheet.create({
}
});
const Italic = ({ value }: IItalicProps): JSX.Element => (
const Italic = ({ value }: IItalicProps) => (
<Text style={styles.text}>
{value.map(block => {
switch (block.type) {

View File

@ -18,7 +18,7 @@ interface ILinkProps {
value: LinkProps['value'];
}
const Link = ({ value }: ILinkProps): JSX.Element => {
const Link = ({ value }: ILinkProps) => {
const { theme } = useTheme();
const { onLinkPress } = useContext(MarkdownContext);
const { src, label } = value;
@ -38,7 +38,7 @@ const Link = ({ value }: ILinkProps): JSX.Element => {
};
return (
<Text onPress={handlePress} onLongPress={onLongPress} style={[styles.link, { color: themes[theme!].actionTintColor }]}>
<Text onPress={handlePress} onLongPress={onLongPress} style={[styles.link, { color: themes[theme].actionTintColor }]}>
{(block => {
switch (block.type) {
case 'PLAIN_TEXT':

View File

@ -11,13 +11,13 @@ interface IOrderedListProps {
value: OrderedListProps['value'];
}
const OrderedList = ({ value }: IOrderedListProps): JSX.Element => {
const OrderedList = ({ value }: IOrderedListProps) => {
const { theme } = useTheme();
return (
<View>
{value.map((item, index) => (
<View style={styles.row}>
<Text style={[styles.text, { color: themes[theme!].bodyText }]}>{index + 1}. </Text>
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{index + 1}. </Text>
<Inline value={item.value} />
</View>
))}

View File

@ -11,10 +11,10 @@ interface IParagraphProps {
value: ParagraphProps['value'];
}
const Paragraph = ({ value }: IParagraphProps): JSX.Element => {
const Paragraph = ({ value }: IParagraphProps) => {
const { theme } = useTheme();
return (
<Text style={[styles.text, { color: themes[theme!].bodyText }]}>
<Text style={[styles.text, { color: themes[theme].bodyText }]}>
<Inline value={value} />
</Text>
);

View File

@ -10,10 +10,10 @@ interface IPlainProps {
value: PlainProps['value'];
}
const Plain = ({ value }: IPlainProps): JSX.Element => {
const Plain = ({ value }: IPlainProps) => {
const { theme } = useTheme();
return (
<Text accessibilityLabel={value} style={[styles.plainText, { color: themes[theme!].bodyText }]}>
<Text accessibilityLabel={value} style={[styles.plainText, { color: themes[theme].bodyText }]}>
{value}
</Text>
);

View File

@ -11,11 +11,11 @@ interface IQuoteProps {
value: QuoteProps['value'];
}
const Quote = ({ value }: IQuoteProps): JSX.Element => {
const Quote = ({ value }: IQuoteProps) => {
const { theme } = useTheme();
return (
<View style={styles.container}>
<View style={[styles.quote, { backgroundColor: themes[theme!].borderColor }]} />
<View style={[styles.quote, { backgroundColor: themes[theme].borderColor }]} />
<View style={styles.childContainer}>
{value.map(item => (
<Paragraph value={item.value} />

View File

@ -17,7 +17,7 @@ const styles = StyleSheet.create({
}
});
const Strike = ({ value }: IStrikeProps): JSX.Element => (
const Strike = ({ value }: IStrikeProps) => (
<Text style={styles.text}>
{value.map(block => {
switch (block.type) {

View File

@ -11,13 +11,13 @@ interface ITasksProps {
value: TasksProps['value'];
}
const TaskList = ({ value = [] }: ITasksProps): JSX.Element => {
const TaskList = ({ value = [] }: ITasksProps) => {
const { theme } = useTheme();
return (
<View>
{value.map(item => (
<View style={styles.row}>
<Text style={[styles.text, { color: themes[theme!].bodyText }]}>{item.status ? '- [x] ' : '- [ ] '}</Text>
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{item.status ? '- [x] ' : '- [ ] '}</Text>
<Inline value={item.value} />
</View>
))}

View File

@ -11,13 +11,13 @@ interface IUnorderedListProps {
value: UnorderedListProps['value'];
}
const UnorderedList = ({ value }: IUnorderedListProps): JSX.Element => {
const UnorderedList = ({ value }: IUnorderedListProps) => {
const { theme } = useTheme();
return (
<View>
{value.map(item => (
<View style={styles.row}>
<Text style={[styles.text, { color: themes[theme!].bodyText }]}>- </Text>
<Text style={[styles.text, { color: themes[theme].bodyText }]}>- </Text>
<Inline value={item.value} />
</View>
))}

View File

@ -35,7 +35,7 @@ const Body = ({
getCustomEmoji,
baseUrl,
onLinkPress
}: IBodyProps): React.ReactElement | null => {
}: IBodyProps) => {
if (isEmpty(tokens)) {
return null;
}

View File

@ -82,7 +82,7 @@ const Attachments = React.memo(
if (file && file.actions && file.actions.length > 0) {
return <AttachedActions attachment={file} />;
}
if (file.title) {
if (typeof file.collapsed === 'boolean') {
return (
<CollapsibleQuote key={index} index={index} attachment={file} timeFormat={timeFormat} getCustomEmoji={getCustomEmoji} />
);

View File

@ -1,7 +1,7 @@
import Model from '@nozbe/watermelondb/Model';
import { IUserEmail, IUserSettings } from './IUser';
import { UserStatus } from './UserStatus';
import { TUserStatus } from './TUserStatus';
export interface ILoggedUser {
id: string;
@ -9,7 +9,7 @@ export interface ILoggedUser {
username: string;
name: string;
language?: string;
status: UserStatus;
status: TUserStatus;
statusText?: string;
customFields?: {
[key: string]: any;

View File

@ -1,6 +1,6 @@
import Model from '@nozbe/watermelondb/Model';
import { UserStatus } from './UserStatus';
import { TUserStatus } from './TUserStatus';
import { IRocketChatRecord } from './IRocketChatRecord';
import { ILoggedUser } from './ILoggedUser';
@ -25,7 +25,7 @@ export interface IPersonalAccessToken extends ILoginToken {
export interface IUserRegistered {
_id: string;
type: string;
status: UserStatus;
status: TUserStatus;
active: boolean;
name: string;
username: string;
@ -133,14 +133,14 @@ export interface IUser extends IRocketChatRecord, Omit<ILoggedUser, 'username' |
name?: string;
services?: IUserServices;
emails?: IUserEmail[];
status: UserStatus;
status: TUserStatus;
statusConnection?: string;
lastLogin?: Date;
avatarOrigin?: string;
avatarETag?: string;
utcOffset?: number;
language?: string;
statusDefault?: UserStatus;
statusDefault?: TUserStatus;
statusText?: string;
oauth?: {
authorizedClients: string[];

View File

@ -0,0 +1,3 @@
export const STATUSES = ['offline', 'online', 'away', 'busy'] as const;
export type TUserStatus = typeof STATUSES[number];

View File

@ -1,6 +0,0 @@
export enum UserStatus {
ONLINE = 'online',
AWAY = 'away',
OFFLINE = 'offline',
BUSY = 'busy'
}

View File

@ -26,6 +26,7 @@ export * from './ICertificate';
export * from './IUrl';
export * from './ICredentials';
export * from './ISearch';
export * from './TUserStatus';
export interface IBaseScreen<T extends Record<string, object | undefined>, S extends string> {
navigation: StackNavigationProp<T, S>;

View File

@ -8,7 +8,7 @@ export interface IDimensionsContextProps {
width: number;
height: number;
scale?: number;
fontScale?: number;
fontScale: number;
setDimensions?: ({
width,
height,
@ -22,7 +22,9 @@ export interface IDimensionsContextProps {
}) => void;
}
export const DimensionsContext = React.createContext<IDimensionsContextProps>(Dimensions.get('window'));
export const DimensionsContext = React.createContext<IDimensionsContextProps>(
Dimensions.get('window') as IDimensionsContextProps
);
export function withDimensions<T extends object>(Component: React.ComponentType<T> & TNavigationOptions): typeof Component {
const DimensionsComponent = (props: T) => (

View File

@ -73,7 +73,6 @@ export const THEME_PREFERENCES_KEY = 'RC_THEME_PREFERENCES_KEY';
export const CRASH_REPORT_KEY = 'RC_CRASH_REPORT_KEY';
export const ANALYTICS_EVENTS_KEY = 'RC_ANALYTICS_EVENTS_KEY';
export const MIN_ROCKETCHAT_VERSION = '0.70.0';
export const STATUSES = ['offline', 'online', 'away', 'busy'];
const RocketChat = {
TOKEN_KEY,

View File

@ -6,7 +6,6 @@ import { Q } from '@nozbe/watermelondb';
import log from '../../../utils/log';
import { onRolesChanged } from '../../methods/getRoles';
import { UserStatus } from '../../../definitions/UserStatus';
import { setActiveUsers } from '../../../actions/activeUsers';
import protectedFunction from '../../methods/helpers/protectedFunction';
import database from '../../database';
@ -17,8 +16,8 @@ import { store } from '../../auxStore';
import { loginRequest, setLoginServices, setUser } from '../../../actions/login';
import sdk from './sdk';
import I18n from '../../../i18n';
import RocketChat, { MIN_ROCKETCHAT_VERSION, STATUSES } from '../rocketchat';
import { ICredentials, ILoggedUser, IRocketChat } from '../../../definitions';
import RocketChat, { MIN_ROCKETCHAT_VERSION } from '../rocketchat';
import { ICredentials, ILoggedUser, IRocketChat, STATUSES } from '../../../definitions';
import { isIOS } from '../../../utils/deviceInfo';
import { connectRequest, connectSuccess, disconnect as disconnectAction } from '../../../actions/connect';
import { updatePermission } from '../../../actions/permissions';
@ -195,7 +194,7 @@ function connect(
const { user: loggedUser } = store.getState().login;
if (loggedUser && loggedUser.id === id) {
store.dispatch(setUser({ status: STATUSES[status] as UserStatus, statusText }));
store.dispatch(setUser({ status: STATUSES[status], statusText }));
}
} else if (/updateAvatar/.test(eventName)) {
const { username, etag } = ddpMessage.fields.args[0];

View File

@ -900,4 +900,4 @@ export const e2eFetchMyKeys = async () => {
};
}
return result;
};
};

View File

@ -12,6 +12,7 @@ import Touchable from './Touchable';
import Tag from './Tag';
import I18n from '../../i18n';
import { DisplayMode } from '../../constants/constantDisplayMode';
import { TUserStatus } from '../../definitions';
interface IRoomItem {
rid: string;
@ -24,7 +25,7 @@ interface IRoomItem {
avatarSize: number;
testID: string;
width: number;
status: string;
status: TUserStatus;
useRealName: boolean;
theme: string;
isFocused: boolean;

View File

@ -1,10 +1,11 @@
import React from 'react';
import { TUserStatus } from '../../definitions';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
interface ITypeIcon {
type: string;
status: string;
status: TUserStatus;
prid: string;
isGroupChat: boolean;
teamMain: boolean;

View File

@ -5,6 +5,7 @@ import I18n from '../../i18n';
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
import { formatDate } from '../../utils/room';
import RoomItem from './RoomItem';
import { TUserStatus } from '../../definitions';
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
interface IRoomItemContainerProps {
@ -16,7 +17,7 @@ interface IRoomItemContainerProps {
username: string;
avatarSize: number;
width: number;
status: string;
status: TUserStatus;
toggleFav(): void;
toggleRead(): void;
hideChannel(): void;
@ -53,7 +54,7 @@ class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
private roomSubscription: any;
static defaultProps = {
static defaultProps: Partial<IRoomItemContainerProps> = {
avatarSize: 48,
status: 'offline',
getUserPresence: () => {},
@ -233,7 +234,7 @@ const mapStateToProps = (state: any, ownProps: any) => {
}
return {
connected: state.meteor.connected,
status
status: status as TUserStatus
};
};

View File

@ -1,5 +1,4 @@
import { clearActiveUsers, setActiveUsers } from '../actions/activeUsers';
import { UserStatus } from '../definitions/UserStatus';
import { IActiveUsers, initialState } from './activeUsers';
import { mockedStore } from './mockedStore';
@ -9,7 +8,7 @@ describe('test reducer', () => {
expect(state).toEqual(initialState);
});
it('should return modified store after action', () => {
const activeUsers: IActiveUsers = { any: { status: UserStatus.ONLINE, statusText: 'any' } };
const activeUsers: IActiveUsers = { any: { status: 'online', statusText: 'any' } };
mockedStore.dispatch(setActiveUsers(activeUsers));
const state = mockedStore.getState().activeUsers;
expect(state).toEqual({ ...activeUsers });

View File

@ -1,9 +1,8 @@
import { ACTIVE_USERS } from '../actions/actionsTypes';
import { TApplicationActions } from '../definitions';
import { UserStatus } from '../definitions/UserStatus';
import { TApplicationActions, TUserStatus } from '../definitions';
export interface IActiveUser {
status: UserStatus;
status: TUserStatus;
statusText: string;
}

View File

@ -1,3 +1,4 @@
import { TUserStatus } from '../definitions';
import {
clearUser,
loginFailure,
@ -8,7 +9,6 @@ import {
setLoginServices,
setUser
} from '../actions/login';
import { UserStatus } from '../definitions/UserStatus';
import { initialState } from './login';
import { mockedStore } from './mockedStore';
@ -49,7 +49,7 @@ describe('test selectedUsers reducer', () => {
isFromWebView: false,
showMessageInMainThread: false,
enableMessageParserEarlyAdoption: false,
status: UserStatus.ONLINE,
status: 'online' as TUserStatus,
statusText: 'online'
};
mockedStore.dispatch(loginSuccess(user));

View File

@ -1,7 +1,6 @@
import { UserStatus } from '../definitions/UserStatus';
import * as types from '../actions/actionsTypes';
import { TActionsLogin } from '../actions/login';
import { IUser } from '../definitions';
import { IUser, TUserStatus } from '../definitions';
export interface IUserLogin {
id: string;
@ -9,7 +8,7 @@ export interface IUserLogin {
username: string;
name: string;
language?: string;
status: UserStatus;
status: TUserStatus;
statusText: string;
roles: string[];
avatarETag?: string;

View File

@ -6,7 +6,6 @@ import { CompositeNavigationProp } from '@react-navigation/core';
import * as List from '../containers/List';
import StatusBar from '../containers/StatusBar';
import { useTheme } from '../theme';
import * as HeaderButton from '../containers/HeaderButton';
import SafeAreaView from '../containers/SafeAreaView';
import I18n from '../i18n';
@ -41,7 +40,6 @@ const setHeader = ({
const AddChannelTeamView = ({ navigation, route, isMasterDetail }: IAddChannelTeamView) => {
const { teamId, teamChannels } = route.params;
const { theme } = useTheme();
useEffect(() => {
setHeader({ navigation, isMasterDetail });
@ -67,7 +65,6 @@ const AddChannelTeamView = ({ navigation, route, isMasterDetail }: IAddChannelTe
testID='add-channel-team-view-create-channel'
left={() => <List.Icon name='team' />}
right={() => <List.Icon name='chevron-right' />}
theme={theme}
/>
<List.Separator />
<List.Item
@ -76,7 +73,6 @@ const AddChannelTeamView = ({ navigation, route, isMasterDetail }: IAddChannelTe
testID='add-channel-team-view-add-existing'
left={() => <List.Icon name='channel-public' />}
right={() => <List.Icon name='chevron-right' />}
theme={theme}
/>
<List.Separator />
</List.Container>

View File

@ -92,7 +92,7 @@ class ForgotPasswordView extends React.Component<IForgotPasswordViewProps, IForg
const { theme } = this.props;
return (
<FormContainer theme={theme} testID='forgot-password-view'>
<FormContainer testID='forgot-password-view'>
<FormContainerInner>
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, { color: themes[theme].titleText }]}>
{I18n.t('Forgot_password')}

View File

@ -229,7 +229,7 @@ class LoginView extends React.Component<ILoginViewProps, any> {
render() {
const { Accounts_ShowFormLogin, theme, navigation } = this.props;
return (
<FormContainer theme={theme} testID='login-view'>
<FormContainer testID='login-view'>
<FormContainerInner>
<LoginServices separator={Accounts_ShowFormLogin} navigation={navigation} theme={theme} />
{this.renderUserForm()}

View File

@ -321,7 +321,7 @@ class NewServerView extends React.Component<INewServerViewProps, INewServerViewS
const marginTop = previousServer ? 0 : 35;
return (
<FormContainer theme={theme} testID='new-server-view' keyboardShouldPersistTaps='never'>
<FormContainer testID='new-server-view' keyboardShouldPersistTaps='never'>
<FormContainerInner>
<Image
style={[

View File

@ -172,60 +172,64 @@ class RegisterView extends React.Component<IProps, any> {
return null;
}
try {
return Object.keys(this.parsedCustomFields).map((key, index, array) => {
if (this.parsedCustomFields[key].type === 'select') {
const options = this.parsedCustomFields[key].options.map((option: string) => ({ label: option, value: option }));
return (
<RNPickerSelect
key={key}
items={options}
onValueChange={value => {
const newValue: { [key: string]: string | number } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
value={customFields[key]}>
return (
<>
{Object.keys(this.parsedCustomFields).map((key, index, array) => {
if (this.parsedCustomFields[key].type === 'select') {
const options = this.parsedCustomFields[key].options.map((option: string) => ({ label: option, value: option }));
return (
<RNPickerSelect
key={key}
items={options}
onValueChange={value => {
const newValue: { [key: string]: string | number } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
value={customFields[key]}>
<TextInput
inputRef={(e: any) => {
// @ts-ignore
this[key] = e;
}}
placeholder={key}
value={customFields[key]}
testID='register-view-custom-picker'
theme={theme}
/>
</RNPickerSelect>
);
}
return (
<TextInput
inputRef={e => {
// @ts-ignore
this[key] = e;
}}
key={key}
label={key}
placeholder={key}
value={customFields[key]}
testID='register-view-custom-picker'
onChangeText={(value: string) => {
const newValue: { [key: string]: string | number } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
onSubmitEditing={() => {
if (array.length - 1 > index) {
// @ts-ignore
return this[array[index + 1]].focus();
}
this.avatarUrl.focus();
}}
containerStyle={styles.inputContainer}
theme={theme}
/>
</RNPickerSelect>
);
}
return (
<TextInput
inputRef={(e: any) => {
// @ts-ignore
this[key] = e;
}}
key={key}
label={key}
placeholder={key}
value={customFields[key]}
onChangeText={(value: string) => {
const newValue: { [key: string]: string | number } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
onSubmitEditing={() => {
if (array.length - 1 > index) {
// @ts-ignore
return this[array[index + 1]].focus();
}
this.avatarUrl.focus();
}}
containerStyle={styles.inputContainer}
theme={theme}
/>
);
});
);
})}
</>
);
} catch (error) {
return null;
}
@ -235,7 +239,7 @@ class RegisterView extends React.Component<IProps, any> {
const { saving } = this.state;
const { theme, showLoginButton, navigation } = this.props;
return (
<FormContainer theme={theme} testID='register-view'>
<FormContainer testID='register-view'>
<FormContainerInner>
<LoginServices navigation={navigation} theme={theme} separator />
<Text style={[styles.title, sharedStyles.textBold, { color: themes[theme].titleText }]}>{I18n.t('Sign_Up')}</Text>

View File

@ -223,7 +223,7 @@ class ScreenLockConfigView extends React.Component<IScreenLockConfigViewProps, I
return (
<List.Section>
<List.Separator />
{items.map(item => this.renderItem({ item }))}
<>{items.map(item => this.renderItem({ item }))}</>
</List.Section>
);
};

View File

@ -62,7 +62,7 @@ const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmation
}, []);
return (
<FormContainer theme={theme} testID='send-email-confirmation-view'>
<FormContainer testID='send-email-confirmation-view'>
<FormContainerInner>
<TextInput
autoFocus

View File

@ -19,6 +19,7 @@ import Navigation from '../../lib/Navigation';
import SidebarItem from './SidebarItem';
import styles from './styles';
import { DrawerParamList } from '../../stacks/types';
import { TUserStatus } from '../../definitions';
interface ISeparatorProps {
theme: string;
@ -40,7 +41,7 @@ interface ISidebarProps {
Site_Name: string;
user: {
statusText: string;
status: string;
status: TUserStatus;
username: string;
name: string;
roles: string[];

View File

@ -2,7 +2,6 @@ import React from 'react';
import { FlatList, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { UserStatus } from '../definitions/UserStatus';
import { setUser } from '../actions/login';
import * as HeaderButton from '../containers/HeaderButton';
import * as List from '../containers/List';
@ -11,7 +10,7 @@ import SafeAreaView from '../containers/SafeAreaView';
import Status from '../containers/Status/Status';
import TextInput from '../containers/TextInput';
import { LISTENER } from '../containers/Toast';
import { IApplicationState, IBaseScreen, IUser } from '../definitions';
import { IApplicationState, IBaseScreen, IUser, TUserStatus } from '../definitions';
import I18n from '../i18n';
import RocketChat from '../lib/rocketchat';
import { getUserSelector } from '../selectors/login';
@ -20,7 +19,12 @@ import EventEmitter from '../utils/events';
import { showErrorAlert } from '../utils/info';
import log, { events, logEvent } from '../utils/log';
const STATUS = [
interface IStatus {
id: TUserStatus;
name: string;
}
const STATUS: IStatus[] = [
{
id: 'online',
name: 'Online'
@ -135,7 +139,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
value={statusText}
containerStyle={styles.inputContainer}
onChangeText={text => this.setState({ statusText: text })}
left={<Status testID={`status-view-current-${user.status}`} style={styles.inputLeft} status={user.status!} size={24} />}
left={<Status testID={`status-view-current-${user.status}`} style={styles.inputLeft} status={user.status} size={24} />}
inputStyle={styles.inputStyle}
placeholder={I18n.t('What_are_you_doing_right_now')}
testID='status-view-input'
@ -145,7 +149,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
);
};
renderItem = ({ item }: { item: { id: string; name: string } }) => {
renderItem = ({ item }: { item: IStatus }) => {
const { statusText } = this.state;
const { user, dispatch } = this.props;
const { id, name } = item;
@ -159,7 +163,7 @@ class StatusView extends React.Component<IStatusViewProps, IStatusViewState> {
try {
const result = await RocketChat.setUserStatus(item.id, statusText);
if (result.success) {
dispatch(setUser({ status: item.id as UserStatus }));
dispatch(setUser({ status: item.id }));
}
} catch (e: any) {
showErrorAlert(I18n.t(e.data.errorType));

View File

@ -131,11 +131,11 @@ class ThemeView extends React.Component<IThemeViewProps> {
<List.Container>
<List.Section title='Theme'>
<List.Separator />
{themeGroup.map(item => this.renderItem({ item }))}
<>{themeGroup.map(item => this.renderItem({ item }))}</>
</List.Section>
<List.Section title='Dark_level'>
<List.Separator />
{darkGroup.map(item => this.renderItem({ item }))}
<>{darkGroup.map(item => this.renderItem({ item }))}</>
</List.Section>
</List.Container>
</SafeAreaView>

View File

@ -74,7 +74,7 @@ class WorkspaceView extends React.Component<IWorkSpaceProp, any> {
const { theme, Site_Name, Site_Url, Assets_favicon_512, server, showLoginButton } = this.props;
return (
<FormContainer theme={theme} testID='workspace-view'>
<FormContainer testID='workspace-view'>
<FormContainerInner>
<View style={styles.alignItemsCenter}>
<ServerAvatar theme={theme} url={server} image={Assets_favicon_512?.url ?? Assets_favicon_512?.defaultUrl} />

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long