Merge branch 'develop' into chore/migration-ts-redux-encryption
This commit is contained in:
commit
49ac4c1f65
|
@ -3,7 +3,7 @@ import { NavigationContainer } from '@react-navigation/native';
|
|||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { SetUsernameStackParamList, StackParamList } from './navigationTypes';
|
||||
import { SetUsernameStackParamList, StackParamList } from './definitions/navigationTypes';
|
||||
import Navigation from './lib/Navigation';
|
||||
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
||||
import { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME } from './actions/app';
|
||||
|
|
|
@ -6,9 +6,9 @@ import sharedStyles from '../../views/Styles';
|
|||
import { themes } from '../../constants/colors';
|
||||
|
||||
interface IBackgroundContainer {
|
||||
text: string;
|
||||
theme: string;
|
||||
loading: boolean;
|
||||
text?: string;
|
||||
theme?: string;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -35,8 +35,8 @@ const styles = StyleSheet.create({
|
|||
const BackgroundContainer = ({ theme, text, loading }: IBackgroundContainer) => (
|
||||
<View style={styles.container}>
|
||||
<ImageBackground source={{ uri: `message_empty_${theme}` }} style={styles.image} />
|
||||
{text ? <Text style={[styles.text, { color: themes[theme].auxiliaryTintColor }]}>{text}</Text> : null}
|
||||
{loading ? <ActivityIndicator style={styles.text} color={themes[theme].auxiliaryTintColor} /> : null}
|
||||
{text ? <Text style={[styles.text, { color: themes[theme!].auxiliaryTintColor }]}>{text}</Text> : null}
|
||||
{loading ? <ActivityIndicator style={styles.text} color={themes[theme!].auxiliaryTintColor} /> : null}
|
||||
</View>
|
||||
);
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ export const CloseModal = React.memo(
|
|||
export const CancelModal = React.memo(({ onPress, testID }: Partial<IHeaderButtonCommon>) => (
|
||||
<Container left>
|
||||
{isIOS ? (
|
||||
<Item title={I18n.t('Cancel')} onPress={onPress} testID={testID} />
|
||||
<Item title={I18n.t('Cancel')} onPress={onPress!} testID={testID} />
|
||||
) : (
|
||||
<Item iconName='close' onPress={onPress} testID={testID} />
|
||||
<Item iconName='close' onPress={onPress!} testID={testID} />
|
||||
)}
|
||||
</Container>
|
||||
));
|
||||
|
@ -39,19 +39,19 @@ export const CancelModal = React.memo(({ onPress, testID }: Partial<IHeaderButto
|
|||
// Right
|
||||
export const More = React.memo(({ onPress, testID }: Partial<IHeaderButtonCommon>) => (
|
||||
<Container>
|
||||
<Item iconName='kebab' onPress={onPress} testID={testID} />
|
||||
<Item iconName='kebab' onPress={onPress!} testID={testID} />
|
||||
</Container>
|
||||
));
|
||||
|
||||
export const Download = React.memo(({ onPress, testID, ...props }: Partial<IHeaderButtonCommon>) => (
|
||||
<Container>
|
||||
<Item iconName='download' onPress={onPress} testID={testID} {...props} />
|
||||
<Item iconName='download' onPress={onPress!} testID={testID} {...props} />
|
||||
</Container>
|
||||
));
|
||||
|
||||
export const Preferences = React.memo(({ onPress, testID, ...props }: Partial<IHeaderButtonCommon>) => (
|
||||
<Container>
|
||||
<Item iconName='settings' onPress={onPress} testID={testID} {...props} />
|
||||
<Item iconName='settings' onPress={onPress!} testID={testID} {...props} />
|
||||
</Container>
|
||||
));
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ import { themes } from '../../constants/colors';
|
|||
import sharedStyles from '../../views/Styles';
|
||||
|
||||
interface IHeaderButtonItem {
|
||||
title: string;
|
||||
iconName: string;
|
||||
onPress(): void;
|
||||
testID: string;
|
||||
theme: string;
|
||||
badge(): void;
|
||||
title?: string;
|
||||
iconName?: string;
|
||||
onPress: <T>(arg: T) => void;
|
||||
testID?: string;
|
||||
theme?: string;
|
||||
badge?(): void;
|
||||
}
|
||||
|
||||
export const BUTTON_HIT_SLOP = {
|
||||
|
@ -44,9 +44,9 @@ const Item = ({ title, iconName, onPress, testID, theme, badge }: IHeaderButtonI
|
|||
<Touchable onPress={onPress} testID={testID} hitSlop={BUTTON_HIT_SLOP} style={styles.container}>
|
||||
<>
|
||||
{iconName ? (
|
||||
<CustomIcon name={iconName} size={24} color={themes[theme].headerTintColor} />
|
||||
<CustomIcon name={iconName} size={24} color={themes[theme!].headerTintColor} />
|
||||
) : (
|
||||
<Text style={[styles.title, { color: themes[theme].headerTintColor }]}>{title}</Text>
|
||||
<Text style={[styles.title, { color: themes[theme!].headerTintColor }]}>{title}</Text>
|
||||
)}
|
||||
{badge ? badge() : null}
|
||||
</>
|
||||
|
|
|
@ -11,10 +11,10 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IListContainer {
|
||||
children: JSX.Element;
|
||||
children: React.ReactNode;
|
||||
testID?: string;
|
||||
}
|
||||
const ListContainer = React.memo(({ children, ...props }: IListContainer) => (
|
||||
// @ts-ignore
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.container}
|
||||
scrollIndicatorInsets={{ right: 1 }} // https://github.com/facebook/react-native/issues/26610#issuecomment-539843444
|
||||
|
|
|
@ -20,13 +20,13 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface IListHeader {
|
||||
title: string;
|
||||
theme: string;
|
||||
translateTitle: boolean;
|
||||
theme?: string;
|
||||
translateTitle?: boolean;
|
||||
}
|
||||
|
||||
const ListHeader = React.memo(({ title, theme, translateTitle = true }: IListHeader) => (
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.title, { color: themes[theme].infoText }]} numberOfLines={1}>
|
||||
<Text style={[styles.title, { color: themes[theme!].infoText }]} numberOfLines={1}>
|
||||
{translateTitle ? I18n.t(title) : title}
|
||||
</Text>
|
||||
</View>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { CustomIcon } from '../../lib/Icons';
|
||||
|
@ -7,11 +7,11 @@ import { withTheme } from '../../theme';
|
|||
import { ICON_SIZE } from './constants';
|
||||
|
||||
interface IListIcon {
|
||||
theme: string;
|
||||
theme?: string;
|
||||
name: string;
|
||||
color: string;
|
||||
style: object;
|
||||
testID: string;
|
||||
color?: string;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -23,7 +23,7 @@ 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} />
|
||||
<CustomIcon name={name} color={color ?? themes[theme!].auxiliaryText} size={ICON_SIZE} testID={testID} />
|
||||
</View>
|
||||
));
|
||||
|
||||
|
|
|
@ -20,13 +20,13 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface IListHeader {
|
||||
info: string;
|
||||
theme: string;
|
||||
translateInfo: boolean;
|
||||
theme?: string;
|
||||
translateInfo?: boolean;
|
||||
}
|
||||
|
||||
const ListInfo = React.memo(({ info, theme, translateInfo = true }: IListHeader) => (
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.text, { color: themes[theme].infoText }]}>{translateInfo ? I18n.t(info) : info}</Text>
|
||||
<Text style={[styles.text, { color: themes[theme!].infoText }]}>{translateInfo ? I18n.t(info) : info}</Text>
|
||||
</View>
|
||||
));
|
||||
|
||||
|
|
|
@ -56,11 +56,11 @@ const styles = StyleSheet.create({
|
|||
interface IListItemContent {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
left?: Function;
|
||||
right?: Function;
|
||||
left?: () => JSX.Element | null;
|
||||
right?: () => JSX.Element | null;
|
||||
disabled?: boolean;
|
||||
testID?: string;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
color?: string;
|
||||
translateTitle?: boolean;
|
||||
translateSubtitle?: boolean;
|
||||
|
@ -89,15 +89,15 @@ const Content = React.memo(
|
|||
{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}>
|
||||
<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' />
|
||||
<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}>
|
||||
<Text style={[styles.subtitle, { color: themes[theme!].auxiliaryText }]} numberOfLines={1}>
|
||||
{translateSubtitle ? I18n.t(subtitle) : subtitle}
|
||||
</Text>
|
||||
) : null}
|
||||
|
@ -112,38 +112,39 @@ const Content = React.memo(
|
|||
)
|
||||
);
|
||||
|
||||
interface IListItemButton {
|
||||
interface IListButtonPress {
|
||||
onPress?: Function;
|
||||
}
|
||||
|
||||
interface IListItemButton extends IListButtonPress {
|
||||
title?: string;
|
||||
onPress: Function;
|
||||
disabled?: boolean;
|
||||
theme: string;
|
||||
backgroundColor: string;
|
||||
theme?: string;
|
||||
backgroundColor?: string;
|
||||
underlayColor?: string;
|
||||
}
|
||||
|
||||
const Button = React.memo(({ onPress, backgroundColor, underlayColor, ...props }: IListItemButton) => (
|
||||
const Button = React.memo<IListItemButton>(({ onPress, backgroundColor, underlayColor, ...props }: IListItemButton) => (
|
||||
<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 {
|
||||
onPress: Function;
|
||||
theme: string;
|
||||
backgroundColor: string;
|
||||
interface IListItem extends IListItemContent, IListButtonPress {
|
||||
backgroundColor?: string;
|
||||
}
|
||||
|
||||
const ListItem = React.memo(({ ...props }: IListItem) => {
|
||||
const ListItem = React.memo<IListItem>(({ ...props }: IListItem) => {
|
||||
if (props.onPress) {
|
||||
return <Button {...props} />;
|
||||
}
|
||||
return (
|
||||
<View style={{ backgroundColor: props.backgroundColor || themes[props.theme].backgroundColor }}>
|
||||
<View style={{ backgroundColor: props.backgroundColor || themes[props.theme!].backgroundColor }}>
|
||||
<Content {...props} />
|
||||
</View>
|
||||
);
|
||||
|
|
|
@ -11,9 +11,9 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IListSection {
|
||||
children: JSX.Element;
|
||||
title: string;
|
||||
translateTitle: boolean;
|
||||
children: React.ReactNode;
|
||||
title?: string;
|
||||
translateTitle?: boolean;
|
||||
}
|
||||
|
||||
const ListSection = React.memo(({ children, title, translateTitle }: IListSection) => (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { StyleSheet, View, ViewStyle } from 'react-native';
|
||||
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
|
@ -11,12 +11,12 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IListSeparator {
|
||||
style: object;
|
||||
theme: string;
|
||||
style?: ViewStyle;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
|
||||
<View style={[styles.separator, style, { backgroundColor: themes[theme].separatorColor }]} />
|
||||
<View style={[styles.separator, style, { backgroundColor: themes[theme!].separatorColor }]} />
|
||||
));
|
||||
|
||||
ListSeparator.displayName = 'List.Separator';
|
||||
|
|
|
@ -19,7 +19,7 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface ILoadingProps {
|
||||
visible: boolean;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||
|
@ -97,7 +97,7 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
|||
|
||||
const opacityAnimation = opacity.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, themes[theme].backdropOpacity],
|
||||
outputRange: [0, themes[theme!].backdropOpacity],
|
||||
extrapolate: 'clamp'
|
||||
});
|
||||
|
||||
|
@ -109,7 +109,7 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
|||
{
|
||||
// @ts-ignore
|
||||
...StyleSheet.absoluteFill,
|
||||
backgroundColor: themes[theme].backdropColor,
|
||||
backgroundColor: themes[theme!].backdropColor,
|
||||
opacity: opacityAnimation
|
||||
}
|
||||
]}
|
||||
|
|
|
@ -17,7 +17,7 @@ interface IHeader {
|
|||
server: string;
|
||||
message: object;
|
||||
isMasterDetail: boolean;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
interface THeaderItem {
|
||||
|
@ -117,19 +117,19 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
|
|||
const onReaction = ({ emoji }: { emoji: IEmoji }) => handleReaction(emoji, message);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ item }) => <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme} />,
|
||||
({ item }) => <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme!} />,
|
||||
[]
|
||||
);
|
||||
|
||||
const renderFooter = useCallback(() => <HeaderFooter onReaction={onReaction} theme={theme} />, []);
|
||||
const renderFooter = useCallback(() => <HeaderFooter onReaction={onReaction} theme={theme!} />, []);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: themes[theme].focusedBackground }]}>
|
||||
<View style={[styles.container, { backgroundColor: themes[theme!].focusedBackground }]}>
|
||||
<FlatList
|
||||
data={items}
|
||||
renderItem={renderItem}
|
||||
ListFooterComponent={renderFooter}
|
||||
style={{ backgroundColor: themes[theme].focusedBackground }}
|
||||
style={{ backgroundColor: themes[theme!].focusedBackground }}
|
||||
keyExtractor={keyExtractor}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
scrollEnabled={false}
|
||||
|
|
|
@ -18,7 +18,7 @@ import events from '../../utils/log/events';
|
|||
|
||||
interface IMessageActions {
|
||||
room: {
|
||||
rid: string | number;
|
||||
rid: string;
|
||||
autoTranslateLanguage: any;
|
||||
autoTranslate: any;
|
||||
reactWhenReadOnly: any;
|
||||
|
|
|
@ -14,7 +14,7 @@ interface IMessageBoxCommandsPreviewItem {
|
|||
id: string;
|
||||
value: string;
|
||||
};
|
||||
theme: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const Item = ({ item, theme }: IMessageBoxCommandsPreviewItem) => {
|
||||
|
@ -37,7 +37,7 @@ const Item = ({ item, theme }: IMessageBoxCommandsPreviewItem) => {
|
|||
{loading ? <ActivityIndicator theme={theme} /> : null}
|
||||
</FastImage>
|
||||
) : (
|
||||
<CustomIcon name='attach' size={36} color={themes[theme].actionTintColor} />
|
||||
<CustomIcon name='attach' size={36} color={themes[theme!].actionTintColor} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
|
|
@ -10,7 +10,7 @@ import { withTheme } from '../../../theme';
|
|||
interface IMessageBoxCommandsPreview {
|
||||
commandPreview: [];
|
||||
showCommandPreview: boolean;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const CommandsPreview = React.memo(
|
||||
|
@ -21,7 +21,7 @@ const CommandsPreview = React.memo(
|
|||
return (
|
||||
<FlatList
|
||||
testID='commandbox-container'
|
||||
style={[styles.mentionList, { backgroundColor: themes[theme].messageboxBackground }]}
|
||||
style={[styles.mentionList, { backgroundColor: themes[theme!].messageboxBackground }]}
|
||||
data={commandPreview}
|
||||
renderItem={({ item }) => <Item item={item} theme={theme} />}
|
||||
keyExtractor={(item: any) => item.id}
|
||||
|
|
|
@ -68,11 +68,11 @@ interface IRoomHeader {
|
|||
tmid: string;
|
||||
teamMain: boolean;
|
||||
status: string;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
usersTyping: [];
|
||||
isGroupChat: boolean;
|
||||
parentTitle: string;
|
||||
onPress: Function;
|
||||
onPress: () => void;
|
||||
testID: string;
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ const Header = React.memo(
|
|||
renderFunc = () => (
|
||||
<View style={styles.titleContainer}>
|
||||
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />
|
||||
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>
|
||||
<Text style={[styles.subtitle, { color: themes[theme!].auxiliaryText }]} numberOfLines={1}>
|
||||
{parentTitle}
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -186,9 +186,15 @@ const Header = React.memo(
|
|||
{tmid ? null : (
|
||||
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />
|
||||
)}
|
||||
<HeaderTitle title={title} tmid={tmid} prid={prid} scale={scale} theme={theme} testID={testID} />
|
||||
<HeaderTitle title={title} tmid={tmid} prid={prid} scale={scale} theme={theme!} testID={testID} />
|
||||
</View>
|
||||
<SubTitle usersTyping={tmid ? [] : usersTyping} subtitle={subtitle} theme={theme} renderFunc={renderFunc} scale={scale} />
|
||||
<SubTitle
|
||||
usersTyping={tmid ? [] : usersTyping}
|
||||
subtitle={subtitle}
|
||||
theme={theme!}
|
||||
renderFunc={renderFunc}
|
||||
scale={scale}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ interface IRoomHeaderContainerProps {
|
|||
prid: string;
|
||||
tmid: string;
|
||||
teamMain: boolean;
|
||||
usersTyping: string;
|
||||
usersTyping: [];
|
||||
status: string;
|
||||
statusText: string;
|
||||
connecting: boolean;
|
||||
|
@ -79,14 +79,12 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
|||
teamMain,
|
||||
prid,
|
||||
tmid,
|
||||
widthOffset,
|
||||
status = 'offline',
|
||||
statusText,
|
||||
connecting,
|
||||
connected,
|
||||
usersTyping,
|
||||
onPress,
|
||||
roomUserId,
|
||||
width,
|
||||
height,
|
||||
parentTitle,
|
||||
|
@ -115,9 +113,6 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
|||
width={width}
|
||||
height={height}
|
||||
usersTyping={usersTyping}
|
||||
widthOffset={widthOffset}
|
||||
roomUserId={roomUserId}
|
||||
connecting={connecting}
|
||||
parentTitle={parentTitle}
|
||||
isGroupChat={isGroupChat}
|
||||
testID={testID}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { StyleSheet, ViewStyle } from 'react-native';
|
||||
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import { STATUS_COLORS, themes } from '../constants/colors';
|
||||
|
@ -13,13 +13,13 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IRoomTypeIcon {
|
||||
theme: string;
|
||||
theme?: string;
|
||||
type: string;
|
||||
isGroupChat: boolean;
|
||||
teamMain: boolean;
|
||||
status: string;
|
||||
size: number;
|
||||
style: any;
|
||||
isGroupChat?: boolean;
|
||||
teamMain?: boolean;
|
||||
status?: string;
|
||||
size?: number;
|
||||
style?: ViewStyle;
|
||||
}
|
||||
|
||||
const RoomTypeIcon = React.memo(({ type, isGroupChat, status, style, theme, teamMain, size = 16 }: IRoomTypeIcon) => {
|
||||
|
@ -27,11 +27,13 @@ const RoomTypeIcon = React.memo(({ type, isGroupChat, status, style, theme, team
|
|||
return null;
|
||||
}
|
||||
|
||||
const color = themes[theme].titleText;
|
||||
const color = themes[theme!].titleText;
|
||||
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} />;
|
||||
return (
|
||||
<Status style={[iconStyle, { color: STATUS_COLORS[status!] ?? STATUS_COLORS.offline }]} size={size} status={status!} />
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: move this to a separate function
|
||||
|
|
|
@ -12,16 +12,16 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface ISafeAreaView {
|
||||
testID: string;
|
||||
theme: string;
|
||||
vertical: boolean;
|
||||
style: object;
|
||||
children: JSX.Element;
|
||||
testID?: string;
|
||||
theme?: string;
|
||||
vertical?: boolean;
|
||||
style?: object;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const SafeAreaView = React.memo(({ style, children, testID, theme, vertical = true, ...props }: ISafeAreaView) => (
|
||||
<SafeAreaContext
|
||||
style={[styles.view, { backgroundColor: themes[theme].auxiliaryBackground }, style]}
|
||||
style={[styles.view, { backgroundColor: themes[theme!].auxiliaryBackground }, style]}
|
||||
edges={vertical ? ['right', 'left'] : undefined}
|
||||
testID={testID}
|
||||
{...props}>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, Text, TextInputProps, View } from 'react-native';
|
||||
import { NativeSyntheticEvent, StyleSheet, Text, TextInputFocusEventData, TextInputProps, View } from 'react-native';
|
||||
import Touchable from 'react-native-platform-touchable';
|
||||
|
||||
import TextInput from '../presentation/TextInput';
|
||||
|
@ -45,13 +45,15 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface ISearchBox {
|
||||
value?: string;
|
||||
onChangeText: TextInputProps['onChangeText'];
|
||||
onSubmitEditing: () => void;
|
||||
hasCancel: boolean;
|
||||
onCancelPress: Function;
|
||||
theme: string;
|
||||
inputRef: any;
|
||||
onSubmitEditing?: () => void;
|
||||
hasCancel?: boolean;
|
||||
onCancelPress?: Function;
|
||||
theme?: string;
|
||||
inputRef?: React.Ref<unknown>;
|
||||
testID?: string;
|
||||
onFocus?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
|
||||
}
|
||||
|
||||
const CancelButton = (onCancelPress: Function, theme: string) => (
|
||||
|
@ -73,10 +75,10 @@ const SearchBox = ({
|
|||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
{ backgroundColor: isIOS ? themes[theme].headerBackground : themes[theme].headerSecondaryBackground }
|
||||
{ backgroundColor: isIOS ? themes[theme!].headerBackground : themes[theme!].headerSecondaryBackground }
|
||||
]}>
|
||||
<View style={[styles.searchBox, { backgroundColor: themes[theme].searchboxBackground }]}>
|
||||
<CustomIcon name='search' size={14} color={themes[theme].auxiliaryText} />
|
||||
<View style={[styles.searchBox, { backgroundColor: themes[theme!].searchboxBackground }]}>
|
||||
<CustomIcon name='search' size={14} color={themes[theme!].auxiliaryText} />
|
||||
<TextInput
|
||||
ref={inputRef}
|
||||
autoCapitalize='none'
|
||||
|
@ -90,11 +92,11 @@ const SearchBox = ({
|
|||
underlineColorAndroid='transparent'
|
||||
onChangeText={onChangeText}
|
||||
onSubmitEditing={onSubmitEditing}
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
{...props}
|
||||
/>
|
||||
</View>
|
||||
{hasCancel ? CancelButton(onCancelPress, theme) : null}
|
||||
{hasCancel ? CancelButton(onCancelPress!, theme!) : null}
|
||||
</View>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { withTheme } from '../theme';
|
||||
import sharedStyles from '../views/Styles';
|
||||
|
@ -20,9 +19,14 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface ISearchHeader {
|
||||
theme?: string;
|
||||
onSearchChangeText?: (text: string) => void;
|
||||
}
|
||||
|
||||
// TODO: it might be useful to refactor this component for reusage
|
||||
const SearchHeader = ({ theme, onSearchChangeText }) => {
|
||||
const titleColorStyle = { color: themes[theme].headerTitleColor };
|
||||
const SearchHeader = ({ theme, onSearchChangeText }: ISearchHeader) => {
|
||||
const titleColorStyle = { color: themes[theme!].headerTitleColor };
|
||||
const isLight = theme === 'light';
|
||||
const { isLandscape } = useOrientation();
|
||||
const scale = isIOS && isLandscape && !isTablet ? 0.8 : 1;
|
||||
|
@ -35,15 +39,11 @@ const SearchHeader = ({ theme, onSearchChangeText }) => {
|
|||
style={[styles.title, isLight && titleColorStyle, { fontSize: titleFontSize }]}
|
||||
placeholder='Search'
|
||||
onChangeText={onSearchChangeText}
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
testID='thread-messages-view-search-header'
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
SearchHeader.propTypes = {
|
||||
theme: PropTypes.string,
|
||||
onSearchChangeText: PropTypes.func
|
||||
};
|
||||
export default withTheme(SearchHeader);
|
|
@ -5,9 +5,9 @@ import { themes } from '../constants/colors';
|
|||
import { withTheme } from '../theme';
|
||||
|
||||
interface IStatusBar {
|
||||
theme: string;
|
||||
barStyle: any;
|
||||
backgroundColor: string;
|
||||
theme?: string;
|
||||
barStyle?: any;
|
||||
backgroundColor?: string;
|
||||
}
|
||||
|
||||
const StatusBar = React.memo(({ theme, barStyle, backgroundColor }: IStatusBar) => {
|
||||
|
@ -17,7 +17,7 @@ const StatusBar = React.memo(({ theme, barStyle, backgroundColor }: IStatusBar)
|
|||
barStyle = 'dark-content';
|
||||
}
|
||||
}
|
||||
return <StatusBarRN backgroundColor={backgroundColor ?? themes[theme].headerBackground} barStyle={barStyle} animated />;
|
||||
return <StatusBarRN backgroundColor={backgroundColor ?? themes[theme!].headerBackground} barStyle={barStyle} animated />;
|
||||
});
|
||||
|
||||
export default withTheme(StatusBar);
|
||||
|
|
|
@ -50,7 +50,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IRCTextInputProps extends TextInputProps {
|
||||
export interface IRCTextInputProps extends TextInputProps {
|
||||
label?: string;
|
||||
error?: {
|
||||
error: any;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, ViewStyle } from 'react-native';
|
||||
import Touchable from 'react-native-platform-touchable';
|
||||
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import { themes } from '../constants/colors';
|
||||
import sharedStyles from '../views/Styles';
|
||||
import { withTheme } from '../theme';
|
||||
import { TThreadModel } from '../definitions/IThread';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -40,33 +41,25 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IThreadDetails {
|
||||
item: {
|
||||
tcount: number | string;
|
||||
replies: any;
|
||||
id: string;
|
||||
};
|
||||
item: Partial<TThreadModel>;
|
||||
user: {
|
||||
id: string;
|
||||
};
|
||||
badgeColor: string;
|
||||
badgeColor?: string;
|
||||
toggleFollowThread: Function;
|
||||
style: object;
|
||||
theme: string;
|
||||
style: ViewStyle;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, theme }: IThreadDetails) => {
|
||||
let { tcount } = item;
|
||||
if (tcount >= 1000) {
|
||||
if (tcount! >= 1000) {
|
||||
tcount = '+999';
|
||||
} else if (tcount >= 100) {
|
||||
tcount = '+99';
|
||||
}
|
||||
|
||||
let replies = item?.replies?.length ?? 0;
|
||||
let replies: number | string = item?.replies?.length ?? 0;
|
||||
if (replies >= 1000) {
|
||||
replies = '+999';
|
||||
} else if (replies >= 100) {
|
||||
replies = '+99';
|
||||
}
|
||||
|
||||
const isFollowing = item.replies?.find((u: any) => u === user?.id);
|
||||
|
@ -75,15 +68,15 @@ const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, them
|
|||
<View style={[styles.container, style]}>
|
||||
<View style={styles.detailsContainer}>
|
||||
<View style={styles.detailContainer}>
|
||||
<CustomIcon name='threads' size={24} color={themes[theme].auxiliaryText} />
|
||||
<Text style={[styles.detailText, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>
|
||||
<CustomIcon name='threads' size={24} color={themes[theme!].auxiliaryText} />
|
||||
<Text style={[styles.detailText, { color: themes[theme!].auxiliaryText }]} numberOfLines={1}>
|
||||
{tcount}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.detailContainer}>
|
||||
<CustomIcon name='user' size={24} color={themes[theme].auxiliaryText} />
|
||||
<Text style={[styles.detailText, { color: themes[theme].auxiliaryText }]} numberOfLines={1}>
|
||||
<CustomIcon name='user' size={24} color={themes[theme!].auxiliaryText} />
|
||||
<Text style={[styles.detailText, { color: themes[theme!].auxiliaryText }]} numberOfLines={1}>
|
||||
{replies}
|
||||
</Text>
|
||||
</View>
|
||||
|
@ -95,7 +88,7 @@ const ThreadDetails = ({ item, user, badgeColor, toggleFollowThread, style, them
|
|||
<CustomIcon
|
||||
size={24}
|
||||
name={isFollowing ? 'notification' : 'notification-disabled'}
|
||||
color={themes[theme].auxiliaryTintColor}
|
||||
color={themes[theme!].auxiliaryTintColor}
|
||||
/>
|
||||
</Touchable>
|
||||
</View>
|
||||
|
|
|
@ -22,7 +22,7 @@ const styles = StyleSheet.create({
|
|||
export const LISTENER = 'Toast';
|
||||
|
||||
interface IToastProps {
|
||||
theme: string;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
class Toast extends React.Component<IToastProps, any> {
|
||||
|
@ -61,8 +61,8 @@ class Toast extends React.Component<IToastProps, any> {
|
|||
ref={this.getToastRef}
|
||||
// @ts-ignore
|
||||
position='center'
|
||||
style={[styles.toast, { backgroundColor: themes[theme].toastBackground }]}
|
||||
textStyle={[styles.text, { color: themes[theme].buttonText }]}
|
||||
style={[styles.toast, { backgroundColor: themes[theme!].toastBackground }]}
|
||||
textStyle={[styles.text, { color: themes[theme!].buttonText }]}
|
||||
opacity={0.9}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -19,7 +19,7 @@ import styles from './styles';
|
|||
export const TWO_FACTOR = 'TWO_FACTOR';
|
||||
|
||||
interface ITwoFactor {
|
||||
theme: string;
|
||||
theme?: string;
|
||||
isMasterDetail: boolean;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
|||
setData({});
|
||||
};
|
||||
|
||||
const color = themes[theme].titleText;
|
||||
const color = themes[theme!].titleText;
|
||||
return (
|
||||
<Modal
|
||||
// @ts-ignore
|
||||
|
@ -101,7 +101,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
|||
style={[
|
||||
styles.content,
|
||||
isMasterDetail && [sharedStyles.modalFormSheet, styles.tablet],
|
||||
{ backgroundColor: themes[theme].backgroundColor }
|
||||
{ backgroundColor: themes[theme!].backgroundColor }
|
||||
]}>
|
||||
<Text style={[styles.title, { color }]}>{I18n.t(method?.title || 'Two_Factor_Authentication')}</Text>
|
||||
{method?.text ? <Text style={[styles.subtitle, { color }]}>{I18n.t(method.text)}</Text> : null}
|
||||
|
@ -128,7 +128,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
|||
<Button
|
||||
title={I18n.t('Cancel')}
|
||||
type='secondary'
|
||||
backgroundColor={themes[theme].chatComponentBackground}
|
||||
backgroundColor={themes[theme!].chatComponentBackground}
|
||||
style={styles.button}
|
||||
onPress={onCancel}
|
||||
theme={theme}
|
||||
|
|
|
@ -5,6 +5,7 @@ import Renderer from 'commonmark-react-renderer';
|
|||
import removeMarkdown from 'remove-markdown';
|
||||
import { MarkdownAST } from '@rocket.chat/message-parser';
|
||||
|
||||
import { UserMention } from '../message/interfaces';
|
||||
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||
import I18n from '../../i18n';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
@ -23,14 +24,6 @@ import styles from './styles';
|
|||
import { isValidURL } from '../../utils/url';
|
||||
import NewMarkdown from './new';
|
||||
|
||||
interface IUser {
|
||||
_id: string;
|
||||
username: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
type UserMention = Pick<IUser, '_id' | 'username' | 'name'>;
|
||||
|
||||
interface IMarkdownProps {
|
||||
msg: string;
|
||||
md: MarkdownAST;
|
||||
|
|
|
@ -30,7 +30,7 @@ interface IMessageAudioProps {
|
|||
};
|
||||
theme: string;
|
||||
getCustomEmoji: Function;
|
||||
scale: number;
|
||||
scale?: number;
|
||||
}
|
||||
|
||||
interface IMessageAudioState {
|
||||
|
|
|
@ -24,7 +24,7 @@ interface IMessageReaction {
|
|||
}
|
||||
|
||||
interface IMessageReactions {
|
||||
reactions: object[];
|
||||
reactions?: object[];
|
||||
getCustomEmoji: Function;
|
||||
theme: string;
|
||||
}
|
||||
|
|
|
@ -68,8 +68,8 @@ interface IMessageUrl {
|
|||
}
|
||||
|
||||
interface IMessageUrls {
|
||||
urls: any;
|
||||
theme: string;
|
||||
urls?: any;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const UrlImage = React.memo(
|
||||
|
@ -156,7 +156,7 @@ const Urls = React.memo(
|
|||
return null;
|
||||
}
|
||||
|
||||
return urls.map((url: any, index: number) => <Url url={url} key={url.url} index={index} theme={theme} />);
|
||||
return urls.map((url: any, index: number) => <Url url={url} key={url.url} index={index} theme={theme!} />);
|
||||
},
|
||||
(oldProps, newProps) => dequal(oldProps.urls, newProps.urls) && oldProps.theme === newProps.theme
|
||||
);
|
||||
|
|
|
@ -38,17 +38,17 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IMessageUser {
|
||||
isHeader: boolean;
|
||||
hasError: boolean;
|
||||
isHeader?: boolean;
|
||||
hasError?: boolean;
|
||||
useRealName: boolean;
|
||||
author: {
|
||||
author?: {
|
||||
_id: string;
|
||||
name: string;
|
||||
username: string;
|
||||
name?: string;
|
||||
username?: string;
|
||||
};
|
||||
alias: string;
|
||||
ts: Date;
|
||||
timeFormat: string;
|
||||
alias?: string;
|
||||
ts?: Date;
|
||||
timeFormat?: string;
|
||||
theme: string;
|
||||
navToRoomInfo: Function;
|
||||
type: string;
|
||||
|
@ -59,16 +59,16 @@ const User = React.memo(
|
|||
if (isHeader || hasError) {
|
||||
const navParam = {
|
||||
t: 'd',
|
||||
rid: author._id
|
||||
rid: author!._id
|
||||
};
|
||||
const { user } = useContext(MessageContext);
|
||||
const username = (useRealName && author.name) || author.username;
|
||||
const username = (useRealName && author!.name) || author!.username;
|
||||
const aliasUsername = alias ? (
|
||||
<Text style={[styles.alias, { color: themes[theme].auxiliaryText }]}> @{username}</Text>
|
||||
) : null;
|
||||
const time = moment(ts).format(timeFormat);
|
||||
const onUserPress = () => navToRoomInfo(navParam);
|
||||
const isDisabled = author._id === user.id;
|
||||
const isDisabled = author!._id === user.id;
|
||||
|
||||
const textContent = (
|
||||
<>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Keyboard } from 'react-native';
|
||||
import { Keyboard, ViewStyle } from 'react-native';
|
||||
|
||||
import Message from './Message';
|
||||
import MessageContext from './Context';
|
||||
|
@ -17,53 +17,55 @@ interface IMessageContainerProps {
|
|||
username: string;
|
||||
token: string;
|
||||
};
|
||||
rid: string;
|
||||
msg?: string;
|
||||
rid?: string;
|
||||
timeFormat: string;
|
||||
style: any;
|
||||
archived: boolean;
|
||||
broadcast: boolean;
|
||||
previousItem: {
|
||||
style?: ViewStyle;
|
||||
archived?: boolean;
|
||||
broadcast?: boolean;
|
||||
previousItem?: {
|
||||
ts: any;
|
||||
u: any;
|
||||
groupable: any;
|
||||
id: any;
|
||||
tmid: any;
|
||||
id: string;
|
||||
tmid: string;
|
||||
status: any;
|
||||
};
|
||||
isHeader: boolean;
|
||||
baseUrl: string;
|
||||
Message_GroupingPeriod: number;
|
||||
isReadReceiptEnabled: boolean;
|
||||
Message_GroupingPeriod?: number;
|
||||
isReadReceiptEnabled?: boolean;
|
||||
isThreadRoom: boolean;
|
||||
useRealName: boolean;
|
||||
autoTranslateRoom: boolean;
|
||||
autoTranslateLanguage: string;
|
||||
status: number;
|
||||
isIgnored: boolean;
|
||||
highlighted: boolean;
|
||||
getCustomEmoji(): void;
|
||||
onLongPress: Function;
|
||||
onReactionPress: Function;
|
||||
onEncryptedPress: Function;
|
||||
onDiscussionPress: Function;
|
||||
onThreadPress: Function;
|
||||
errorActionsShow: Function;
|
||||
replyBroadcast: Function;
|
||||
reactionInit: Function;
|
||||
fetchThreadName: Function;
|
||||
showAttachment: Function;
|
||||
onReactionLongPress: Function;
|
||||
navToRoomInfo: Function;
|
||||
callJitsi: Function;
|
||||
blockAction: Function;
|
||||
onAnswerButtonPress: Function;
|
||||
autoTranslateRoom?: boolean;
|
||||
autoTranslateLanguage?: string;
|
||||
status?: number;
|
||||
isIgnored?: boolean;
|
||||
highlighted?: boolean;
|
||||
getCustomEmoji(name: string): void;
|
||||
onLongPress?: Function;
|
||||
onReactionPress?: Function;
|
||||
onEncryptedPress?: Function;
|
||||
onDiscussionPress?: Function;
|
||||
onThreadPress?: Function;
|
||||
errorActionsShow?: Function;
|
||||
replyBroadcast?: Function;
|
||||
reactionInit?: Function;
|
||||
fetchThreadName?: Function;
|
||||
showAttachment?: Function;
|
||||
onReactionLongPress?: Function;
|
||||
navToRoomInfo?: Function;
|
||||
callJitsi?: Function;
|
||||
blockAction?: Function;
|
||||
onAnswerButtonPress?: Function;
|
||||
theme: string;
|
||||
threadBadgeColor: string;
|
||||
toggleFollowThread: Function;
|
||||
jumpToMessage: Function;
|
||||
threadBadgeColor?: string;
|
||||
toggleFollowThread?: Function;
|
||||
jumpToMessage?: Function;
|
||||
onPress: Function;
|
||||
}
|
||||
|
||||
class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
||||
class MessageContainer extends React.Component<IMessageContainerProps> {
|
||||
static defaultProps = {
|
||||
getCustomEmoji: () => {},
|
||||
onLongPress: () => {},
|
||||
|
@ -224,7 +226,7 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
previousItem.ts.toDateString() === item.ts.toDateString() &&
|
||||
previousItem.u.username === item.u.username &&
|
||||
!(previousItem.groupable === false || item.groupable === false || broadcast === true) &&
|
||||
item.ts - previousItem.ts < Message_GroupingPeriod * 1000 &&
|
||||
item.ts - previousItem.ts < Message_GroupingPeriod! * 1000 &&
|
||||
previousItem.tmid === item.tmid
|
||||
) {
|
||||
return false;
|
||||
|
@ -299,7 +301,7 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
const { item, theme, jumpToMessage } = this.props;
|
||||
const isMessageLink = item?.attachments?.findIndex((att: any) => att?.message_link === link) !== -1;
|
||||
if (isMessageLink) {
|
||||
return jumpToMessage(link);
|
||||
return jumpToMessage!(link);
|
||||
}
|
||||
openLink(link, theme);
|
||||
};
|
||||
|
@ -365,7 +367,7 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
// "autoTranslateRoom" and "autoTranslateLanguage" are properties from the subscription
|
||||
// "autoTranslateMessage" is a toggle between "View Original" and "Translate" state
|
||||
if (autoTranslateRoom && autoTranslateMessage) {
|
||||
message = getMessageTranslation(item, autoTranslateLanguage) || message;
|
||||
message = getMessageTranslation(item, autoTranslateLanguage!) || message;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -393,7 +395,7 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
id={id}
|
||||
msg={message}
|
||||
md={md}
|
||||
rid={rid}
|
||||
rid={rid!}
|
||||
author={u}
|
||||
ts={ts}
|
||||
type={t}
|
||||
|
@ -407,10 +409,10 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
emoji={emoji}
|
||||
timeFormat={timeFormat}
|
||||
style={style}
|
||||
archived={archived}
|
||||
broadcast={broadcast}
|
||||
archived={archived!}
|
||||
broadcast={broadcast!}
|
||||
useRealName={useRealName}
|
||||
isReadReceiptEnabled={isReadReceiptEnabled}
|
||||
isReadReceiptEnabled={isReadReceiptEnabled!}
|
||||
unread={unread}
|
||||
role={role}
|
||||
drid={drid}
|
||||
|
@ -420,10 +422,10 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
tcount={tcount}
|
||||
tlm={tlm}
|
||||
tmsg={tmsg}
|
||||
fetchThreadName={fetchThreadName}
|
||||
fetchThreadName={fetchThreadName!}
|
||||
mentions={mentions}
|
||||
channels={channels}
|
||||
isIgnored={this.isIgnored}
|
||||
isIgnored={this.isIgnored!}
|
||||
isEdited={editedBy && !!editedBy.username}
|
||||
isHeader={this.isHeader}
|
||||
isThreadReply={this.isThreadReply}
|
||||
|
@ -433,13 +435,13 @@ class MessageContainer extends React.Component<IMessageContainerProps, any> {
|
|||
isTemp={this.isTemp}
|
||||
isEncrypted={this.isEncrypted}
|
||||
hasError={this.hasError}
|
||||
showAttachment={showAttachment}
|
||||
showAttachment={showAttachment!}
|
||||
getCustomEmoji={getCustomEmoji}
|
||||
navToRoomInfo={navToRoomInfo}
|
||||
callJitsi={callJitsi}
|
||||
blockAction={blockAction}
|
||||
navToRoomInfo={navToRoomInfo!}
|
||||
callJitsi={callJitsi!}
|
||||
blockAction={blockAction!}
|
||||
theme={theme}
|
||||
highlighted={highlighted}
|
||||
highlighted={highlighted!}
|
||||
/>
|
||||
</MessageContext.Provider>
|
||||
);
|
||||
|
|
|
@ -51,12 +51,13 @@ export interface IMessageCallButton {
|
|||
}
|
||||
|
||||
export interface IUser {
|
||||
_id: string;
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type UserMention = Pick<IUser, '_id' | 'username' | 'name'>;
|
||||
export type UserMention = Pick<IUser, 'id' | 'username' | 'name'>;
|
||||
|
||||
export interface IMessageContent {
|
||||
_id: string;
|
||||
|
|
|
@ -26,7 +26,9 @@ export const SYSTEM_MESSAGES = [
|
|||
'au',
|
||||
'ru',
|
||||
'ul',
|
||||
'ult',
|
||||
'uj',
|
||||
'ujt',
|
||||
'ut',
|
||||
'rm',
|
||||
'user-muted',
|
||||
|
@ -50,8 +52,10 @@ export const SYSTEM_MESSAGE_TYPES = {
|
|||
MESSAGE_PINNED: 'message_pinned',
|
||||
MESSAGE_SNIPPETED: 'message_snippeted',
|
||||
USER_JOINED_CHANNEL: 'uj',
|
||||
USER_JOINED_TEAM: 'ujt',
|
||||
USER_JOINED_DISCUSSION: 'ut',
|
||||
USER_LEFT_CHANNEL: 'ul'
|
||||
USER_LEFT_CHANNEL: 'ul',
|
||||
USER_LEFT_TEAM: 'ult'
|
||||
};
|
||||
|
||||
export const SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME = [
|
||||
|
@ -59,8 +63,10 @@ export const SYSTEM_MESSAGE_TYPES_WITH_AUTHOR_NAME = [
|
|||
SYSTEM_MESSAGE_TYPES.MESSAGE_PINNED,
|
||||
SYSTEM_MESSAGE_TYPES.MESSAGE_SNIPPETED,
|
||||
SYSTEM_MESSAGE_TYPES.USER_JOINED_CHANNEL,
|
||||
SYSTEM_MESSAGE_TYPES.USER_JOINED_TEAM,
|
||||
SYSTEM_MESSAGE_TYPES.USER_JOINED_DISCUSSION,
|
||||
SYSTEM_MESSAGE_TYPES.USER_LEFT_CHANNEL
|
||||
SYSTEM_MESSAGE_TYPES.USER_LEFT_CHANNEL,
|
||||
SYSTEM_MESSAGE_TYPES.USER_LEFT_TEAM
|
||||
];
|
||||
|
||||
type TInfoMessage = {
|
||||
|
@ -77,6 +83,9 @@ export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage) => {
|
|||
if (type === 'uj') {
|
||||
return I18n.t('Has_joined_the_channel');
|
||||
}
|
||||
if (type === 'ujt') {
|
||||
return I18n.t('Has_joined_the_team');
|
||||
}
|
||||
if (type === 'ut') {
|
||||
return I18n.t('Has_joined_the_conversation');
|
||||
}
|
||||
|
@ -92,6 +101,9 @@ export const getInfoMessage = ({ type, role, msg, author }: TInfoMessage) => {
|
|||
if (type === 'ul') {
|
||||
return I18n.t('Has_left_the_channel');
|
||||
}
|
||||
if (type === 'ult') {
|
||||
return I18n.t('Has_left_the_team');
|
||||
}
|
||||
if (type === 'ru') {
|
||||
return I18n.t('User_removed_by', { userRemoved: msg, userBy: username });
|
||||
}
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
import { IServedBy } from './IServedBy';
|
||||
import { SubscriptionType } from './ISubscription';
|
||||
|
||||
export interface IRoom {
|
||||
id: string;
|
||||
rid: string;
|
||||
prid: string;
|
||||
t: SubscriptionType;
|
||||
name: string;
|
||||
teamMain: boolean;
|
||||
alert?: boolean;
|
||||
customFields: string[];
|
||||
broadcast: boolean;
|
||||
encrypted: boolean;
|
||||
|
|
|
@ -43,10 +43,10 @@ export interface IThread {
|
|||
id: string;
|
||||
msg?: string;
|
||||
t?: SubscriptionType;
|
||||
rid: string;
|
||||
_updatedAt: Date;
|
||||
ts: Date;
|
||||
u: IUserMessage;
|
||||
rid?: string;
|
||||
_updatedAt?: Date;
|
||||
ts?: Date;
|
||||
u?: IUserMessage;
|
||||
alias?: string;
|
||||
parseUrls?: boolean;
|
||||
groupable?: boolean;
|
||||
|
@ -64,8 +64,8 @@ export interface IThread {
|
|||
dcount?: number;
|
||||
dlm?: number;
|
||||
tmid?: string;
|
||||
tcount?: number;
|
||||
tlm?: Date;
|
||||
tcount: number | string;
|
||||
tlm?: string;
|
||||
replies?: string[];
|
||||
mentions?: IUserMention[];
|
||||
channels?: IUserChannel[];
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
import { NavigatorScreenParams } from '@react-navigation/core';
|
||||
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||
|
||||
import { ISubscription } from './definitions/ISubscription';
|
||||
import { IServer } from './definitions/IServer';
|
||||
import { IAttachment } from './definitions/IAttachment';
|
||||
import { MasterDetailInsideStackParamList } from './stacks/MasterDetailStack/types';
|
||||
import { OutsideParamList, InsideStackParamList } from './stacks/types';
|
||||
import { ISubscription } from './ISubscription';
|
||||
import { IServer } from './IServer';
|
||||
import { IAttachment } from './IAttachment';
|
||||
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
|
||||
import { OutsideParamList, InsideStackParamList } from '../stacks/types';
|
||||
|
||||
interface INavigationProps {
|
||||
route?: any;
|
||||
navigation?: any;
|
||||
isMasterDetail?: boolean;
|
||||
}
|
||||
|
||||
export type TNavigationOptions = {
|
||||
navigationOptions?(props: INavigationProps): StackNavigationOptions;
|
||||
};
|
||||
|
||||
export type SetUsernameStackParamList = {
|
||||
SetUsernameView: {
|
|
@ -2,6 +2,8 @@ import React from 'react';
|
|||
import { Dimensions } from 'react-native';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
import { TNavigationOptions } from './definitions/navigationTypes';
|
||||
|
||||
export interface IDimensionsContextProps {
|
||||
width: number;
|
||||
height?: number;
|
||||
|
@ -22,10 +24,11 @@ export interface IDimensionsContextProps {
|
|||
|
||||
export const DimensionsContext = React.createContext<Partial<IDimensionsContextProps>>(Dimensions.get('window'));
|
||||
|
||||
export function withDimensions(Component: any): any {
|
||||
const DimensionsComponent = (props: any) => (
|
||||
export function withDimensions<T extends object>(Component: React.ComponentType<T> & TNavigationOptions): typeof Component {
|
||||
const DimensionsComponent = (props: T) => (
|
||||
<DimensionsContext.Consumer>{contexts => <Component {...props} {...contexts} />}</DimensionsContext.Consumer>
|
||||
);
|
||||
|
||||
hoistNonReactStatics(DimensionsComponent, Component);
|
||||
return DimensionsComponent;
|
||||
}
|
||||
|
|
|
@ -249,8 +249,10 @@
|
|||
"Full_table": "Click to see full table",
|
||||
"Generate_New_Link": "Generate New Link",
|
||||
"Has_joined_the_channel": "has joined the channel",
|
||||
"Has_joined_the_team": "has joined the team",
|
||||
"Has_joined_the_conversation": "has joined the conversation",
|
||||
"Has_left_the_channel": "has left the channel",
|
||||
"Has_left_the_team": "has left the team",
|
||||
"Hide_System_Messages": "Hide System Messages",
|
||||
"Hide_type_messages": "Hide \"{{type}}\" messages",
|
||||
"How_It_Works": "How It Works",
|
||||
|
|
|
@ -18,9 +18,9 @@ interface IServerItem {
|
|||
name: string;
|
||||
};
|
||||
onPress(): void;
|
||||
onLongPress(): void;
|
||||
hasCheck: boolean;
|
||||
theme: string;
|
||||
onLongPress?(): void;
|
||||
hasCheck?: boolean;
|
||||
theme?: string;
|
||||
}
|
||||
|
||||
const defaultLogo = require('../../static/images/logo.png');
|
||||
|
@ -31,10 +31,10 @@ const ServerItem = React.memo(({ item, onPress, onLongPress, hasCheck, theme }:
|
|||
onLongPress={() => onLongPress?.()}
|
||||
testID={`rooms-list-header-server-${item.id}`}
|
||||
android_ripple={{
|
||||
color: themes[theme].bannerBackground
|
||||
color: themes[theme!].bannerBackground
|
||||
}}
|
||||
style={({ pressed }: any) => ({
|
||||
backgroundColor: isIOS && pressed ? themes[theme].bannerBackground : themes[theme].backgroundColor
|
||||
backgroundColor: isIOS && pressed ? themes[theme!].bannerBackground : themes[theme!].backgroundColor
|
||||
})}>
|
||||
<View style={styles.serverItemContainer}>
|
||||
{item.iconURL ? (
|
||||
|
@ -52,14 +52,14 @@ const ServerItem = React.memo(({ item, onPress, onLongPress, hasCheck, theme }:
|
|||
<FastImage source={defaultLogo} style={styles.serverIcon} />
|
||||
)}
|
||||
<View style={styles.serverTextContainer}>
|
||||
<Text numberOfLines={1} style={[styles.serverName, { color: themes[theme].titleText }]}>
|
||||
<Text numberOfLines={1} style={[styles.serverName, { color: themes[theme!].titleText }]}>
|
||||
{item.name || item.id}
|
||||
</Text>
|
||||
<Text numberOfLines={1} style={[styles.serverUrl, { color: themes[theme].auxiliaryText }]}>
|
||||
<Text numberOfLines={1} style={[styles.serverUrl, { color: themes[theme!].auxiliaryText }]}>
|
||||
{item.id}
|
||||
</Text>
|
||||
</View>
|
||||
{hasCheck ? <Check theme={theme} /> : null}
|
||||
{hasCheck ? <Check theme={theme!} /> : null}
|
||||
</View>
|
||||
</Pressable>
|
||||
));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { I18nManager, StyleProp, StyleSheet, TextInput, TextInputProps, TextStyle } from 'react-native';
|
||||
import { I18nManager, StyleProp, StyleSheet, TextInput, TextStyle } from 'react-native';
|
||||
|
||||
import { IRCTextInputProps } from '../containers/TextInput';
|
||||
import { themes } from '../constants/colors';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -9,7 +10,7 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IThemedTextInput extends TextInputProps {
|
||||
interface IThemedTextInput extends IRCTextInputProps {
|
||||
style: StyleProp<TextStyle>;
|
||||
theme: string;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, ViewStyle } from 'react-native';
|
||||
|
||||
import sharedStyles from '../../views/Styles';
|
||||
import { getUnreadStyle } from './getUnreadStyle';
|
||||
|
@ -30,15 +30,15 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IUnreadBadge {
|
||||
theme: string;
|
||||
unread: number;
|
||||
userMentions: number;
|
||||
groupMentions: number;
|
||||
style: object;
|
||||
tunread: [];
|
||||
tunreadUser: [];
|
||||
tunreadGroup: [];
|
||||
small: boolean;
|
||||
theme?: string;
|
||||
unread?: number;
|
||||
userMentions?: number;
|
||||
groupMentions?: number;
|
||||
style?: ViewStyle;
|
||||
tunread?: [];
|
||||
tunreadUser?: [];
|
||||
tunreadGroup?: [];
|
||||
small?: boolean;
|
||||
}
|
||||
|
||||
const UnreadBadge = React.memo(
|
||||
|
|
|
@ -26,7 +26,7 @@ import { setCurrentScreen } from './utils/log';
|
|||
import AuthLoadingView from './views/AuthLoadingView';
|
||||
import { DimensionsContext } from './dimensions';
|
||||
import debounce from './utils/debounce';
|
||||
import { ShareInsideStackParamList, ShareOutsideStackParamList, ShareAppStackParamList } from './navigationTypes';
|
||||
import { ShareInsideStackParamList, ShareOutsideStackParamList, ShareAppStackParamList } from './definitions/navigationTypes';
|
||||
|
||||
interface IDimensions {
|
||||
width: number;
|
||||
|
|
|
@ -116,10 +116,10 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
<ModalStack.Screen
|
||||
name='RoomActionsView'
|
||||
component={RoomActionsView}
|
||||
options={props => RoomActionsView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => RoomActionsView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='RoomInfoView' component={RoomInfoView} options={RoomInfoView.navigationOptions} />
|
||||
<ModalStack.Screen name='SelectListView' component={SelectListView} options={SelectListView.navigationOptions} />
|
||||
<ModalStack.Screen name='SelectListView' component={SelectListView} />
|
||||
<ModalStack.Screen name='RoomInfoEditView' component={RoomInfoEditView} options={RoomInfoEditView.navigationOptions} />
|
||||
<ModalStack.Screen name='RoomMembersView' component={RoomMembersView} options={RoomMembersView.navigationOptions} />
|
||||
<ModalStack.Screen
|
||||
|
@ -145,12 +145,12 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
<ModalStack.Screen
|
||||
name='DirectoryView'
|
||||
component={DirectoryView}
|
||||
options={props => DirectoryView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => DirectoryView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen
|
||||
name='QueueListView'
|
||||
component={QueueListView}
|
||||
options={props => QueueListView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => QueueListView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen
|
||||
name='NotificationPrefView'
|
||||
|
@ -172,12 +172,12 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
<ModalStack.Screen
|
||||
name='ReadReceiptsView'
|
||||
component={ReadReceiptsView}
|
||||
options={props => ReadReceiptsView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => ReadReceiptsView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen
|
||||
name='SettingsView'
|
||||
component={SettingsView}
|
||||
options={props => SettingsView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => SettingsView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='LanguageView' component={LanguageView} options={LanguageView.navigationOptions} />
|
||||
<ModalStack.Screen name='ThemeView' component={ThemeView} options={ThemeView.navigationOptions} />
|
||||
|
@ -195,13 +195,13 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
|||
<ModalStack.Screen
|
||||
name='ProfileView'
|
||||
component={ProfileView}
|
||||
options={props => ProfileView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => ProfileView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
|
||||
<ModalStack.Screen
|
||||
name='AdminPanelView'
|
||||
component={AdminPanelView}
|
||||
options={props => AdminPanelView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
options={props => AdminPanelView.navigationOptions!({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen name='NewMessageView' component={NewMessageView} options={NewMessageView.navigationOptions} />
|
||||
<ModalStack.Screen name='SelectedUsersViewCreateChannel' component={SelectedUsersView} />
|
||||
|
|
|
@ -2,6 +2,7 @@ import { NavigatorScreenParams } from '@react-navigation/core';
|
|||
import { TextInputProps } from 'react-native';
|
||||
import Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
import { IRoom } from '../definitions/IRoom';
|
||||
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
||||
import { IServer } from '../definitions/IServer';
|
||||
import { IAttachment } from '../definitions/IAttachment';
|
||||
|
@ -31,13 +32,13 @@ export type ChatsStackParamList = {
|
|||
joined: boolean;
|
||||
};
|
||||
SelectListView: {
|
||||
data: any;
|
||||
data: IRoom[];
|
||||
title: string;
|
||||
infoText: string;
|
||||
nextAction: Function;
|
||||
showAlert: boolean;
|
||||
nextAction: (selected: string[]) => void;
|
||||
showAlert: () => void;
|
||||
isSearch: boolean;
|
||||
onSearch: Function;
|
||||
onSearch: (text: string) => Partial<IRoom[]>;
|
||||
isRadio?: boolean;
|
||||
};
|
||||
RoomInfoView: {
|
||||
|
@ -64,7 +65,7 @@ export type ChatsStackParamList = {
|
|||
showButton?: boolean;
|
||||
title?: string;
|
||||
buttonText?: string;
|
||||
nextAction?: Function;
|
||||
nextAction?(): void;
|
||||
};
|
||||
InviteUsersView: {
|
||||
rid: string;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
|
||||
import { TNavigationOptions } from './definitions/navigationTypes';
|
||||
import { IThemePreference } from './definitions/ITheme';
|
||||
|
||||
interface IThemeContextProps {
|
||||
|
@ -11,12 +12,13 @@ interface IThemeContextProps {
|
|||
|
||||
export const ThemeContext = React.createContext<IThemeContextProps>({ theme: 'light' });
|
||||
|
||||
export function withTheme(Component: any): any {
|
||||
const ThemedComponent = (props: any) => (
|
||||
export function withTheme<T extends object>(Component: React.ComponentType<T> & TNavigationOptions): typeof Component {
|
||||
const ThemedComponent = (props: T) => (
|
||||
<ThemeContext.Consumer>{contexts => <Component {...props} {...contexts} />}</ThemeContext.Consumer>
|
||||
);
|
||||
|
||||
hoistNonReactStatics(ThemedComponent, Component);
|
||||
return ThemedComponent;
|
||||
}
|
||||
|
||||
export const useTheme = () => React.useContext(ThemeContext);
|
||||
export const useTheme = (): IThemeContextProps => React.useContext(ThemeContext);
|
||||
|
|
|
@ -3,10 +3,18 @@ export const MessageTypeValues = [
|
|||
value: 'uj',
|
||||
text: 'Message_HideType_uj'
|
||||
},
|
||||
{
|
||||
value: 'ujt',
|
||||
text: 'Message_HideType_ujt'
|
||||
},
|
||||
{
|
||||
value: 'ul',
|
||||
text: 'Message_HideType_ul'
|
||||
},
|
||||
{
|
||||
value: 'ult',
|
||||
text: 'Message_HideType_ult'
|
||||
},
|
||||
{
|
||||
value: 'ru',
|
||||
text: 'Message_HideType_ru'
|
||||
|
|
|
@ -22,11 +22,11 @@ import { goRoom } from '../utils/goRoom';
|
|||
import { showErrorAlert } from '../utils/info';
|
||||
import debounce from '../utils/debounce';
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import { IRoom } from '../definitions/IRoom';
|
||||
|
||||
interface IAddExistingChannelViewState {
|
||||
// TODO: refactor with Room Model
|
||||
search: any[];
|
||||
channels: any[];
|
||||
search: Array<IRoom>;
|
||||
channels: Array<IRoom>;
|
||||
selected: string[];
|
||||
loading: boolean;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ const QUERY_SIZE = 50;
|
|||
|
||||
class AddExistingChannelView extends React.Component<IAddExistingChannelViewProps, IAddExistingChannelViewState> {
|
||||
private teamId?: string;
|
||||
|
||||
constructor(props: IAddExistingChannelViewProps) {
|
||||
super(props);
|
||||
this.query();
|
||||
|
@ -93,10 +94,9 @@ class AddExistingChannelView extends React.Component<IAddExistingChannelViewProp
|
|||
)
|
||||
.fetch();
|
||||
|
||||
// TODO: Refactor with Room Model
|
||||
const asyncFilter = async (channelsArray: any[]) => {
|
||||
const asyncFilter = async (channelsArray: Array<IRoom>) => {
|
||||
const results = await Promise.all(
|
||||
channelsArray.map(async (channel: any) => {
|
||||
channelsArray.map(async (channel: IRoom) => {
|
||||
if (channel.prid) {
|
||||
return false;
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ class AddExistingChannelView extends React.Component<IAddExistingChannelViewProp
|
|||
<FlatList
|
||||
data={search.length > 0 ? search : channels}
|
||||
extraData={this.state}
|
||||
keyExtractor={item => item._id}
|
||||
keyExtractor={item => item.id}
|
||||
ListHeaderComponent={this.renderHeader}
|
||||
renderItem={this.renderItem}
|
||||
ItemSeparatorComponent={List.Separator}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import { WebView } from 'react-native-webview';
|
||||
import { connect } from 'react-redux';
|
||||
import { DrawerScreenProps } from '@react-navigation/drawer';
|
||||
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||
|
||||
import I18n from '../../i18n';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
|
@ -22,7 +23,7 @@ interface INavigationOptions {
|
|||
}
|
||||
|
||||
class AdminPanelView extends React.Component<IAdminPanelViewProps, any> {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: INavigationOptions) => ({
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: INavigationOptions): StackNavigationOptions => ({
|
||||
headerLeft: isMasterDetail ? undefined : () => <HeaderButton.Drawer navigation={navigation} />,
|
||||
title: I18n.t('Admin_Panel')
|
||||
});
|
||||
|
|
|
@ -113,7 +113,7 @@ class AutoTranslateView extends React.Component<IAutoTranslateViewProps, any> {
|
|||
|
||||
renderIcon = () => {
|
||||
const { theme } = this.props;
|
||||
return <List.Icon name='check' style={{ color: themes[theme].tintColor }} />;
|
||||
return <List.Icon name='check' color={themes[theme!].tintColor} />;
|
||||
};
|
||||
|
||||
renderSwitch = () => {
|
||||
|
@ -131,7 +131,7 @@ class AutoTranslateView extends React.Component<IAutoTranslateViewProps, any> {
|
|||
title={name || language}
|
||||
onPress={() => this.saveAutoTranslateLanguage(language)}
|
||||
testID={`auto-translate-view-${language}`}
|
||||
right={isSelected ? this.renderIcon : null}
|
||||
right={() => (isSelected ? this.renderIcon() : null)}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -127,7 +127,7 @@ class DefaultBrowserView extends React.Component<IDefaultBrowserViewProps, IDefa
|
|||
title={I18n.t(title, { defaultValue: title })}
|
||||
onPress={() => this.changeDefaultBrowser(value)}
|
||||
testID={`default-browser-view-${title}`}
|
||||
right={this.isSelected(value) ? this.renderIcon : null}
|
||||
right={() => (this.isSelected(value) ? this.renderIcon() : null)}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { FlatList, Text, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
|
||||
import { ChatsStackParamList } from '../../stacks/types';
|
||||
import * as List from '../../containers/List';
|
||||
|
@ -39,8 +39,8 @@ interface IDirectoryViewProps {
|
|||
}
|
||||
|
||||
class DirectoryView extends React.Component<IDirectoryViewProps, any> {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: any) => {
|
||||
const options: any = {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: IDirectoryViewProps) => {
|
||||
const options: StackNavigationOptions = {
|
||||
title: I18n.t('Directory')
|
||||
};
|
||||
if (isMasterDetail) {
|
||||
|
|
|
@ -40,9 +40,9 @@ interface IInviteUsersViewProps {
|
|||
class InviteUsersView extends React.Component<IInviteUsersViewProps, any> {
|
||||
private rid: string;
|
||||
|
||||
static navigationOptions: StackNavigationOptions = {
|
||||
static navigationOptions = (): StackNavigationOptions => ({
|
||||
title: I18n.t('Invite_users')
|
||||
};
|
||||
});
|
||||
|
||||
constructor(props: IInviteUsersViewProps) {
|
||||
super(props);
|
||||
|
|
|
@ -134,7 +134,7 @@ class LanguageView extends React.Component<ILanguageViewProps, ILanguageViewStat
|
|||
title={label}
|
||||
onPress={() => this.submit(value)}
|
||||
testID={`language-view-${value}`}
|
||||
right={isSelected ? this.renderIcon : null}
|
||||
right={() => (isSelected ? this.renderIcon() : null)}
|
||||
translateTitle={false}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -15,9 +15,9 @@ interface ILegalView {
|
|||
}
|
||||
|
||||
class LegalView extends React.Component<ILegalView, any> {
|
||||
static navigationOptions: StackNavigationOptions = {
|
||||
static navigationOptions = (): StackNavigationOptions => ({
|
||||
title: I18n.t('Legal')
|
||||
};
|
||||
});
|
||||
|
||||
onPressItem = ({ route }: { route: string }) => {
|
||||
const { server, theme } = this.props;
|
||||
|
|
|
@ -25,6 +25,8 @@ import { ISubscription, SubscriptionType } from '../../definitions/ISubscription
|
|||
interface IMessagesViewProps {
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
};
|
||||
baseUrl: string;
|
||||
navigation: CompositeNavigationProp<
|
||||
|
|
|
@ -15,7 +15,6 @@ import ActivityIndicator from '../containers/ActivityIndicator';
|
|||
import { CONTAINER_TYPES, MODAL_ACTIONS } from '../lib/methods/actions';
|
||||
import { textParser } from '../containers/UIKit/utils';
|
||||
import Navigation from '../lib/Navigation';
|
||||
import sharedStyles from './Styles';
|
||||
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
@ -25,10 +24,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
content: {
|
||||
paddingVertical: 16
|
||||
},
|
||||
submit: {
|
||||
...sharedStyles.textSemibold,
|
||||
fontSize: 16
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -152,24 +147,14 @@ class ModalBlockView extends React.Component<IModalBlockViewProps, IModalBlockVi
|
|||
headerLeft: close
|
||||
? () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item
|
||||
title={textParser([close.text])}
|
||||
style={styles.submit}
|
||||
onPress={this.cancel}
|
||||
testID='close-modal-uikit'
|
||||
/>
|
||||
<HeaderButton.Item title={textParser([close.text])} onPress={this.cancel} testID='close-modal-uikit' />
|
||||
</HeaderButton.Container>
|
||||
)
|
||||
: undefined,
|
||||
headerRight: submit
|
||||
? () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item
|
||||
title={textParser([submit.text])}
|
||||
style={styles.submit}
|
||||
onPress={this.submit}
|
||||
testID='submit-modal-uikit'
|
||||
/>
|
||||
<HeaderButton.Item title={textParser([submit.text])} onPress={this.submit} testID='submit-modal-uikit' />
|
||||
</HeaderButton.Container>
|
||||
)
|
||||
: undefined
|
||||
|
|
|
@ -48,7 +48,7 @@ interface IPickerViewProps {
|
|||
const Item = React.memo(({ item, selected, onItemPress, theme }: IItem) => (
|
||||
<List.Item
|
||||
title={I18n.t(item.label, { defaultValue: item.label, second: item?.second })}
|
||||
right={selected && (() => <List.Icon name='check' color={themes[theme].tintColor} />)}
|
||||
right={() => (selected ? <List.Icon name='check' color={themes[theme].tintColor} /> : null)}
|
||||
onPress={onItemPress}
|
||||
translateTitle={false}
|
||||
/>
|
||||
|
|
|
@ -185,7 +185,7 @@ class ScreenLockConfigView extends React.Component<IScreenLockConfigViewProps, I
|
|||
<List.Item
|
||||
title={title}
|
||||
onPress={() => this.changeAutoLockTime(value)}
|
||||
right={this.isSelected(value) ? this.renderIcon : null}
|
||||
right={() => (this.isSelected(value) ? this.renderIcon() : null)}
|
||||
disabled={disabled}
|
||||
translateTitle={false}
|
||||
/>
|
||||
|
|
|
@ -58,7 +58,11 @@ interface INavigationOption {
|
|||
}
|
||||
|
||||
interface ISearchMessagesViewProps extends INavigationOption {
|
||||
user: { id: string };
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
token: string;
|
||||
};
|
||||
baseUrl: string;
|
||||
serverVersion: string;
|
||||
customEmojis: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
|||
import { RadioButton } from 'react-native-ui-lib';
|
||||
import { RouteProp } from '@react-navigation/native';
|
||||
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import log from '../utils/log';
|
||||
import * as List from '../containers/List';
|
||||
import I18n from '../i18n';
|
||||
|
@ -17,6 +18,7 @@ import { animateNextTransition } from '../utils/layoutAnimation';
|
|||
import { ICON_SIZE } from '../containers/List/constants';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
import sharedStyles from './Styles';
|
||||
import { IRoom } from '../definitions/IRoom';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
buttonText: {
|
||||
|
@ -26,38 +28,16 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
interface IData {
|
||||
rid: string;
|
||||
name: string;
|
||||
t?: string;
|
||||
teamMain?: boolean;
|
||||
alert?: boolean;
|
||||
}
|
||||
|
||||
interface ISelectListViewState {
|
||||
data: IData[];
|
||||
dataFiltered: IData[];
|
||||
data: IRoom[];
|
||||
dataFiltered?: IRoom[];
|
||||
isSearching: boolean;
|
||||
selected: string[];
|
||||
}
|
||||
|
||||
interface ISelectListViewProps {
|
||||
navigation: StackNavigationProp<any, 'SelectListView'>;
|
||||
route: RouteProp<
|
||||
{
|
||||
SelectView: {
|
||||
data: IData[];
|
||||
title: string;
|
||||
infoText: string;
|
||||
nextAction(selected: string[]): void;
|
||||
showAlert(): void;
|
||||
isSearch: boolean;
|
||||
onSearch(text: string): IData[];
|
||||
isRadio: boolean;
|
||||
};
|
||||
},
|
||||
'SelectView'
|
||||
>;
|
||||
navigation: StackNavigationProp<ChatsStackParamList, 'SelectListView'>;
|
||||
route: RouteProp<ChatsStackParamList, 'SelectListView'>;
|
||||
theme: string;
|
||||
isMasterDetail: boolean;
|
||||
}
|
||||
|
@ -73,9 +53,9 @@ class SelectListView extends React.Component<ISelectListViewProps, ISelectListVi
|
|||
|
||||
private isSearch: boolean;
|
||||
|
||||
private onSearch: (text: string) => IData[];
|
||||
private onSearch: (text: string) => Partial<IRoom[]>;
|
||||
|
||||
private isRadio: boolean;
|
||||
private isRadio?: boolean;
|
||||
|
||||
constructor(props: ISelectListViewProps) {
|
||||
super(props);
|
||||
|
@ -142,7 +122,7 @@ class SelectListView extends React.Component<ISelectListViewProps, ISelectListVi
|
|||
search = async (text: string) => {
|
||||
try {
|
||||
this.setState({ isSearching: true });
|
||||
const result = await this.onSearch(text);
|
||||
const result = (await this.onSearch(text)) as IRoom[];
|
||||
this.setState({ dataFiltered: result });
|
||||
} catch (e) {
|
||||
log(e);
|
||||
|
@ -170,19 +150,19 @@ class SelectListView extends React.Component<ISelectListViewProps, ISelectListVi
|
|||
}
|
||||
};
|
||||
|
||||
renderItem = ({ item }: { item: IData }) => {
|
||||
renderItem = ({ item }: { item: Partial<IRoom> }) => {
|
||||
const { theme } = this.props;
|
||||
const { selected } = this.state;
|
||||
|
||||
const channelIcon = item.t === 'p' ? 'channel-private' : 'channel-public';
|
||||
const teamIcon = item.t === 'p' ? 'teams-private' : 'teams';
|
||||
const icon = item.teamMain ? teamIcon : channelIcon;
|
||||
const checked = this.isChecked(item.rid) ? 'check' : null;
|
||||
const checked = this.isChecked(item.rid!) ? 'check' : '';
|
||||
|
||||
const showRadio = () => (
|
||||
<RadioButton
|
||||
testID={selected ? `radio-button-selected-${item.name}` : `radio-button-unselected-${item.name}`}
|
||||
selected={selected.includes(item.rid)}
|
||||
selected={selected.includes(item.rid!)}
|
||||
color={themes[theme].actionTintColor}
|
||||
size={ICON_SIZE}
|
||||
/>
|
||||
|
@ -202,7 +182,7 @@ class SelectListView extends React.Component<ISelectListViewProps, ISelectListVi
|
|||
title={item.name}
|
||||
translateTitle={false}
|
||||
testID={`select-list-view-item-${item.name}`}
|
||||
onPress={() => (item.alert ? this.showAlert() : this.toggleItem(item.rid))}
|
||||
onPress={() => (item.alert ? this.showAlert() : this.toggleItem(item.rid!))}
|
||||
alert={item.alert}
|
||||
left={() => <List.Icon name={icon} color={themes[theme].controlText} />}
|
||||
right={() => (this.isRadio ? showRadio() : showCheck())}
|
||||
|
|
|
@ -11,14 +11,15 @@ import RocketChat from '../lib/rocketchat';
|
|||
import database from '../lib/database';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
import * as List from '../containers/List';
|
||||
import { ShareInsideStackParamList } from '../definitions/navigationTypes';
|
||||
|
||||
const getItemLayout = (data: any, index: number) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||
const keyExtractor = (item: IServer) => item.id;
|
||||
|
||||
interface IServer extends Model {
|
||||
id: string;
|
||||
iconURL?: string;
|
||||
name?: string;
|
||||
iconURL: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ISelectServerViewState {
|
||||
|
@ -26,7 +27,7 @@ interface ISelectServerViewState {
|
|||
}
|
||||
|
||||
interface ISelectServerViewProps {
|
||||
navigation: StackNavigationProp<any, 'SelectServerView'>;
|
||||
navigation: StackNavigationProp<ShareInsideStackParamList, 'SelectServerView'>;
|
||||
server: string;
|
||||
}
|
||||
|
||||
|
@ -40,7 +41,7 @@ class SelectServerView extends React.Component<ISelectServerViewProps, ISelectSe
|
|||
async componentDidMount() {
|
||||
const serversDB = database.servers;
|
||||
const serversCollection = serversDB.get('servers');
|
||||
const servers: IServer[] = await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch();
|
||||
const servers = (await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch()) as IServer[];
|
||||
this.setState({ servers });
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Clipboard, Linking, Share } from 'react-native';
|
|||
import { connect } from 'react-redux';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import CookieManager from '@react-native-cookies/cookies';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
|
||||
import { SettingsStackParamList } from '../../stacks/types';
|
||||
import { logout as logoutAction } from '../../actions/login';
|
||||
|
@ -48,7 +48,7 @@ interface ISettingsViewProps {
|
|||
}
|
||||
|
||||
class SettingsView extends React.Component<ISettingsViewProps, any> {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: ISettingsViewProps) => ({
|
||||
static navigationOptions = ({ navigation, isMasterDetail }: ISettingsViewProps): StackNavigationOptions => ({
|
||||
headerLeft: () =>
|
||||
isMasterDetail ? (
|
||||
<HeaderButton.CloseModal navigation={navigation} testID='settings-view-close' />
|
||||
|
@ -181,7 +181,7 @@ class SettingsView extends React.Component<ISettingsViewProps, any> {
|
|||
return (
|
||||
<SafeAreaView testID='settings-view'>
|
||||
<StatusBar />
|
||||
<List.Container testID='settings-view-list'>
|
||||
<List.Container>
|
||||
{isMasterDetail ? (
|
||||
<>
|
||||
<List.Section>
|
||||
|
|
|
@ -53,6 +53,9 @@ interface IChat {
|
|||
}
|
||||
|
||||
interface IServerInfo {
|
||||
id: string;
|
||||
iconURL: string;
|
||||
name: string;
|
||||
useRealName: boolean;
|
||||
}
|
||||
interface IState {
|
||||
|
|
|
@ -5,7 +5,7 @@ import I18n from '../../i18n';
|
|||
import { CustomIcon } from '../../lib/Icons';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import { themes } from '../../constants/colors';
|
||||
import { withTheme } from '../../theme';
|
||||
import { useTheme } from '../../theme';
|
||||
import { isAndroid, isTablet } from '../../utils/deviceInfo';
|
||||
import sharedStyles from '../Styles';
|
||||
import { makeThreadName } from '../../utils/room';
|
||||
|
@ -37,10 +37,10 @@ const styles = StyleSheet.create({
|
|||
interface IHeader {
|
||||
room: { prid?: string; t?: string };
|
||||
thread: { id?: string };
|
||||
theme: string;
|
||||
}
|
||||
|
||||
const Header = React.memo(({ room, thread, theme }: IHeader) => {
|
||||
const Header = React.memo(({ room, thread }: IHeader) => {
|
||||
const { theme } = useTheme();
|
||||
let type;
|
||||
if (thread?.id) {
|
||||
type = 'thread';
|
||||
|
@ -94,4 +94,4 @@ const Header = React.memo(({ room, thread, theme }: IHeader) => {
|
|||
);
|
||||
});
|
||||
|
||||
export default withTheme(Header);
|
||||
export default Header;
|
||||
|
|
|
@ -116,11 +116,7 @@ class ShareView extends Component<IShareViewProps, IShareViewState> {
|
|||
if (!attachments.length && !readOnly) {
|
||||
options.headerRight = () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item
|
||||
title={I18n.t('Send')}
|
||||
onPress={this.send}
|
||||
buttonStyle={[styles.send, { color: themes[theme].previewTintColor }]}
|
||||
/>
|
||||
<HeaderButton.Item title={I18n.t('Send')} onPress={this.send} />
|
||||
</HeaderButton.Container>
|
||||
);
|
||||
}
|
||||
|
@ -364,7 +360,7 @@ class ShareView extends Component<IShareViewProps, IShareViewState> {
|
|||
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<StatusBar barStyle='light-content' backgroundColor={themes[theme].previewBackground} />
|
||||
{this.renderContent()}
|
||||
<Loading visible={loading} />
|
||||
<Loading visible={loading} theme={theme} />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import styles from './styles';
|
|||
|
||||
interface SidebarItemProps {
|
||||
left: JSX.Element;
|
||||
right: JSX.Element;
|
||||
right?: JSX.Element;
|
||||
text: string;
|
||||
current: boolean;
|
||||
current?: boolean;
|
||||
onPress(): void;
|
||||
testID: string;
|
||||
theme: string;
|
||||
|
|
|
@ -45,7 +45,7 @@ interface ISidebarProps {
|
|||
name: string;
|
||||
roles: string[];
|
||||
};
|
||||
theme: string;
|
||||
theme?: string;
|
||||
loadingServer: boolean;
|
||||
useRealName: boolean;
|
||||
allowStatusMessage: boolean;
|
||||
|
@ -177,12 +177,13 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
const routeName = isMasterDetail ? 'AdminPanelView' : 'AdminPanelStackNavigator';
|
||||
return (
|
||||
<>
|
||||
<Separator theme={theme} />
|
||||
<Separator theme={theme!} />
|
||||
<SidebarItem
|
||||
text={I18n.t('Admin_Panel')}
|
||||
left={<CustomIcon name='settings' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='settings' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate(routeName)}
|
||||
testID='sidebar-admin'
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === routeName}
|
||||
/>
|
||||
</>
|
||||
|
@ -195,30 +196,34 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<>
|
||||
<SidebarItem
|
||||
text={I18n.t('Chats')}
|
||||
left={<CustomIcon name='message' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='message' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('ChatsStackNavigator')}
|
||||
testID='sidebar-chats'
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'ChatsStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Profile')}
|
||||
left={<CustomIcon name='user' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='user' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('ProfileStackNavigator')}
|
||||
testID='sidebar-profile'
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'ProfileStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Display')}
|
||||
left={<CustomIcon name='sort' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='sort' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('DisplayPrefStackNavigator')}
|
||||
testID='sidebar-display'
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'DisplayPrefStackNavigator'}
|
||||
/>
|
||||
<SidebarItem
|
||||
text={I18n.t('Settings')}
|
||||
left={<CustomIcon name='administration' size={20} color={themes[theme].titleText} />}
|
||||
left={<CustomIcon name='administration' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('SettingsStackNavigator')}
|
||||
testID='sidebar-settings'
|
||||
theme={theme!}
|
||||
current={this.currentItemKey === 'SettingsStackNavigator'}
|
||||
/>
|
||||
{this.renderAdmin()}
|
||||
|
@ -232,7 +237,8 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<SidebarItem
|
||||
text={user.statusText || I18n.t('Edit_Status')}
|
||||
left={<Status size={24} status={user?.status} />}
|
||||
right={<CustomIcon name='edit' size={20} color={themes[theme].titleText} />}
|
||||
theme={theme!}
|
||||
right={<CustomIcon name='edit' size={20} color={themes[theme!].titleText} />}
|
||||
onPress={() => this.sidebarNavigate('StatusView')}
|
||||
testID='sidebar-custom-status'
|
||||
/>
|
||||
|
@ -246,12 +252,12 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme].focusedBackground }} vertical={isMasterDetail}>
|
||||
<SafeAreaView testID='sidebar-view' style={{ backgroundColor: themes[theme!].focusedBackground }} vertical={isMasterDetail}>
|
||||
<ScrollView
|
||||
style={[
|
||||
styles.container,
|
||||
{
|
||||
backgroundColor: isMasterDetail ? themes[theme].backgroundColor : themes[theme].focusedBackground
|
||||
backgroundColor: isMasterDetail ? themes[theme!].backgroundColor : themes[theme!].focusedBackground
|
||||
}
|
||||
]}
|
||||
{...scrollPersistTaps}>
|
||||
|
@ -260,12 +266,12 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
<Avatar text={user.username} style={styles.avatar} size={30} />
|
||||
<View style={styles.headerTextContainer}>
|
||||
<View style={styles.headerUsername}>
|
||||
<Text numberOfLines={1} style={[styles.username, { color: themes[theme].titleText }]}>
|
||||
<Text numberOfLines={1} style={[styles.username, { color: themes[theme!].titleText }]}>
|
||||
{useRealName ? user.name : user.username}
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
style={[styles.currentServerText, { color: themes[theme].titleText }]}
|
||||
style={[styles.currentServerText, { color: themes[theme!].titleText }]}
|
||||
numberOfLines={1}
|
||||
accessibilityLabel={`Connected to ${baseUrl}`}>
|
||||
{Site_Name}
|
||||
|
@ -274,14 +280,14 @@ class Sidebar extends Component<ISidebarProps, ISidebarState> {
|
|||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
|
||||
<Separator theme={theme} />
|
||||
<Separator theme={theme!} />
|
||||
|
||||
{allowStatusMessage ? this.renderCustomStatus() : null}
|
||||
{!isMasterDetail ? (
|
||||
<>
|
||||
<Separator theme={theme} />
|
||||
<Separator theme={theme!} />
|
||||
{this.renderNavigation()}
|
||||
<Separator theme={theme} />
|
||||
<Separator theme={theme!} />
|
||||
</>
|
||||
) : (
|
||||
<>{this.renderAdmin()}</>
|
||||
|
|
|
@ -55,9 +55,9 @@ const styles = StyleSheet.create({
|
|||
});
|
||||
|
||||
interface IUser {
|
||||
id: string;
|
||||
status: string;
|
||||
statusText: string;
|
||||
id?: string;
|
||||
status?: string;
|
||||
statusText?: string;
|
||||
}
|
||||
|
||||
interface IStatusViewState {
|
||||
|
@ -70,7 +70,7 @@ interface IStatusViewProps {
|
|||
user: IUser;
|
||||
theme: string;
|
||||
isMasterDetail: boolean;
|
||||
setUser: (user: Partial<IUser>) => void;
|
||||
setUser: (user: IUser) => void;
|
||||
Accounts_AllowInvisibleStatusOption: boolean;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,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'
|
||||
|
|
|
@ -117,7 +117,7 @@ class ThemeView extends React.Component<IThemeViewProps> {
|
|||
title={label}
|
||||
onPress={() => this.onClick(item)}
|
||||
testID={`theme-view-${value}`}
|
||||
right={this.isSelected(item) ? this.renderIcon : null}
|
||||
right={() => (this.isSelected(item) ? this.renderIcon() : null)}
|
||||
/>
|
||||
<List.Separator />
|
||||
</>
|
||||
|
|
|
@ -24,16 +24,16 @@ const styles = StyleSheet.create({
|
|||
|
||||
interface IDropdownItem {
|
||||
text: string;
|
||||
iconName: string;
|
||||
theme: string;
|
||||
iconName: string | null;
|
||||
theme?: string;
|
||||
onPress: () => void;
|
||||
}
|
||||
|
||||
const DropdownItem = React.memo(({ theme, onPress, iconName, text }: IDropdownItem) => (
|
||||
<Touch theme={theme} onPress={onPress} style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
<Touch theme={theme!} onPress={onPress} style={{ backgroundColor: themes[theme!].backgroundColor }}>
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.text, { color: themes[theme].auxiliaryText }]}>{text}</Text>
|
||||
{iconName ? <CustomIcon name={iconName} size={22} color={themes[theme].auxiliaryText} /> : null}
|
||||
<Text style={[styles.text, { color: themes[theme!].auxiliaryText }]}>{text}</Text>
|
||||
{iconName ? <CustomIcon name={iconName} size={22} color={themes[theme!].auxiliaryText} /> : null}
|
||||
</View>
|
||||
</Touch>
|
||||
));
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import React from 'react';
|
||||
|
||||
import I18n from '../../../i18n';
|
||||
import { Filter } from '../filters';
|
||||
import DropdownItem from './DropdownItem';
|
||||
|
||||
interface IDropdownItemFilter {
|
||||
currentFilter: string;
|
||||
value: string;
|
||||
onPress: (value: string) => void;
|
||||
value: Filter;
|
||||
onPress: (value: Filter) => void;
|
||||
}
|
||||
|
||||
const DropdownItemFilter = ({ currentFilter, value, onPress }: IDropdownItemFilter): JSX.Element => (
|
||||
|
|
|
@ -14,12 +14,12 @@ import DropdownItemHeader from './DropdownItemHeader';
|
|||
const ANIMATION_DURATION = 200;
|
||||
|
||||
interface IDropdownProps {
|
||||
isMasterDetail: boolean;
|
||||
theme: string;
|
||||
insets: EdgeInsets;
|
||||
isMasterDetail?: boolean;
|
||||
theme?: string;
|
||||
insets?: EdgeInsets;
|
||||
currentFilter: Filter;
|
||||
onClose: () => void;
|
||||
onFilterSelected: (value: string) => void;
|
||||
onFilterSelected: (value: Filter) => void;
|
||||
}
|
||||
|
||||
class Dropdown extends React.Component<IDropdownProps> {
|
||||
|
@ -59,7 +59,7 @@ class Dropdown extends React.Component<IDropdownProps> {
|
|||
});
|
||||
const backdropOpacity = this.animatedValue.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, themes[theme].backdropOpacity]
|
||||
outputRange: [0, themes[theme!].backdropOpacity]
|
||||
});
|
||||
return (
|
||||
<>
|
||||
|
@ -68,7 +68,7 @@ class Dropdown extends React.Component<IDropdownProps> {
|
|||
style={[
|
||||
styles.backdrop,
|
||||
{
|
||||
backgroundColor: themes[theme].backdropColor,
|
||||
backgroundColor: themes[theme!].backdropColor,
|
||||
opacity: backdropOpacity,
|
||||
top: heightDestination
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ class Dropdown extends React.Component<IDropdownProps> {
|
|||
styles.dropdownContainer,
|
||||
{
|
||||
transform: [{ translateY }],
|
||||
backgroundColor: themes[theme].backgroundColor,
|
||||
borderColor: themes[theme].separatorColor
|
||||
backgroundColor: themes[theme!].backgroundColor,
|
||||
borderColor: themes[theme!].separatorColor
|
||||
}
|
||||
]}>
|
||||
<DropdownItemHeader currentFilter={currentFilter} onPress={this.close} />
|
||||
|
|
|
@ -59,10 +59,10 @@ const styles = StyleSheet.create({
|
|||
interface IItem {
|
||||
item: TThreadModel;
|
||||
baseUrl: string;
|
||||
theme: string;
|
||||
theme?: string;
|
||||
useRealName: boolean;
|
||||
user: any;
|
||||
badgeColor: string;
|
||||
badgeColor?: string;
|
||||
onPress: (item: TThreadModel) => void;
|
||||
toggleFollowThread: (isFollowing: boolean, id: string) => void;
|
||||
}
|
||||
|
@ -78,15 +78,15 @@ const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, to
|
|||
<Touchable
|
||||
onPress={() => onPress(item)}
|
||||
testID={`thread-messages-view-${item.msg}`}
|
||||
style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||
style={{ backgroundColor: themes[theme!].backgroundColor }}>
|
||||
<View style={styles.container}>
|
||||
<Avatar style={styles.avatar} text={item?.u?.username} size={36} borderRadius={4} theme={theme} />
|
||||
<View style={styles.contentContainer}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={[styles.title, { color: themes[theme].titleText }]} numberOfLines={1}>
|
||||
<Text style={[styles.title, { color: themes[theme!].titleText }]} numberOfLines={1}>
|
||||
{username}
|
||||
</Text>
|
||||
<Text style={[styles.time, { color: themes[theme].auxiliaryText }]}>{time}</Text>
|
||||
<Text style={[styles.time, { color: themes[theme!].auxiliaryText }]}>{time}</Text>
|
||||
</View>
|
||||
<View style={styles.messageContainer}>
|
||||
<Markdown
|
||||
|
@ -94,7 +94,7 @@ const Item = ({ item, baseUrl, theme, useRealName, user, badgeColor, onPress, to
|
|||
msg={makeThreadName(item)}
|
||||
baseUrl={baseUrl}
|
||||
username={username!}
|
||||
theme={theme}
|
||||
theme={theme!}
|
||||
numberOfLines={2}
|
||||
style={[styles.markdown]}
|
||||
preview
|
||||
|
|
|
@ -35,9 +35,9 @@ interface IWorkSpaceProp {
|
|||
}
|
||||
|
||||
class WorkspaceView extends React.Component<IWorkSpaceProp, any> {
|
||||
static navigationOptions: StackNavigationOptions = {
|
||||
static navigationOptions = (): StackNavigationOptions => ({
|
||||
title: I18n.t('Your_workspace')
|
||||
};
|
||||
});
|
||||
|
||||
get showRegistrationButton() {
|
||||
const { registrationForm, inviteLinkToken, Accounts_iframe_enabled } = this.props;
|
||||
|
|
Loading…
Reference in New Issue