Merge branch 'improvement.typescript-migration' into improvement.eslint-change-to-ts

This commit is contained in:
AlexAlexandre 2021-08-18 10:59:27 -03:00
commit 7cf55c1f3b
134 changed files with 28209 additions and 29311 deletions

View File

@ -3,7 +3,8 @@ defaults: &defaults
macos: &macos
macos:
xcode: "12.5.0"
xcode: "12.5.0"
resource_class: large
bash-env: &bash-env
BASH_ENV: "~/.nvm/nvm.sh"
@ -143,15 +144,6 @@ commands:
fi
working_directory: android/app
- run:
name: Config variables
command: |
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY_OFFICIAL' };" > ./config.js
else
echo -e "export default { BUGSNAG_API_KEY: '$BUGSNAG_KEY' };" > ./config.js
fi
- run:
name: Build App
command: |
@ -170,22 +162,20 @@ commands:
name: Upload sourcemaps to Bugsnag
command: |
if [[ $CIRCLE_JOB == "android-build-official" ]]; then
yarn generate-source-maps-android upload \
npx bugsnag-source-maps upload-react-native \
--api-key=$BUGSNAG_KEY_OFFICIAL \
--app-version=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/officialPlay/release/app.bundle \
--app-version-code=$CIRCLE_BUILD_NUM \
--platform android \
--source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \
--minified-url=app.bundle \
--upload-sources
--bundle android/app/build/generated/assets/react/officialPlay/release/app.bundle
fi
if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then
yarn generate-source-maps-android upload \
npx bugsnag-source-maps upload-react-native \
--api-key=$BUGSNAG_KEY \
--app-version=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/experimentalPlay/release/app.bundle \
--app-version-code=$CIRCLE_BUILD_NUM \
--platform android \
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \
--minified-url=app.bundle \
--upload-sources
--bundle android/app/build/generated/assets/react/experimentalPlay/release/app.bundle
fi
- store_artifacts:
@ -216,41 +206,20 @@ commands:
echo $GOOGLE_SERVICES_IOS | base64 --decode > GoogleService-Info.plist
fi
working_directory: ios
- run:
name: Upload sourcemaps to Bugsnag
command: |
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
yarn generate-source-maps-ios
curl https://upload.bugsnag.com/react-native-source-map \
-F apiKey=$BUGSNAG_KEY_OFFICIAL \
-F appBundleVersion=$CIRCLE_BUILD_NUM \
-F dev=false \
-F platform=ios \
-F sourceMap=@ios-release.bundle.map \
-F bundle=@ios-release.bundle
fi
if [[ $CIRCLE_JOB == "ios-build-experimental" ]]; then
yarn generate-source-maps-ios
curl https://upload.bugsnag.com/react-native-source-map \
-F apiKey=$BUGSNAG_KEY \
-F appBundleVersion=$CIRCLE_BUILD_NUM \
-F dev=false \
-F platform=ios \
-F sourceMap=@ios-release.bundle.map \
-F bundle=@ios-release.bundle
fi
- run:
name: Fastlane Build
no_output_timeout: 40m
command: |
agvtool new-version -all $CIRCLE_BUILD_NUM
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY_OFFICIAL" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY_OFFICIAL" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./NotificationService/Info.plist
else
/usr/libexec/PlistBuddy -c "Set BugsnagAPIKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set :bugsnag:apiKey $BUGSNAG_KEY" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./NotificationService/Info.plist

5
__mocks__/@bugsnag/react-native.js vendored Normal file
View File

@ -0,0 +1,5 @@
export default {
start: () => '',
leaveBreadcrumb: () => '',
notify: () => ''
};

View File

@ -1,8 +0,0 @@
export class Client { }
export default {
bugsnag: () => '',
leaveBreadcrumb: () => '',
notify: () => '',
loggerConfig: () => ''
};

View File

@ -4693,7 +4693,7 @@ exports[`Storyshots List pressable 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -6211,7 +6211,7 @@ exports[`Storyshots List with bigger font 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 69,
},
@ -6625,7 +6625,7 @@ exports[`Storyshots List with bigger font 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 69,
},
@ -7080,7 +7080,7 @@ exports[`Storyshots List with black theme 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -7494,7 +7494,7 @@ exports[`Storyshots List with black theme 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -7972,7 +7972,7 @@ exports[`Storyshots List with custom colors 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -8129,7 +8129,7 @@ exports[`Storyshots List with dark theme 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -8543,7 +8543,7 @@ exports[`Storyshots List with dark theme 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 92,
},
@ -10410,7 +10410,7 @@ exports[`Storyshots List with small font 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 36.800000000000004,
},
@ -10824,7 +10824,7 @@ exports[`Storyshots List with small font 1`] = `
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
undefined,
Object {
"height": 36.800000000000004,
},

View File

@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer
versionName "4.18.0"
versionName "4.19.0"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]

View File

@ -8,8 +8,15 @@ import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.JsIOHelper;
import com.wix.reactnativenotifications.core.notification.INotificationsApplication;
import com.wix.reactnativenotifications.core.notification.IPushNotification;
import com.bugsnag.android.Bugsnag;
public class MainPlayApplication extends MainApplication implements INotificationsApplication {
@Override
public void onCreate() {
super.onCreate();
Bugsnag.start(this);
}
@Override
public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) {
return new CustomPushNotification(

View File

@ -25,7 +25,7 @@ import * as List from '../List';
import I18n from '../../i18n';
import { useOrientation, useDimensions, IDimensionsContextProps } from '../../dimensions';
type TActionSheetData = {
interface IActionSheetData {
options: any;
headerHeight?: number;
hasCancel?: boolean;
@ -48,7 +48,7 @@ const ANIMATION_CONFIG = {
const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.Element; theme: string}, ref) => {
const bottomSheetRef: any = useRef();
const [data, setData] = useState<TActionSheetData>({} as TActionSheetData);
const [data, setData] = useState<IActionSheetData>({} as IActionSheetData);
const [isVisible, setVisible] = useState(false);
const { height }: Partial<IDimensionsContextProps> = useDimensions();
const { isLandscape } = useOrientation();

View File

@ -2,10 +2,12 @@ import React from 'react';
import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-native';
import { themes } from '../constants/colors';
type TTheme = 'light' | 'dark' | 'black' | string;
interface IActivityIndicator extends ActivityIndicatorProps{
theme?: 'light' | 'dark' | 'black' | string,
absolute?: boolean,
props?: object
theme?: TTheme;
absolute?: boolean;
props?: object;
}
const styles = StyleSheet.create({

View File

@ -6,39 +6,12 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk';
import { avatarURL } from '../../utils/avatar';
import Emoji from '../markdown/Emoji';
export interface IAvatar {
server?: string;
style?: any,
text?: string;
avatar?: string;
emoji?: string;
size?: number;
borderRadius?: number;
type?: string;
children?: JSX.Element;
user?: {
id: string;
token: string;
};
theme: string;
onPress?(): void;
getCustomEmoji(): any;
avatarETag?: string;
isStatic?: boolean;
rid?: string;
blockUnauthenticatedAccess?: boolean;
serverVersion?: string;
}
import {IAvatar} from './interfaces';
const Avatar = React.memo(({
text,
size,
server,
borderRadius,
style,
style,
avatar,
type,
children,
user,
onPress,
@ -49,8 +22,13 @@ const Avatar = React.memo(({
isStatic,
rid,
blockUnauthenticatedAccess,
serverVersion
serverVersion,
text,
size = 25,
borderRadius = 4,
type = 'd',
}: Partial<IAvatar>) => {
if ((!text && !avatar && !emoji && !rid) || !server) {
return null;
}

View File

@ -4,12 +4,19 @@ import { Q } from '@nozbe/watermelondb';
import database from '../../lib/database';
import { getUserSelector } from '../../selectors/login';
import Avatar, {IAvatar} from './Avatar';
import Avatar from './Avatar';
import {IAvatar} from "./interfaces";
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
private mounted: boolean;
private subscription!: any;
static defaultProps = {
text: '',
type: 'd'
};
constructor(props: Partial<IAvatar>) {
super(props);
this.mounted = false;

View File

@ -0,0 +1,23 @@
export interface IAvatar {
server: string;
style: any,
text: string;
avatar: string;
emoji: string;
size: number;
borderRadius: number;
type: string;
children: JSX.Element;
user: {
id: string;
token: string;
};
theme: string;
onPress(): void;
getCustomEmoji(): any;
avatarETag: string;
isStatic: boolean;
rid: string;
blockUnauthenticatedAccess: boolean;
serverVersion: string;
}

View File

@ -24,7 +24,7 @@ stories.add('long text', () => (
<BackgroundContainer text={longText} />
));
const ThemeStory = ({ theme, ...props }: any) => (
const ThemeStory = ({ theme, ...props }) => (
<ThemeContext.Provider
value={{ theme }}
>

View File

@ -40,6 +40,14 @@ const styles = StyleSheet.create({
export default class Button extends React.PureComponent<Partial<IButtonProps>, any> {
static defaultProps = {
title: 'Press me!',
type: 'primary',
onPress: () => alert('It works!'),
disabled: false,
loading: false
}
render() {
const {
title, type, onPress, disabled, backgroundColor, color, loading, style, theme, fontSize, ...otherProps

View File

@ -4,9 +4,9 @@ import { StyleSheet } from 'react-native';
import { CustomIcon } from '../lib/Icons';
import { themes } from '../constants/colors';
type TCheck = {
style?: object,
theme: string
interface ICheck {
style?: object;
theme: string;
}
const styles = StyleSheet.create({
icon: {
@ -16,6 +16,6 @@ const styles = StyleSheet.create({
}
});
const Check = React.memo(({ theme, style }: TCheck) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);
const Check = React.memo(({ theme, style }: ICheck) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);
export default Check;

View File

@ -1,12 +1,6 @@
import React from 'react';
import FastImage from '@rocket.chat/react-native-fast-image';
import {TEmoji} from "./index";
interface ICustomEmoji {
baseUrl: string,
emoji: TEmoji,
style: any
}
import {ICustomEmoji} from "./interfaces";
const CustomEmoji = React.memo(({ baseUrl, emoji, style }: ICustomEmoji) => (
<FastImage

View File

@ -5,20 +5,11 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
import styles from './styles';
import CustomEmoji from './CustomEmoji';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import {IEmoji, IEmojiCategory} from "./interfaces";
const EMOJI_SIZE: number = 50;
const EMOJI_SIZE = 50;
interface IEmoji {
baseUrl: string;
emojis: any;
onEmojiSelected({}: any): void;
emojisPerRow: number;
width: number;
style: any;
tabLabel: string;
}
const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
const renderEmoji = (emoji: IEmoji, size: number, baseUrl: string) => {
if (emoji && emoji.isCustom) {
return <CustomEmoji style={[styles.customCategoryEmoji, { height: size - 16, width: size - 16 }]} emoji={emoji} baseUrl={baseUrl} />;
}
@ -29,7 +20,7 @@ const renderEmoji = (emoji: any, size: number, baseUrl: string) => {
);
};
class EmojiCategory extends React.Component<Partial<IEmoji>> {
class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
renderItem(emoji: any) {
const { baseUrl, onEmojiSelected } = this.props;

View File

@ -3,7 +3,7 @@ import { View, TouchableOpacity, Text } from 'react-native';
import styles from './styles';
import { themes } from '../../constants/colors';
interface ITabBar {
interface ITabBarProps {
goToPage({}): void;
activeTab: number,
tabs: [],
@ -11,7 +11,7 @@ interface ITabBar {
theme: string
}
export default class TabBar extends React.Component<Partial<ITabBar>> {
export default class TabBar extends React.Component<Partial<ITabBarProps>> {
shouldComponentUpdate(nextProps: any) {
const { activeTab, theme } = this.props;

View File

@ -17,18 +17,22 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
import log from '../../utils/log';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import {IEmoji} from "../markdown/Emoji";
import {IEmoji} from "./interfaces";
const scrollProps = {
keyboardShouldPersistTaps: 'always',
keyboardDismissMode: 'none'
};
export type TEmoji = {
content: any;
name: string;
extension: any;
isCustom: boolean;
interface IEmojiPickerProps {
isMessageContainsOnlyEmoji: boolean;
getCustomEmoji?: Function;
baseUrl: string;
customEmojis?: any;
style: object;
theme?: string;
onEmojiSelected?: Function;
tabEmojiStyle?: object;
}
interface IEmojiPickerState {
@ -38,9 +42,9 @@ interface IEmojiPickerState {
width: number | null;
}
class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
constructor(props: IEmoji) {
constructor(props: IEmojiPickerProps) {
super(props);
const customEmojis = Object.keys(props.customEmojis)
.filter(item => item === props.customEmojis[item].name)
@ -80,7 +84,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
return false;
}
onEmojiSelected = (emoji: TEmoji) => {
onEmojiSelected = (emoji: IEmoji) => {
try {
const { onEmojiSelected } = this.props;
if (emoji.isCustom) {
@ -100,7 +104,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
}
// eslint-disable-next-line react/sort-comp
_addFrequentlyUsed = protectedFunction(async(emoji: TEmoji) => {
_addFrequentlyUsed = protectedFunction(async(emoji: IEmoji) => {
const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojiRecord: any;
@ -129,7 +133,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
const db = database.active;
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
frequentlyUsed = frequentlyUsed.map((item: TEmoji) => {
frequentlyUsed = frequentlyUsed.map((item: IEmoji) => {
if (item.isCustom) {
return { content: item.content, extension: item.extension, isCustom: item.isCustom };
}
@ -192,7 +196,7 @@ class EmojiPicker extends Component<IEmoji, IEmojiPickerState> {
}
}
const mapStateToProps = (state: IEmojiPickerState) => ({
const mapStateToProps = (state: any) => ({
customEmojis: state.customEmojis
});

View File

@ -0,0 +1,22 @@
export interface IEmoji {
content: any;
name: string;
extension: any;
isCustom: boolean;
}
export interface ICustomEmoji {
baseUrl: string,
emoji: IEmoji,
style: any
}
export interface IEmojiCategory {
baseUrl: string;
emojis: IEmoji[];
onEmojiSelected({}: any): void;
emojisPerRow: number;
width: number;
style: any;
tabLabel: string;
}

View File

@ -29,6 +29,7 @@ export const FormContainerInner = ({ children }: {children: JSX.Element}) => (
);
const FormContainer = ({ children, theme, testID, ...props }: IFormContainer) => (
// @ts-ignore
<KeyboardView
style={{ backgroundColor: themes[theme].backgroundColor }}
contentContainerStyle={sharedStyles.container}

View File

@ -20,7 +20,7 @@ export const getHeaderHeight = (isLandscape: boolean) => {
return 56;
};
type THeaderTitlePosition = {
interface IHeaderTitlePosition {
insets: {
left: number;
right: number;
@ -28,7 +28,7 @@ type THeaderTitlePosition = {
numIconsRight: number;
}
export const getHeaderTitlePosition = ({ insets, numIconsRight }: THeaderTitlePosition) => ({
export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
left: insets.left + 60,
right: insets.right + Math.max(45 * numIconsRight, 15)
});

View File

@ -20,7 +20,7 @@ const styles = StyleSheet.create({
}
});
const Container = ({ children, left }: IHeaderButtonContainer) => (
const Container = ({ children, left = false }: IHeaderButtonContainer) => (
<View style={[styles.container, left ? styles.left : styles.right]}>
{children}
</View>

View File

@ -9,10 +9,10 @@ const styles = StyleSheet.create({
}
});
type TListContainer = {
interface IListContainer {
children: JSX.Element;
}
const ListContainer = React.memo(({ children, ...props }: TListContainer) => (
const ListContainer = React.memo(({ children, ...props }: IListContainer) => (
// @ts-ignore
<ScrollView
contentContainerStyle={styles.container}

View File

@ -10,12 +10,12 @@ const styles = StyleSheet.create({
}
});
type TListSeparator = {
interface IListSeparator {
style: object;
theme: string;
}
const ListSeparator = React.memo(({ style, theme }: TListSeparator) => (
const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
<View
style={[
styles.separator,

View File

@ -1,12 +1,13 @@
import React from 'react';
import { StyleSheet, View, Modal, Animated } from 'react-native';
import { StyleSheet, Modal, Animated , View } from 'react-native';
import { withTheme } from '../theme';
import { themes } from '../constants/colors';
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.25)'
justifyContent: 'center'
},
image: {
width: 100,
@ -17,9 +18,10 @@ const styles = StyleSheet.create({
interface ILoadingProps {
visible: boolean;
theme: string;
}
export default class Loading extends React.PureComponent<ILoadingProps, any> {
class Loading extends React.PureComponent<ILoadingProps, any> {
state = {
scale: new Animated.Value(1),
@ -36,7 +38,7 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
opacity,
{
toValue: 1,
duration: 1000,
duration: 200,
useNativeDriver: true
}
);
@ -91,23 +93,40 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
render() {
const { opacity, scale } = this.state;
const { visible } = this.props;
const { visible, theme } = this.props;
const scaleAnimation = scale.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 1.1, 1]
});
const opacityAnimation = opacity.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity],
extrapolate: 'clamp'
});
return (
<Modal
visible={visible}
transparent
onRequestClose={() => {}}
>
<View style={styles.container} testID='loading'>
<View
style={styles.container}
testID='loading'
>
<Animated.View
style={[{
// @ts-ignore
...StyleSheet.absoluteFill,
backgroundColor: themes[theme].backdropColor,
opacity: opacityAnimation
}]}
/>
<Animated.Image
source={require('../static/images/logo.png')}
style={[styles.image, {
opacity,
transform: [{
scale: scaleAnimation
}]
@ -118,3 +137,5 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
);
}
}
export default (withTheme(Loading));

View File

@ -57,19 +57,19 @@ const styles = StyleSheet.create({
}
});
type TOpenOAuth = {
interface IOpenOAuth {
url?: string;
ssoToken?: string;
authType?: string;
}
type TService = {
interface IService {
name: string;
service: string;
authType: string;
buttonColor: string;
buttonLabelColor: string;
};
}
interface ILoginServicesProps {
navigation: any;
@ -93,6 +93,10 @@ interface ILoginServicesProps {
class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
private _animation: any;
static defaultProps = {
separator: true
}
state = {
collapsed: true,
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
@ -251,7 +255,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
return Base64.encodeURI(JSON.stringify(obj));
}
openOAuth = ({ url, ssoToken, authType = 'oauth' }: TOpenOAuth) => {
openOAuth = ({ url, ssoToken, authType = 'oauth' }: IOpenOAuth) => {
const { navigation } = this.props;
navigation.navigate('AuthenticationWebView', { url, authType, ssoToken });
}
@ -322,7 +326,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
return null;
}
renderItem = (service: TService) => {
renderItem = (service: IService) => {
const { CAS_enabled, theme } = this.props;
let { name } = service;
name = name === 'meteor-developer' ? 'meteor' : name;

View File

@ -10,7 +10,7 @@ import database from '../../lib/database';
import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions';
import sharedStyles from '../../views/Styles';
import {TEmoji} from "../EmojiPicker";
import {IEmoji} from "../EmojiPicker/interfaces";
interface IHeader {
handleReaction: Function;
@ -21,7 +21,7 @@ interface IHeader {
}
interface THeaderItem {
item: TEmoji;
item: IEmoji;
onReaction: Function;
server: string;
theme: string;
@ -118,7 +118,7 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
setEmojis();
}, []);
const onReaction = ({ emoji }: {emoji: TEmoji}) => handleReaction(emoji, message);
const onReaction = ({ emoji }: {emoji: IEmoji}) => handleReaction(emoji, message);
const renderItem = useCallback(({ item }) => <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme} />, []);

View File

@ -11,6 +11,7 @@ import { withTheme } from '../../theme';
interface IMessageBoxEmojiKeyboard {
theme: string
}
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
private readonly baseUrl: any;

View File

@ -6,10 +6,10 @@ import shortnameToUnicode from '../../../utils/shortnameToUnicode';
import styles from '../styles';
import MessageboxContext from '../Context';
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
import {TEmoji} from "../../EmojiPicker";
import {IEmoji} from "../../EmojiPicker/interfaces";
interface IMessageBoxMentionEmoji {
item: TEmoji;
item: IEmoji;
}
const MentionEmoji = ({ item }: IMessageBoxMentionEmoji) => {

View File

@ -8,7 +8,7 @@ import FixedMentionItem from './FixedMentionItem';
import MentionEmoji from './MentionEmoji';
import { MENTIONS_TRACKING_TYPE_EMOJIS, MENTIONS_TRACKING_TYPE_COMMANDS } from '../constants';
import { themes } from '../../../constants/colors';
import {TEmoji} from "../../EmojiPicker";
import {IEmoji} from "../../EmojiPicker/interfaces";
interface IMessageBoxMentionItem {
item: {
@ -17,7 +17,7 @@ interface IMessageBoxMentionItem {
username: string;
t: string;
id: string;
} & TEmoji;
} & IEmoji;
trackingType: string;
theme: string;
}

View File

@ -11,6 +11,7 @@ interface IMessageBoxMentions {
trackingType: string;
theme: string;
}
const Mentions = React.memo(({ mentions, trackingType, theme }: IMessageBoxMentions) => {
if (!trackingType) {
return null;

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { View, Alert, Keyboard, Text } from 'react-native';
import {View, Alert, Keyboard, Text, NativeModules} from 'react-native';
import { connect } from 'react-redux';
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
import ImagePicker from 'react-native-image-crop-picker';
@ -111,6 +111,7 @@ interface IMessageBoxProps {
sharing: boolean;
isActionsEnabled: boolean;
}
interface IMessageBoxState {
mentions: any[];
showEmojiKeyboard: boolean;
@ -143,6 +144,16 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
private component: any;
private typingTimeout: any;
static defaultProps = {
message: {
id: ''
},
sharing: false,
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
isActionsEnabled: true,
getCustomEmoji: () => {}
}
constructor(props: IMessageBoxProps) {
super(props);
this.state = {
@ -958,6 +969,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
//@ts-ignore
style={[styles.textBoxInput, { color: themes[theme].bodyText }]}
returnKeyType='default'
//@ts-ignore
keyboardType='twitter'
blurOnSubmit={false}
placeholder={I18n.t('New_Message')}

View File

@ -11,18 +11,18 @@ import Title from './Title';
import Subtitle from './Subtitle';
import LockIcon from './LockIcon';
type TPasscodeTimer = {
interface IPasscodeTimer {
time: string;
theme: string;
setStatus: Function;
};
}
interface IPasscodeLocked {
theme: string;
setStatus: Function;
}
const Timer = React.memo(({ time, theme, setStatus }: TPasscodeTimer) => {
const Timer = React.memo(({ time, theme, setStatus }: IPasscodeTimer) => {
const calcTimeLeft = () => {
const diff = getDiff(time);
if (diff > 0) {
@ -62,6 +62,8 @@ const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
}, []);
return (
//TODO - verify if this 'r' it's correct
// @ts-ignore
<Grid style={[styles.grid, { backgroundColor: themes[theme].passcodeBackground }]} r>
<LockIcon theme={theme} />
<Title text={I18n.t('Passcode_app_locked_title')} theme={theme} />

View File

@ -92,6 +92,7 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
}
return (
// @ts-ignore
<Base
ref={ref}
theme={theme}

View File

@ -59,7 +59,7 @@ const styles = StyleSheet.create({
const standardEmojiStyle = { fontSize: 20 };
const customEmojiStyle = { width: 20, height: 20 };
type TItem = {
interface IItem {
item: {
usernames: any;
emoji: string;
@ -68,15 +68,15 @@ type TItem = {
baseUrl?: string;
getCustomEmoji?: Function;
theme?: string;
};
}
type TModalContent = {
interface IModalContent {
message: {
reactions: any
};
onClose: Function;
theme: string;
};
}
interface IReactionsModal {
isVisible: boolean;
@ -84,7 +84,7 @@ interface IReactionsModal {
theme: string;
}
const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: TItem) => {
const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: IItem) => {
const count = item.usernames.length;
let usernames = item.usernames.slice(0, 3)
.map((username: any) => (username === user?.username ? I18n.t('you') : username)).join(', ');
@ -114,7 +114,7 @@ const Item = React.memo(({ item, user, baseUrl, getCustomEmoji, theme }: TItem)
);
});
const ModalContent = React.memo(({ message, onClose, ...props }: TModalContent) => {
const ModalContent = React.memo(({ message, onClose, ...props }: IModalContent) => {
if (message && message.reactions) {
return (
<SafeAreaView style={styles.safeArea}>

View File

@ -11,7 +11,7 @@ import { ThemeContext } from '../../theme';
const stories = storiesOf('RoomHeader', module);
// TODO: refactor after react-navigation v6
const HeaderExample = ({ title }: any) => (
const HeaderExample = ({ title }) => (
<Header
headerTitle={() => (
<View style={{ flex: 1, paddingHorizontal: 12 }}>
@ -77,7 +77,7 @@ stories.add('thread', () => (
</>
));
const ThemeStory = ({ theme }: any) => (
const ThemeStory = ({ theme }) => (
<ThemeContext.Provider
value={{ theme }}
>

View File

@ -141,7 +141,7 @@ const HeaderTitle = React.memo(({ title, tmid, prid, scale, theme, testID }: TRo
});
const Header = React.memo(({
title, subtitle, parentTitle, type, status, usersTyping, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID
title, subtitle, parentTitle, type, status, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID, usersTyping = []
}: IRoomHeader) => {
const portrait = height > width;
let scale = 1;

View File

@ -22,7 +22,7 @@ interface IRoomTypeIcon {
}
const RoomTypeIcon = React.memo(({
type, size, isGroupChat, status, style, theme, teamMain
type, isGroupChat, status, style, theme, teamMain, size = 16
}: IRoomTypeIcon) => {
if (!type) {
return null;

View File

@ -8,7 +8,7 @@ interface IStatus {
style: any;
}
const Status = React.memo(({ status, size, style, ...props }: IStatus) => {
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
const name = `status-${ status }`;
const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';

View File

@ -72,6 +72,11 @@ interface IRCTextInputProps {
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, any> {
static defaultProps = {
error: {},
theme: 'light'
}
state = {
showPassword: false
}
@ -167,6 +172,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
inputStyle
]}
ref={inputRef}
/*@ts-ignore*/
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'

View File

@ -43,7 +43,7 @@ const methods: any = {
const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
const [visible, setVisible] = useState(false);
const [data, setData] = useState<any>({});
const [code, setCode] = useState('');
const [code, setCode] = useState<any>('');
const method = methods[data.method];
const isEmail = data.method === 'email';
@ -102,6 +102,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
<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}
<TextInput
/*@ts-ignore*/
value={code}
theme={theme}
inputRef={(e: any) => InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}

View File

@ -15,19 +15,19 @@ const styles = StyleSheet.create({
}
});
type TThumb = {
interface IThumb {
element: {
imageUrl: string;
};
size?: number;
};
}
type TMedia = {
interface IMedia {
element: {
imageUrl: string;
};
theme: string;
};
}
interface IImage {
element: any;
@ -37,14 +37,14 @@ interface IImage {
const ThumbContext = (args: any) => <View style={styles.mediaContext}><Thumb size={20} {...args} /></View>;
export const Thumb = ({ element, size = 88 }: TThumb) => (
export const Thumb = ({ element, size = 88 }: IThumb) => (
<FastImage
style={[{ width: size, height: size }, styles.image]}
source={{ uri: element.imageUrl }}
/>
);
export const Media = ({ element, theme }: TMedia) => {
export const Media = ({ element, theme }: IMedia) => {
const showAttachment = (attachment: any) => Navigation.navigate('AttachmentView', { attachment });
const { imageUrl } = element;

View File

@ -9,7 +9,7 @@ import { CustomIcon } from '../../../lib/Icons';
import styles from './styles';
type TChip = {
interface IChip {
item: {
value: string;
imageUrl: string;
@ -30,7 +30,7 @@ interface IChips {
const keyExtractor = (item: any) => item.value.toString();
const Chip = ({ item, onSelect, style, theme }: TChip) => (
const Chip = ({ item, onSelect, style, theme }: IChip) => (
<Touchable
key={item.value}
onPress={() => onSelect(item)}

View File

@ -10,7 +10,7 @@ import { themes } from '../../../constants/colors';
import styles from './styles';
type TItem = {
interface IItem {
item: {
value: { name: string; };
text: { text: string; };
@ -19,7 +19,7 @@ type TItem = {
selected: any;
onSelect: Function;
theme: string;
};
}
interface IItems {
items: [];
@ -31,7 +31,7 @@ interface IItems {
const keyExtractor = (item: any) => item.value.toString();
// RectButton doesn't work on modal (Android)
const Item = ({ item, selected, onSelect, theme }: TItem) => {
const Item = ({ item, selected, onSelect, theme }: IItem) => {
const itemName = item.value.name || item.text.text.toLowerCase();
return (
<Touchable

View File

@ -54,7 +54,7 @@ export const MultiSelect = React.memo(({
value: values,
multiselect = false,
onSearch,
onClose,
onClose = () => {},
disabled,
inputStyle,
theme
@ -129,6 +129,7 @@ export const MultiSelect = React.memo(({
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
<TextInput
testID='multi-select-search'
/*@ts-ignore*/
onChangeText={onSearch || onSearchChange}
placeholder={I18n.t('Search')}
theme={theme}

View File

@ -2,7 +2,7 @@ import { StyleSheet } from 'react-native';
import sharedStyles from '../../../views/Styles';
export default StyleSheet.create({
export default StyleSheet.create<any>({
container: {
flex: 1,
alignItems: 'center',

View File

@ -9,7 +9,7 @@ import { themes } from '../../constants/colors';
import { BUTTON_HIT_SLOP } from '../message/utils';
import * as List from '../List';
type TOption = {
interface IOption {
option: {
text: string;
value: string;
@ -17,14 +17,14 @@ type TOption = {
onOptionPress: Function;
parser: any;
theme: string;
};
}
type TOptions = {
interface IOptions {
options: [];
onOptionPress: Function;
parser: object;
theme: string;
};
}
interface IOverflow {
element: any;
@ -50,7 +50,7 @@ const styles = StyleSheet.create({
}
});
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOption) => (
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: IOption) => (
<Touchable
onPress={() => onOptionPress({ value })}
background={Touchable.Ripple(themes[theme].bannerBackground)}
@ -60,7 +60,7 @@ const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOpti
</Touchable>
);
const Options = ({ options, onOptionPress, parser, theme }: TOptions) => (
const Options = ({ options, onOptionPress, parser, theme }: IOptions) => (
<FlatList
data={options}
renderItem={({ item }) => <Option option={item} onOptionPress={onOptionPress} parser={parser} theme={theme} />}

View File

@ -23,14 +23,14 @@ const styles = StyleSheet.create({
}
});
type TAccessory = {
interface IAccessory {
blockId?: string;
appId?: string;
element: any;
parser: any
}
type TFields = {
interface IFields {
fields: any;
parser: any;
theme: string;
@ -46,13 +46,13 @@ interface ISection {
parser: any;
}
const Accessory = ({ blockId, appId, element, parser }: TAccessory) => parser.renderAccessories(
const Accessory = ({ blockId, appId, element, parser }: IAccessory) => parser.renderAccessories(
{ blockId, appId, ...element },
BLOCK_CONTEXT.SECTION,
parser
);
const Fields = ({ fields, parser, theme }: TFields) => fields.map((field: any) => (
const Fields = ({ fields, parser, theme }: IFields) => fields.map((field: any) => (
<Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>
{parser.text(field)}
</Text>

View File

@ -225,6 +225,7 @@ class ModalParser extends UiKitParserModal {
const { theme } = useContext(ThemeContext);
const { multiline, actionId, placeholder } = element;
return (
// @ts-ignore
<TextInput
id={actionId}
placeholder={plainText(placeholder)}
@ -235,6 +236,7 @@ class ModalParser extends UiKitParserModal {
inputStyle={multiline && styles.multiline}
containerStyle={styles.input}
value={value}
// @ts-ignore
error={{ error }}
theme={theme}
/>

View File

@ -7,7 +7,7 @@ import { themes } from '../../constants/colors';
import styles from './styles';
export interface IEmoji {
interface IEmoji {
literal: string;
isMessageContainsOnlyEmoji: boolean;
getCustomEmoji?: Function;

View File

@ -5,17 +5,15 @@ import { themes } from '../../constants/colors';
import styles from './styles';
export type TChannel = {
name: string;
_id: number;
}
interface IHashtag {
hashtag: string;
navToRoomInfo: Function;
style: [];
theme: string;
channels: TChannel[];
channels: {
name: string;
_id: number;
}[];
}
const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [], theme }: IHashtag) => {

View File

@ -8,7 +8,7 @@ interface IList {
numberOfLines: number;
}
const List = React.memo(({ children, ordered, start = 1, tight, numberOfLines = 0 }: IList) => {
const List = React.memo(({ children, ordered, tight, start = 1, numberOfLines = 0 }: IList) => {
let bulletWidth = 15;
if (ordered) {

View File

@ -12,7 +12,7 @@ import MarkdownLink from './Link';
import MarkdownList from './List';
import MarkdownListItem from './ListItem';
import MarkdownAtMention from './AtMention';
import MarkdownHashtag, {TChannel} from './Hashtag';
import MarkdownHashtag from './Hashtag';
import MarkdownBlockQuote from './BlockQuote';
import MarkdownEmoji from './Emoji';
import MarkdownTable from './Table';
@ -33,7 +33,10 @@ interface IMarkdownProps {
numberOfLines: number;
customEmojis: boolean;
useRealName: boolean;
channels: TChannel[];
channels: {
name: string;
_id: number;
}[];
mentions: object[];
navToRoomInfo: Function;
preview: boolean;

View File

@ -1,19 +1,13 @@
import React from 'react';
import { dequal } from 'dequal';
import {IMessageAttachments} from "./interfaces";
import Image from './Image';
import Audio from './Audio';
import Video from './Video';
import Reply from './Reply';
export interface IMessageAttachments {
attachments: any;
timeFormat: string;
showAttachment: Function;
getCustomEmoji: Function;
theme: string;
}
const Attachments = React.memo(({
attachments, timeFormat, showAttachment, getCustomEmoji, theme
}: IMessageAttachments) => {

View File

@ -16,12 +16,12 @@ import MessageContext from './Context';
import ActivityIndicator from '../ActivityIndicator';
import { withDimensions } from '../../dimensions';
type TButton = {
interface IButton {
loading: boolean;
paused: boolean;
theme: string;
onPress: Function;
};
}
interface IMessageAudioProps {
file: {
@ -88,7 +88,7 @@ const sliderAnimationConfig = {
delay: 0
};
const Button = React.memo(({ loading, paused, onPress, theme }: TButton) => (
const Button = React.memo(({ loading, paused, onPress, theme }: IButton) => (
<Touchable
style={styles.playPauseButton}
onPress={onPress}

View File

@ -1,12 +1,6 @@
import React from 'react';
import { messageBlockWithContext } from '../UIKit/MessageBlock';
export interface IMessageBlocks {
blocks: any;
id: string;
rid: string;
blockAction: Function;
}
import {IMessageBlocks} from "./interfaces";
const Blocks = React.memo(({ blocks, id: mid, rid, blockAction }: IMessageBlocks) => {
if (blocks && blocks.length > 0) {

View File

@ -8,14 +8,7 @@ import { BUTTON_HIT_SLOP } from './utils';
import I18n from '../../i18n';
import { themes } from '../../constants/colors';
import MessageContext from './Context';
export interface IMessageBroadcast {
author: {
_id: string
};
broadcast: boolean;
theme: string
}
import {IMessageBroadcast} from "./interfaces";
const Broadcast = React.memo(({ author, broadcast, theme }: IMessageBroadcast) => {
const { user, replyBroadcast } = useContext(MessageContext);

View File

@ -7,11 +7,7 @@ import styles from './styles';
import I18n from '../../i18n';
import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors';
export interface IMessageCallButton {
theme: string;
callJitsi: Function;
}
import {IMessageCallButton} from "./interfaces";
const CallButton = React.memo(({ theme, callJitsi }: IMessageCallButton) => (
<View style={styles.buttonContainer}>

View File

@ -11,25 +11,7 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context';
import Encrypted from './Encrypted';
import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants';
import {TChannel} from "../markdown/Hashtag";
export interface IMessageContent {
isTemp: boolean;
isInfo: boolean;
tmid: string;
isThreadRoom: boolean;
msg: string;
theme: string;
isEdited: boolean;
isEncrypted: boolean;
getCustomEmoji: Function;
channels: TChannel[];
mentions: object[];
navToRoomInfo: Function;
useRealName: boolean;
isIgnored: boolean;
type: string;
}
import {IMessageContent} from "./interfaces";
const Content = React.memo((props: IMessageContent) => {
if (props.isInfo) {

View File

@ -10,13 +10,8 @@ import { DISCUSSION } from './constants';
import { themes } from '../../constants/colors';
import MessageContext from './Context';
import { formatDateThreads } from '../../utils/room';
import {IMessageDiscussion} from "./interfaces";
export interface IMessageDiscussion {
msg: string;
dcount: number;
dlm: string;
theme: string;
}
const Discussion = React.memo(({ msg, dcount, dlm, theme }: IMessageDiscussion) => {
let time;

View File

@ -3,14 +3,7 @@ import { Text } from 'react-native';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
import CustomEmoji from '../EmojiPicker/CustomEmoji';
interface IMessageEmoji {
content: any;
baseUrl: string;
standardEmojiStyle: object;
customEmojiStyle: object;
getCustomEmoji: Function;
}
import {IMessageEmoji} from "./interfaces";
const Emoji = React.memo(({ content, baseUrl, standardEmojiStyle, customEmojiStyle, getCustomEmoji }: IMessageEmoji) => {
const parsedContent = content.replace(/^:|:$/g, '');

View File

@ -69,7 +69,6 @@ const ImageContainer = React.memo(({file, imageUrl, showAttachment, getCustomEmo
<Button theme={theme} onPress={onPress}>
<View>
<MessageImage img={img} theme={theme} />
//TODO - fix the required fields for the Markdown
{/*@ts-ignore*/}
<Markdown msg={file.description} baseUrl={baseUrl} username={user.username} getCustomEmoji={getCustomEmoji} theme={theme} />
</View>

View File

@ -6,59 +6,22 @@ import MessageContext from './Context';
import User from './User';
import styles from './styles';
import RepliedThread, {IMessageRepliedThread} from './RepliedThread';
import MessageAvatar, {IMessageAvatar} from './MessageAvatar';
import Attachments, {IMessageAttachments} from './Attachments';
import RepliedThread from './RepliedThread';
import MessageAvatar from './MessageAvatar';
import Attachments from './Attachments';
import Urls from './Urls';
import Thread, {IMessageThread} from './Thread';
import Blocks, {IMessageBlocks} from './Blocks';
import Thread from './Thread';
import Blocks from './Blocks';
import Reactions from './Reactions';
import Broadcast, {IMessageBroadcast} from './Broadcast';
import Discussion, {IMessageDiscussion} from './Discussion';
import Content, {IMessageContent} from './Content';
import Broadcast from './Broadcast';
import Discussion from './Discussion';
import Content from './Content';
import ReadReceipt from './ReadReceipt';
import CallButton, {IMessageCallButton} from './CallButton';
import CallButton from './CallButton';
import { themes } from '../../constants/colors';
import {IMessage, IMessageInner, IMessageTouchable} from "./interfaces";
type TMessageInner = {
type: string;
blocks: [];
} & IMessageDiscussion & IMessageContent & IMessageCallButton & IMessageBlocks
& IMessageThread & IMessageAttachments & IMessageBroadcast;
type TMessage = {
isThreadReply: boolean;
isThreadSequential: boolean;
isInfo: boolean;
isTemp: boolean;
isHeader: boolean;
hasError: boolean;
style: any;
onLongPress: Function;
isReadReceiptEnabled: boolean;
unread: boolean;
theme: string;
isIgnored: boolean;
} & IMessageRepliedThread & IMessageAvatar & IMessageContent & TMessageInner;
interface IMessageTouchable {
hasError: boolean;
isInfo: boolean;
isThreadReply: boolean;
isTemp: boolean;
archived: boolean;
highlighted: boolean;
theme: string;
ts?: any
urls?: any;
reactions?: any;
alias?: any;
role?: any;
drid?: any;
}
const MessageInner = React.memo((props: TMessageInner) => {
const MessageInner = React.memo((props: IMessageInner) => {
if (props.type === 'discussion-created') {
return (
<>
@ -100,7 +63,7 @@ const MessageInner = React.memo((props: TMessageInner) => {
});
MessageInner.displayName = 'MessageInner';
const Message = React.memo((props: TMessage) => {
const Message = React.memo((props: IMessage) => {
if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) {
const thread = props.isThreadReply ? <RepliedThread {...props} /> : null;
return (
@ -144,7 +107,7 @@ const Message = React.memo((props: TMessage) => {
});
Message.displayName = 'Message';
const MessageTouchable = React.memo((props: IMessageTouchable & TMessage) => {
const MessageTouchable = React.memo((props: IMessageTouchable & IMessage) => {
if (props.hasError) {
return (
<View>

View File

@ -3,20 +3,7 @@ import React, { useContext } from 'react';
import Avatar from '../Avatar';
import styles from './styles';
import MessageContext from './Context';
export interface IMessageAvatar {
isHeader: boolean;
avatar: string;
emoji: string;
author: {
username: string
_id: string;
};
small?: boolean;
navToRoomInfo: Function;
getCustomEmoji(): void;
theme: string;
}
import {IMessageAvatar} from "./interfaces";
const MessageAvatar = React.memo(({
isHeader, avatar, author, small, navToRoomInfo, emoji, getCustomEmoji, theme

View File

@ -10,18 +10,18 @@ import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import MessageContext from './Context';
type TMessageAddReaction = {
interface IMessageAddReaction {
theme: string
};
}
type TMessageReaction = {
interface IMessageReaction {
reaction: {
usernames: [];
emoji: object;
};
getCustomEmoji: Function;
theme: string;
};
}
interface IMessageReactions {
reactions: object[];
@ -29,7 +29,7 @@ interface IMessageReactions {
theme: string;
}
const AddReaction = React.memo(({ theme }: TMessageAddReaction) => {
const AddReaction = React.memo(({ theme }: IMessageAddReaction) => {
const { reactionInit } = useContext(MessageContext);
return (
<Touchable
@ -47,9 +47,9 @@ const AddReaction = React.memo(({ theme }: TMessageAddReaction) => {
);
});
const Reaction = React.memo(({reaction, getCustomEmoji, theme}: TMessageReaction) => {
const Reaction = React.memo(({reaction, getCustomEmoji, theme}: IMessageReaction) => {
const { onReactionPress, onReactionLongPress, baseUrl, user } = useContext(MessageContext);
const reacted = reaction.usernames.findIndex((item: TMessageReaction) => item === user.username) !== -1;
const reacted = reaction.usernames.findIndex((item: IMessageReaction) => item === user.username) !== -1;
return (
<Touchable
onPress={() => onReactionPress(reaction.emoji)}

View File

@ -6,16 +6,7 @@ import styles from './styles';
import { themes } from '../../constants/colors';
import I18n from '../../i18n';
import Markdown from '../markdown';
export interface IMessageRepliedThread {
tmid: string;
tmsg: string;
id: string;
isHeader: boolean;
theme: string;
fetchThreadName: Function;
isEncrypted: boolean;
}
import {IMessageRepliedThread} from "./interfaces";
const RepliedThread = memo(({
tmid, tmsg, isHeader, fetchThreadName, id, isEncrypted, theme

View File

@ -68,7 +68,7 @@ const styles = StyleSheet.create({
}
});
type TAttachment = {
interface IMessageReplyAttachment {
author_name: string;
message_link: string;
ts: string;
@ -81,36 +81,36 @@ type TAttachment = {
type: string;
color: string;
description: string;
fields: TAttachment[];
fields: IMessageReplyAttachment[];
}
type TMessageTitle = {
attachment: Partial<TAttachment>
interface IMessageTitle {
attachment: Partial<IMessageReplyAttachment>
timeFormat: string;
theme: string;
};
}
type TMessageDescription = {
attachment: Partial<TAttachment>
interface IMessageDescription {
attachment: Partial<IMessageReplyAttachment>
getCustomEmoji: Function;
theme: string;
};
}
type TMessageFields = {
attachment: Partial<TAttachment>;
interface IMessageFields {
attachment: Partial<IMessageReplyAttachment>;
theme: string;
getCustomEmoji: Function;
};
}
interface IMessageReply {
attachment: Partial<TAttachment>
attachment: Partial<IMessageReplyAttachment>
timeFormat: string;
index: number;
theme: string;
getCustomEmoji: Function;
}
const Title = React.memo(({ attachment, timeFormat, theme }: TMessageTitle) => {
const Title = React.memo(({ attachment, timeFormat, theme }: IMessageTitle) => {
if (!attachment.author_name) {
return null;
}
@ -123,7 +123,7 @@ const Title = React.memo(({ attachment, timeFormat, theme }: TMessageTitle) => {
);
});
const Description = React.memo(({ attachment, getCustomEmoji, theme }: TMessageDescription) => {
const Description = React.memo(({ attachment, getCustomEmoji, theme }: IMessageDescription) => {
const text = attachment.text || attachment.title;
if (!text) {
return null;
@ -152,7 +152,7 @@ const Description = React.memo(({ attachment, getCustomEmoji, theme }: TMessageD
return true;
});
const Fields = React.memo(({ attachment, theme, getCustomEmoji }: TMessageFields) => {
const Fields = React.memo(({ attachment, theme, getCustomEmoji }: IMessageFields) => {
if (!attachment.fields) {
return null;
}

View File

@ -6,15 +6,7 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context';
import ThreadDetails from '../ThreadDetails';
import I18n from '../../i18n';
export interface IMessageThread {
msg: string;
tcount: number;
theme: string;
tlm: string;
isThreadRoom: boolean;
id: string;
}
import {IMessageThread} from "./interfaces";
const Thread = React.memo(({ msg, tcount, tlm, isThreadRoom, theme, id }: IMessageThread) => {
if (!tlm || isThreadRoom || tcount === 0) {

View File

@ -49,13 +49,13 @@ const styles = StyleSheet.create({
}
});
type TMessageUrlContent = {
interface IMessageUrlContent {
title: string;
description: string;
theme: string;
};
}
type TMessageUrl = {
interface IMessageUrl {
url: {
ignoreParse: boolean;
url: string;
@ -65,7 +65,7 @@ type TMessageUrl = {
};
index: number;
theme: string;
};
}
interface IMessageUrls {
urls: any;
@ -81,7 +81,7 @@ const UrlImage = React.memo(({ image }: {image: string}) => {
return <FastImage source={{ uri: image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} />;
}, (prevProps, nextProps) => prevProps.image === nextProps.image);
const UrlContent = React.memo(({ title, description, theme }: TMessageUrlContent) => (
const UrlContent = React.memo(({ title, description, theme }: IMessageUrlContent) => (
<View style={styles.textContainer}>
{title ? <Text style={[styles.title, { color: themes[theme].tintColor }]} numberOfLines={2}>{title}</Text> : null}
{description ? <Text style={[styles.description, { color: themes[theme].auxiliaryText }]} numberOfLines={2}>{description}</Text> : null}
@ -99,7 +99,7 @@ const UrlContent = React.memo(({ title, description, theme }: TMessageUrlContent
return true;
});
const Url = React.memo(({ url, index, theme }: TMessageUrl) => {
const Url = React.memo(({ url, index, theme }: IMessageUrl) => {
if (!url || url?.ignoreParse) {
return null;
}

View File

@ -64,6 +64,28 @@ interface IMessageContainerProps {
class MessageContainer extends React.Component<IMessageContainerProps, any> {
static defaultProps = {
getCustomEmoji: () => {},
onLongPress: () => {},
onReactionPress: () => {},
onEncryptedPress: () => {},
onDiscussionPress: () => {},
onThreadPress: () => {},
errorActionsShow: () => {},
replyBroadcast: () => {},
reactionInit: () => {},
fetchThreadName: () => {},
showAttachment: () => {},
onReactionLongPress: () => {},
navToRoomInfo: () => {},
callJitsi: () => {},
blockAction: () => {},
archived: false,
broadcast: false,
isIgnored: false,
theme: 'light'
}
state = { isManualUnignored: false };
private subscription: any;

View File

@ -0,0 +1,133 @@
export interface IMessageAttachments {
attachments: any;
timeFormat: string;
showAttachment: Function;
getCustomEmoji: Function;
theme: string;
}
export interface IMessageAvatar {
isHeader: boolean;
avatar: string;
emoji: string;
author: {
username: string
_id: string;
};
small?: boolean;
navToRoomInfo: Function;
getCustomEmoji(): void;
theme: string;
}
export interface IMessageBlocks {
blocks: any;
id: string;
rid: string;
blockAction: Function;
}
export interface IMessageBroadcast {
author: {
_id: string
};
broadcast: boolean;
theme: string
}
export interface IMessageCallButton {
theme: string;
callJitsi: Function;
}
export interface IMessageContent {
isTemp: boolean;
isInfo: boolean;
tmid: string;
isThreadRoom: boolean;
msg: string;
theme: string;
isEdited: boolean;
isEncrypted: boolean;
getCustomEmoji: Function;
channels: {
name: string;
_id: number;
}[];
mentions: object[];
navToRoomInfo: Function;
useRealName: boolean;
isIgnored: boolean;
type: string;
}
export interface IMessageDiscussion {
msg: string;
dcount: number;
dlm: string;
theme: string;
}
export interface IMessageEmoji {
content: any;
baseUrl: string;
standardEmojiStyle: object;
customEmojiStyle: object;
getCustomEmoji: Function;
}
export interface IMessageThread {
msg: string;
tcount: number;
theme: string;
tlm: string;
isThreadRoom: boolean;
id: string;
}
export interface IMessageTouchable {
hasError: boolean;
isInfo: boolean;
isThreadReply: boolean;
isTemp: boolean;
archived: boolean;
highlighted: boolean;
theme: string;
ts?: any
urls?: any;
reactions?: any;
alias?: any;
role?: any;
drid?: any;
}
export interface IMessageRepliedThread {
tmid: string;
tmsg: string;
id: string;
isHeader: boolean;
theme: string;
fetchThreadName: Function;
isEncrypted: boolean;
}
export interface IMessageInner extends IMessageDiscussion, IMessageContent, IMessageCallButton, IMessageBlocks,
IMessageThread, IMessageAttachments, IMessageBroadcast {
type: string;
blocks: [];
}
export interface IMessage extends IMessageRepliedThread, IMessageInner {
isThreadReply: boolean;
isThreadSequential: boolean;
isInfo: boolean;
isTemp: boolean;
isHeader: boolean;
hasError: boolean;
style: any;
onLongPress: Function;
isReadReceiptEnabled: boolean;
unread: boolean;
theme: string;
isIgnored: boolean;
}

View File

@ -761,5 +761,12 @@
"Move_to_Team_Warning": "Nachdem du die vorherigen Anleitungen zu diesem Verhalten gelesen hast, möchtest du diesen Kanal immer noch in das ausgewählte Team verschieben?",
"Load_More": "Mehr laden",
"Load_Newer": "Neuere laden",
"Load_Older": "Ältere laden"
"Load_Older": "Ältere laden",
"Left_The_Room_Successfully": "Raum erfolgreich verlassen",
"Deleted_The_Team_Successfully": "Team erfolgreich gelöscht",
"Deleted_The_Room_Successfully": "Raum erfolgreich gelöscht",
"Convert_to_Channel": "In Kanal umwandeln",
"Converting_Team_To_Channel": "Team in Kanal umwandeln",
"Select_Team_Channels_To_Delete": "Wähle die Kanäle des Teams aus, die du löschen möchtest. Die Kanäle, die du nicht auswählst, werden in den Arbeitsbereich verschoben \n\nBeachte, dass öffentliche Kanäle öffentlich und für alle sichtbar sind.",
"You_are_converting_the_team": "Du wandelst dieses Team in einen Raum um"
}

View File

@ -761,5 +761,12 @@
"Move_to_Team_Warning": "После прочтения предыдущих инструкций об этом поведении, вы все еще хотите переместить этот канал в выбранную Команду?",
"Load_More": "Загрузить еще",
"Load_Newer": "Загрузить более позднее",
"Load_Older": "Загрузить более раннее"
"Load_Older": "Загрузить более раннее",
"Left_The_Room_Successfully": "Успешно покинул комнату",
"Deleted_The_Team_Successfully": "Команда успешно удалена",
"Deleted_The_Room_Successfully": "Комната успешно удалена",
"Convert_to_Channel": "Преобразовать в канал",
"Converting_Team_To_Channel": "Преобразование Команды в канал",
"Select_Team_Channels_To_Delete": "Выберите каналы Команды, которые вы хотите удалить, те, которые вы не выбрали, будут перемещены в рабочую область \n\nОбратите внимание, что публичные каналы будут открытыми и видимыми для всех.",
"You_are_converting_the_team": "Вы преобразуете эту Команду в канал"
}

View File

@ -33,12 +33,13 @@ import { isFDroidBuild } from './constants/environment';
RNScreens.enableScreens();
type TDimensions = {
interface IDimensions {
width: number,
height: number,
scale: number,
fontScale: number
}
interface IProps {}
interface IState {
theme: string,
@ -163,7 +164,7 @@ export default class Root extends React.Component<IProps, IState> {
window: {
width, height, scale, fontScale
}
}: {window: TDimensions}) => {
}: {window: IDimensions}) => {
this.setDimensions({
width, height, scale, fontScale
});
@ -179,7 +180,7 @@ export default class Root extends React.Component<IProps, IState> {
});
}
setDimensions = ({width, height, scale, fontScale}: TDimensions) => {
setDimensions = ({width, height, scale, fontScale}: IDimensions) => {
this.setState({width, height, scale, fontScale});
}

View File

@ -1,6 +1,5 @@
import React from 'react';
import { Text, View } from 'react-native';
import PropTypes from 'prop-types';
import Touch from '../../utils/touch';
import Avatar from '../../containers/Avatar';
@ -10,7 +9,26 @@ import { themes } from '../../constants/colors';
export { ROW_HEIGHT };
const DirectoryItemLabel = React.memo(({ text, theme }) => {
interface IDirectoryItemLabel {
text: string;
theme: string;
}
interface IDirectoryItem {
title: string;
description: string;
avatar: string;
type: string;
onPress(): void;
testID: string;
style: any;
rightLabel: string;
rid: string;
theme: string;
teamMain: boolean;
}
const DirectoryItemLabel = React.memo(({ text, theme }: IDirectoryItemLabel) => {
if (!text) {
return null;
}
@ -19,7 +37,7 @@ const DirectoryItemLabel = React.memo(({ text, theme }) => {
const DirectoryItem = ({
title, description, avatar, onPress, testID, style, rightLabel, type, rid, theme, teamMain
}) => (
}: IDirectoryItem) => (
<Touch
onPress={onPress}
style={{ backgroundColor: themes[theme].backgroundColor }}
@ -46,23 +64,4 @@ const DirectoryItem = ({
</Touch>
);
DirectoryItem.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string,
avatar: PropTypes.string,
type: PropTypes.string,
onPress: PropTypes.func.isRequired,
testID: PropTypes.string.isRequired,
style: PropTypes.any,
rightLabel: PropTypes.string,
rid: PropTypes.string,
theme: PropTypes.string,
teamMain: PropTypes.bool
};
DirectoryItemLabel.propTypes = {
text: PropTypes.string,
theme: PropTypes.string
};
export default DirectoryItem;

View File

@ -1,6 +1,6 @@
import { types } from './types';
export const ImageComponent = (type) => {
export const ImageComponent = (type: string) => {
let Component;
if (type === types.REACT_NATIVE_IMAGE) {
const { Image } = require('react-native');

View File

@ -1,11 +1,6 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import PropTypes from 'prop-types';
import {
PanGestureHandler,
State,
PinchGestureHandler
} from 'react-native-gesture-handler';
import { PanGestureHandler, State, PinchGestureHandler } from 'react-native-gesture-handler';
import Animated, { Easing } from 'react-native-reanimated';
import { ImageComponent } from './ImageComponent';
import { themes } from '../../constants/colors';
@ -44,13 +39,13 @@ const {
event
} = Animated;
function scaleDiff(value) {
function scaleDiff(value: any) {
const tmp = new Value(1);
const prev = new Value(1);
return [set(tmp, divide(value, prev)), set(prev, value), tmp];
}
function dragDiff(value, updating) {
function dragDiff(value: any, updating: any) {
const tmp = new Value(0);
const prev = new Value(0);
return cond(
@ -63,7 +58,7 @@ function dragDiff(value, updating) {
// returns linear friction coeff. When `value` is 0 coeff is 1 (no friction), then
// it grows linearly until it reaches `MAX_FRICTION` when `value` is equal
// to `MAX_VALUE`
function friction(value) {
function friction(value: any) {
const MAX_FRICTION = 5;
const MAX_VALUE = 100;
return max(
@ -72,7 +67,7 @@ function friction(value) {
);
}
function speed(value) {
function speed(value: any) {
const clock = new Clock();
const dt = diff(clock);
return cond(lessThan(dt, 1), 0, multiply(1000, divide(diff(value), dt)));
@ -81,7 +76,7 @@ function speed(value) {
const MIN_SCALE = 1;
const MAX_SCALE = 2;
function scaleRest(value) {
function scaleRest(value: any) {
return cond(
lessThan(value, MIN_SCALE),
MIN_SCALE,
@ -89,7 +84,7 @@ function scaleRest(value) {
);
}
function scaleFriction(value, rest, delta) {
function scaleFriction(value: any, rest: any, delta: any) {
const MAX_FRICTION = 20;
const MAX_VALUE = 0.5;
const res = multiply(value, delta);
@ -105,7 +100,7 @@ function scaleFriction(value, rest, delta) {
);
}
function runTiming(clock, value, dest, startStopClock = true) {
function runTiming(clock: any, value: any, dest: any, startStopClock: any = true) {
const state = {
finished: new Value(0),
position: new Value(0),
@ -134,7 +129,7 @@ function runTiming(clock, value, dest, startStopClock = true) {
];
}
function runDecay(clock, value, velocity) {
function runDecay(clock: any, value: any, velocity: any) {
const state = {
finished: new Value(0),
velocity: new Value(0),
@ -160,13 +155,13 @@ function runDecay(clock, value, velocity) {
}
function bouncyPinch(
value,
gesture,
gestureActive,
focalX,
displacementX,
focalY,
displacementY
value: any,
gesture: any,
gestureActive: any,
focalX: any,
displacementX: any,
focalY: any,
displacementY: any
) {
const clock = new Clock();
@ -212,12 +207,12 @@ function bouncyPinch(
}
function bouncy(
value,
gestureDiv,
gestureActive,
lowerBound,
upperBound,
f
value: any,
gestureDiv: any,
gestureActive: any,
lowerBound: any,
upperBound: any,
f: any
) {
const timingClock = new Clock();
const decayClock = new Clock();
@ -260,13 +255,14 @@ function bouncy(
const WIDTH = 300;
const HEIGHT = 300;
class Image extends React.PureComponent {
static propTypes = {
imageComponentType: PropTypes.string
}
interface IImageProps {
imageComponentType: string
}
class Image extends React.PureComponent<IImageProps, any> {
render() {
const { imageComponentType } = this.props;
const { imageComponentType }: any = this.props;
const Component = ImageComponent(imageComponentType);
@ -277,16 +273,25 @@ const AnimatedImage = Animated.createAnimatedComponent(Image);
// it was picked from https://github.com/software-mansion/react-native-reanimated/tree/master/Example/imageViewer
// and changed to use FastImage animated component
export class ImageViewer extends React.Component {
static propTypes = {
uri: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
theme: PropTypes.string,
imageComponentType: PropTypes.string
}
constructor(props) {
interface IImageViewerProps {
uri: string;
width: number;
height: number;
theme: string;
imageComponentType: string;
}
export class ImageViewer extends React.Component<IImageViewerProps, any> {
private _onPinchEvent: any;
private _focalDisplacementX: any;
private _focalDisplacementY: any;
private _scale: any;
private _onPanEvent: any;
private _panTransX: any;
private _panTransY: any;
constructor(props: IImageViewerProps) {
super(props);
// DECLARE TRANSX
@ -351,7 +356,7 @@ export class ImageViewer extends React.Component {
]);
const panActive = eq(panState, State.ACTIVE);
const panFriction = value => friction(value);
const panFriction = (value: any) => friction(value);
// X
const panUpX = cond(

View File

@ -1,6 +1,5 @@
import React from 'react';
import { ScrollView, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { ImageComponent } from './ImageComponent';
import { themes } from '../../constants/colors';
@ -15,12 +14,21 @@ const styles = StyleSheet.create({
}
});
interface IImageViewer {
uri: string;
imageComponentType: string;
width: number;
height: number;
theme: string;
}
export const ImageViewer = ({
uri, imageComponentType, theme, width, height, ...props
}) => {
}: IImageViewer) => {
const backgroundColor = themes[theme].previewBackground;
const Component = ImageComponent(imageComponentType);
return (
// @ts-ignore
<ScrollView
style={{ backgroundColor }}
contentContainerStyle={[
@ -41,11 +49,3 @@ export const ImageViewer = ({
</ScrollView>
);
};
ImageViewer.propTypes = {
uri: PropTypes.string,
imageComponentType: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
theme: PropTypes.string
};

View File

@ -1,19 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
import scrollPersistTaps from '../utils/scrollPersistTaps';
export default class KeyboardView extends React.PureComponent {
static propTypes = {
style: PropTypes.any,
contentContainerStyle: PropTypes.any,
keyboardVerticalOffset: PropTypes.number,
scrollEnabled: PropTypes.bool,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
}
interface IKeyboardViewProps {
style: any,
contentContainerStyle: any,
keyboardVerticalOffset: number,
scrollEnabled: boolean,
children: JSX.Element;
}
export default class KeyboardView extends React.PureComponent<IKeyboardViewProps, any> {
render() {
const {
@ -28,6 +25,7 @@ export default class KeyboardView extends React.PureComponent {
scrollEnabled={scrollEnabled}
alwaysBounceVertical={false}
extraHeight={keyboardVerticalOffset}
// @ts-ignore
behavior='position'
>
{children}

View File

@ -1,18 +1,34 @@
import React from 'react';
import { Animated, View, Text } from 'react-native';
import { RectButton } from 'react-native-gesture-handler';
import PropTypes from 'prop-types';
import I18n, { isRTL } from '../../i18n';
import styles, { ACTION_WIDTH, LONG_SWIPE } from './styles';
import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors';
interface ILeftActions {
theme: string;
transX: any;
isRead: boolean;
width: number;
onToggleReadPress(): void;
}
interface IRightActions {
theme: string;
transX: any;
favorite: boolean;
width: number;
toggleFav(): void;
onHidePress(): void;
}
const reverse = new Animated.Value(isRTL() ? -1 : 1);
export const LeftActions = React.memo(({
theme, transX, isRead, width, onToggleReadPress
}) => {
}: ILeftActions) => {
const translateX = Animated.multiply(
transX.interpolate({
inputRange: [0, ACTION_WIDTH],
@ -51,7 +67,7 @@ export const LeftActions = React.memo(({
export const RightActions = React.memo(({
transX, favorite, width, toggleFav, onHidePress, theme
}) => {
}: IRightActions) => {
const translateXFav = Animated.multiply(
transX.interpolate({
inputRange: [-width / 2, -ACTION_WIDTH * 2, 0],
@ -113,20 +129,3 @@ export const RightActions = React.memo(({
</View>
);
});
LeftActions.propTypes = {
theme: PropTypes.string,
transX: PropTypes.object,
isRead: PropTypes.bool,
width: PropTypes.number,
onToggleReadPress: PropTypes.func
};
RightActions.propTypes = {
theme: PropTypes.string,
transX: PropTypes.object,
favorite: PropTypes.bool,
width: PropTypes.number,
toggleFav: PropTypes.func,
onHidePress: PropTypes.func
};

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { dequal } from 'dequal';
import I18n from '../../i18n';
@ -8,9 +7,27 @@ import Markdown from '../../containers/markdown';
import { themes } from '../../constants/colors';
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/encryption/constants';
interface ILastMessage {
theme: string;
lastMessage: {
u: any;
pinned: boolean;
t: string;
attachments: any;
msg: string;
e2e: string;
};
type: string;
showLastMessage: boolean;
username: string;
useRealName: boolean;
alert: boolean;
}
const formatMsg = ({
lastMessage, type, showLastMessage, username, useRealName
}) => {
}: Partial<ILastMessage>) => {
if (!showLastMessage) {
return '';
}
@ -45,11 +62,12 @@ const formatMsg = ({
return `${ prefix }${ lastMessage.msg }`;
};
const arePropsEqual = (oldProps, newProps) => dequal(oldProps, newProps);
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
const LastMessage = React.memo(({
lastMessage, type, showLastMessage, username, alert, useRealName, theme
}) => (
}: ILastMessage) => (
// @ts-ignore
<Markdown
msg={formatMsg({
lastMessage, type, showLastMessage, username, useRealName
@ -63,14 +81,4 @@ const LastMessage = React.memo(({
/>
), arePropsEqual);
LastMessage.propTypes = {
theme: PropTypes.string,
lastMessage: PropTypes.object,
type: PropTypes.string,
showLastMessage: PropTypes.bool,
username: PropTypes.string,
useRealName: PropTypes.bool,
alert: PropTypes.bool
};
export default LastMessage;

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native';
import styles from './styles';
@ -13,6 +12,53 @@ import Touchable from './Touchable';
import Tag from './Tag';
import I18n from '../../i18n';
interface IRoomItem {
rid: string;
type: string;
prid: string;
name: string;
avatar: string;
showLastMessage: boolean;
username: string;
avatarSize: number;
testID: string;
width: number;
status: string;
useRealName: boolean;
theme: string;
isFocused: boolean;
isGroupChat: boolean;
isRead: boolean;
teamMain: boolean;
date: string;
accessibilityLabel: string;
lastMessage: {
u: any;
pinned: boolean;
t: string;
attachments: any;
msg: string;
e2e: string;
};
favorite: boolean;
alert: boolean;
hideUnreadStatus: boolean;
unread: number;
userMentions: number;
groupMentions: number;
tunread: [];
tunreadUser: [];
tunreadGroup: [];
swipeEnabled: boolean;
toggleFav(): void;
toggleRead(): void;
onPress(): void;
onLongPress(): void;
hideChannel(): void;
autoJoin: boolean;
size?: number;
}
const RoomItem = ({
rid,
type,
@ -20,10 +66,10 @@ const RoomItem = ({
name,
avatar,
width,
avatarSize,
avatarSize = 48,
username,
showLastMessage,
status,
status = 'offline',
useRealName,
theme,
isFocused,
@ -42,7 +88,7 @@ const RoomItem = ({
tunreadUser,
tunreadGroup,
testID,
swipeEnabled,
swipeEnabled = true,
onPress,
onLongPress,
toggleFav,
@ -50,7 +96,7 @@ const RoomItem = ({
hideChannel,
teamMain,
autoJoin
}) => (
}: IRoomItem) => (
<Touchable
onPress={onPress}
onLongPress={onLongPress}
@ -158,49 +204,4 @@ const RoomItem = ({
</Touchable>
);
RoomItem.propTypes = {
rid: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
prid: PropTypes.string,
name: PropTypes.string.isRequired,
avatar: PropTypes.string.isRequired,
showLastMessage: PropTypes.bool,
username: PropTypes.string,
avatarSize: PropTypes.number,
testID: PropTypes.string,
width: PropTypes.number,
status: PropTypes.string,
useRealName: PropTypes.bool,
theme: PropTypes.string,
isFocused: PropTypes.bool,
isGroupChat: PropTypes.bool,
isRead: PropTypes.bool,
teamMain: PropTypes.bool,
date: PropTypes.string,
accessibilityLabel: PropTypes.string,
lastMessage: PropTypes.object,
favorite: PropTypes.bool,
alert: PropTypes.bool,
hideUnreadStatus: PropTypes.bool,
unread: PropTypes.number,
userMentions: PropTypes.number,
groupMentions: PropTypes.number,
tunread: PropTypes.array,
tunreadUser: PropTypes.array,
tunreadGroup: PropTypes.array,
swipeEnabled: PropTypes.bool,
toggleFav: PropTypes.func,
toggleRead: PropTypes.func,
onPress: PropTypes.func,
onLongPress: PropTypes.func,
hideChannel: PropTypes.func,
autoJoin: PropTypes.bool
};
RoomItem.defaultProps = {
avatarSize: 48,
status: 'offline',
swipeEnabled: true
};
export default RoomItem;

View File

@ -1,13 +1,17 @@
import React from 'react';
import { Text, View } from 'react-native';
import PropTypes from 'prop-types';
import { themes } from '../../constants/colors';
import { useTheme } from '../../theme';
import styles from './styles';
const Tag = React.memo(({ name, testID }) => {
const { theme } = useTheme();
interface ITag {
name: string;
testID?: string;
}
const Tag = React.memo(({ name, testID }: ITag) => {
const { theme }: any = useTheme();
return (
<View style={[styles.tagContainer, { backgroundColor: themes[theme].borderColor }]}>
@ -24,9 +28,4 @@ const Tag = React.memo(({ name, testID }) => {
);
});
Tag.propTypes = {
name: PropTypes.string,
testID: PropTypes.string
};
export default Tag;

View File

@ -1,13 +1,17 @@
import React from 'react';
import { Text } from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
const Title = React.memo(({
name, theme, hideUnreadStatus, alert
}) => (
interface ITitle {
name: string;
theme: string;
hideUnreadStatus: boolean;
alert: boolean;
}
const Title = React.memo(({ name, theme, hideUnreadStatus, alert }: ITitle) => (
<Text
style={[
styles.title,
@ -21,11 +25,4 @@ const Title = React.memo(({
</Text>
));
Title.propTypes = {
name: PropTypes.string,
theme: PropTypes.string,
hideUnreadStatus: PropTypes.bool,
alert: PropTypes.bool
};
export default Title;

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Animated } from 'react-native';
import {
LongPressGestureHandler, PanGestureHandler, State
@ -15,26 +14,34 @@ import { isRTL } from '../../i18n';
import { themes } from '../../constants/colors';
import { LeftActions, RightActions } from './Actions';
class Touchable extends React.Component {
static propTypes = {
type: PropTypes.string.isRequired,
onPress: PropTypes.func,
onLongPress: PropTypes.func,
testID: PropTypes.string,
width: PropTypes.number,
favorite: PropTypes.bool,
isRead: PropTypes.bool,
rid: PropTypes.string,
toggleFav: PropTypes.func,
toggleRead: PropTypes.func,
hideChannel: PropTypes.func,
children: PropTypes.element,
theme: PropTypes.string,
isFocused: PropTypes.bool,
swipeEnabled: PropTypes.bool
}
interface ITouchableProps {
children: JSX.Element;
type: string;
onPress(): void;
onLongPress(): void;
testID: string;
width: number;
favorite: boolean;
isRead: boolean;
rid: string;
toggleFav: Function;
toggleRead: Function;
hideChannel: Function;
theme: string;
isFocused: boolean;
swipeEnabled: boolean;
}
constructor(props) {
class Touchable extends React.Component<ITouchableProps, any> {
private dragX: Animated.Value;
private rowOffSet: Animated.Value;
private reverse: Animated.Value;
private transX: Animated.AnimatedAddition;
private transXReverse: Animated.AnimatedMultiplication;
private _onGestureEvent: (...args: any[]) => void;
private _value: number;
constructor(props: ITouchableProps) {
super(props);
this.dragX = new Animated.Value(0);
this.rowOffSet = new Animated.Value(0);
@ -56,20 +63,20 @@ class Touchable extends React.Component {
this._value = 0;
}
_onHandlerStateChange = ({ nativeEvent }) => {
_onHandlerStateChange = ({ nativeEvent }: any) => {
if (nativeEvent.oldState === State.ACTIVE) {
this._handleRelease(nativeEvent);
}
}
onLongPressHandlerStateChange = ({ nativeEvent }) => {
onLongPressHandlerStateChange = ({ nativeEvent }: any) => {
if (nativeEvent.state === State.ACTIVE) {
this.onLongPress();
}
}
_handleRelease = (nativeEvent) => {
_handleRelease = (nativeEvent: any) => {
const { translationX } = nativeEvent;
const { rowState } = this.state;
this._value += translationX;
@ -152,7 +159,7 @@ class Touchable extends React.Component {
this._animateRow(toValue);
}
_animateRow = (toValue) => {
_animateRow = (toValue: any) => {
this.rowOffSet.setValue(this._value);
this._value = toValue;
this.dragX.setValue(0);

View File

@ -1,18 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
const TypeIcon = React.memo(({
type, prid, status, isGroupChat, teamMain
}) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />);
TypeIcon.propTypes = {
type: PropTypes.string,
status: PropTypes.string,
prid: PropTypes.string,
isGroupChat: PropTypes.bool,
teamMain: PropTypes.bool
};
export default TypeIcon;

View File

@ -0,0 +1,17 @@
import React from 'react';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
interface ITypeIcon {
type: string;
status: string;
prid: string;
isGroupChat: boolean;
teamMain: boolean;
theme?: string;
}
const TypeIcon = React.memo(({
type, prid, status, isGroupChat, teamMain
}: ITypeIcon) => <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />);
export default TypeIcon;

View File

@ -1,14 +1,18 @@
import React from 'react';
import { Text } from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
import { capitalize } from '../../utils/room';
const UpdatedAt = React.memo(({
date, theme, hideUnreadStatus, alert
}) => {
interface IUpdatedAt {
date: string;
theme: string;
hideUnreadStatus: boolean;
alert: boolean;
}
const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdatedAt) => {
if (!date) {
return null;
}
@ -38,11 +42,4 @@ const UpdatedAt = React.memo(({
);
});
UpdatedAt.propTypes = {
date: PropTypes.string,
theme: PropTypes.string,
hideUnreadStatus: PropTypes.bool,
alert: PropTypes.bool
};
export default UpdatedAt;

View File

@ -1,11 +1,20 @@
import React from 'react';
import { View } from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles';
import { themes } from '../../constants/colors';
import Avatar from '../../containers/Avatar';
interface IWrapper {
accessibilityLabel: string;
avatar: string;
avatarSize: number;
type: string;
theme: string;
rid: string;
children: JSX.Element;
}
const Wrapper = ({
accessibilityLabel,
avatar,
@ -14,7 +23,7 @@ const Wrapper = ({
theme,
rid,
children
}) => (
}: IWrapper) => (
<View
style={styles.container}
accessibilityLabel={accessibilityLabel}
@ -39,14 +48,4 @@ const Wrapper = ({
</View>
);
Wrapper.propTypes = {
accessibilityLabel: PropTypes.string,
avatar: PropTypes.string,
avatarSize: PropTypes.number,
type: PropTypes.string,
theme: PropTypes.string,
rid: PropTypes.string,
children: PropTypes.element
};
export default Wrapper;

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import I18n from '../../i18n';
@ -9,6 +8,32 @@ import RoomItem from './RoomItem';
export { ROW_HEIGHT };
interface IRoomItemContainerProps {
item: any;
showLastMessage: boolean;
id: string;
onPress({}?): void;
onLongPress({}?): void;
username: string;
avatarSize: number;
width: number;
status: string;
toggleFav(): void;
toggleRead(): void;
hideChannel(): void;
useRealName: boolean;
getUserPresence: Function;
connected: boolean;
theme: string;
isFocused: boolean;
getRoomTitle: Function;
getRoomAvatar: Function;
getIsGroupChat: Function;
getIsRead: Function;
swipeEnabled: boolean;
autoJoin: boolean;
}
const attrs = [
'width',
'status',
@ -20,32 +45,9 @@ const attrs = [
'autoJoin'
];
class RoomItemContainer extends React.Component {
static propTypes = {
item: PropTypes.object.isRequired,
showLastMessage: PropTypes.bool,
id: PropTypes.string,
onPress: PropTypes.func,
onLongPress: PropTypes.func,
username: PropTypes.string,
avatarSize: PropTypes.number,
width: PropTypes.number,
status: PropTypes.string,
toggleFav: PropTypes.func,
toggleRead: PropTypes.func,
hideChannel: PropTypes.func,
useRealName: PropTypes.bool,
getUserPresence: PropTypes.func,
connected: PropTypes.bool,
theme: PropTypes.string,
isFocused: PropTypes.bool,
getRoomTitle: PropTypes.func,
getRoomAvatar: PropTypes.func,
getIsGroupChat: PropTypes.func,
getIsRead: PropTypes.func,
swipeEnabled: PropTypes.bool,
autoJoin: PropTypes.bool
};
class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
private mounted: boolean;
private roomSubscription: any;
static defaultProps = {
avatarSize: 48,
@ -58,7 +60,7 @@ class RoomItemContainer extends React.Component {
swipeEnabled: true
}
constructor(props) {
constructor(props: IRoomItemContainerProps) {
super(props);
this.mounted = false;
this.init();
@ -72,12 +74,12 @@ class RoomItemContainer extends React.Component {
}
}
shouldComponentUpdate(nextProps) {
const { props } = this;
shouldComponentUpdate(nextProps: any) {
const { props }: any = this;
return !attrs.every(key => props[key] === nextProps[key]);
}
componentDidUpdate(prevProps) {
componentDidUpdate(prevProps: any) {
const { connected, getUserPresence, id } = this.props;
if (prevProps.connected !== connected && connected && this.isDirect) {
getUserPresence(id);
@ -96,7 +98,7 @@ class RoomItemContainer extends React.Component {
}
get isDirect() {
const { item: { t }, id } = this.props;
const { item: { t }, id }: any = this.props;
return t === 'd' && id && !this.isGroupChat;
}
@ -165,6 +167,7 @@ class RoomItemContainer extends React.Component {
}
return (
// @ts-ignore
<RoomItem
name={name}
avatar={avatar}
@ -207,7 +210,7 @@ class RoomItemContainer extends React.Component {
}
}
const mapStateToProps = (state, ownProps) => {
const mapStateToProps = (state: any, ownProps: any) => {
let status = 'loading';
const { id, type, visitor = {} } = ownProps;
if (state.meteor.connected) {

View File

@ -7,7 +7,7 @@ export const ACTION_WIDTH = 80;
export const SMALL_SWIPE = ACTION_WIDTH / 2;
export const LONG_SWIPE = ACTION_WIDTH * 3;
export default StyleSheet.create({
export default StyleSheet.create<any>({
flex: {
flex: 1
},

View File

@ -1,5 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
// @ts-ignore
import { View, Text, Pressable } from 'react-native';
import FastImage from '@rocket.chat/react-native-fast-image';
@ -11,11 +11,23 @@ import { withTheme } from '../../theme';
export { ROW_HEIGHT };
interface IServerItem {
item: {
id: string;
iconURL: string;
name: string;
};
onPress(): void;
onLongPress(): void;
hasCheck: boolean;
theme: string;
}
const defaultLogo = require('../../static/images/logo.png');
const ServerItem = React.memo(({
item, onPress, onLongPress, hasCheck, theme
}) => (
}: IServerItem) => (
<Pressable
onPress={onPress}
onLongPress={() => onLongPress?.()}
@ -23,7 +35,7 @@ const ServerItem = React.memo(({
android_ripple={{
color: themes[theme].bannerBackground
}}
style={({ pressed }) => ({
style={({ pressed }: any) => ({
backgroundColor: isIOS && pressed
? themes[theme].bannerBackground
: themes[theme].backgroundColor
@ -37,6 +49,7 @@ const ServerItem = React.memo(({
uri: item.iconURL,
priority: FastImage.priority.high
}}
// @ts-ignore
defaultSource={defaultLogo}
style={styles.serverIcon}
onError={() => console.log('err_loading_server_icon')}
@ -58,12 +71,4 @@ const ServerItem = React.memo(({
</Pressable>
));
ServerItem.propTypes = {
item: PropTypes.object.isRequired,
onPress: PropTypes.func.isRequired,
onLongPress: PropTypes.func,
hasCheck: PropTypes.bool,
theme: PropTypes.string
};
export default withTheme(ServerItem);

View File

@ -1,6 +1,5 @@
import React from 'react';
import { TextInput, StyleSheet, I18nManager } from 'react-native';
import PropTypes from 'prop-types';
import { themes } from '../constants/colors';
@ -12,7 +11,12 @@ const styles = StyleSheet.create({
}
});
const ThemedTextInput = React.forwardRef(({ style, theme, ...props }, ref) => (
interface IThemedTextInput {
style: object;
theme: string;
}
const ThemedTextInput = React.forwardRef(({ style, theme, ...props }: IThemedTextInput, ref: any) => (
<TextInput
ref={ref}
style={[{ color: themes[theme].titleText }, style, styles.input]}
@ -22,9 +26,4 @@ const ThemedTextInput = React.forwardRef(({ style, theme, ...props }, ref) => (
/>
));
ThemedTextInput.propTypes = {
style: PropTypes.object,
theme: PropTypes.string
};
export default ThemedTextInput;

View File

@ -2,7 +2,7 @@ import { themes } from '../../constants/colors';
export const getUnreadStyle = ({
unread, userMentions, groupMentions, theme, tunread, tunreadUser, tunreadGroup
}) => {
}: any) => {
if ((!unread || unread <= 0) && (!tunread?.length)) {
return {};
}

View File

@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native';
import sharedStyles from '../../views/Styles';
@ -30,9 +29,21 @@ const styles = StyleSheet.create({
}
});
interface IUnreadBadge {
theme: string;
unread: number;
userMentions: number;
groupMentions: number;
style: object;
tunread: [];
tunreadUser: [];
tunreadGroup: [];
small: boolean;
}
const UnreadBadge = React.memo(({
theme, unread, userMentions, groupMentions, style, tunread, tunreadUser, tunreadGroup, small
}) => {
}: IUnreadBadge) => {
if ((!unread || unread <= 0) && (!tunread?.length)) {
return null;
}
@ -43,7 +54,7 @@ const UnreadBadge = React.memo(({
if (!backgroundColor) {
return null;
}
let text = unread || tunread?.length;
let text: any = unread || tunread?.length;
if (small && text >= 100) {
text = '+99';
}
@ -78,16 +89,4 @@ const UnreadBadge = React.memo(({
);
});
UnreadBadge.propTypes = {
theme: PropTypes.string,
unread: PropTypes.number,
userMentions: PropTypes.number,
groupMentions: PropTypes.number,
style: PropTypes.object,
tunread: PropTypes.array,
tunreadUser: PropTypes.array,
tunreadGroup: PropTypes.array,
small: PropTypes.bool
};
export default withTheme(UnreadBadge);

View File

@ -1,8 +1,6 @@
import React from 'react';
import {
Text, View, StyleSheet, Pressable
} from 'react-native';
import PropTypes from 'prop-types';
// @ts-ignore
import { Text, View, StyleSheet, Pressable } from 'react-native';
import Avatar from '../containers/Avatar';
import { CustomIcon } from '../lib/Icons';
@ -41,9 +39,20 @@ const styles = StyleSheet.create({
}
});
interface IUserItem {
name: string;
username: string;
onPress(): void;
testID: string;
onLongPress(): void;
style: any;
icon: string;
theme: string;
}
const UserItem = ({
name, username, onPress, testID, onLongPress, style, icon, theme
}) => (
}: IUserItem) => (
<Pressable
onPress={onPress}
onLongPress={onLongPress}
@ -51,7 +60,7 @@ const UserItem = ({
android_ripple={{
color: themes[theme].bannerBackground
}}
style={({ pressed }) => ({
style={({ pressed }: any) => ({
backgroundColor: isIOS && pressed
? themes[theme].bannerBackground
: 'transparent'
@ -68,15 +77,4 @@ const UserItem = ({
</Pressable>
);
UserItem.propTypes = {
name: PropTypes.string.isRequired,
username: PropTypes.string.isRequired,
onPress: PropTypes.func.isRequired,
testID: PropTypes.string.isRequired,
onLongPress: PropTypes.func,
style: PropTypes.any,
icon: PropTypes.string,
theme: PropTypes.string
};
export default UserItem;

Some files were not shown because too many files have changed in this diff Show More