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: &macos
macos: macos:
xcode: "12.5.0" xcode: "12.5.0"
resource_class: large
bash-env: &bash-env bash-env: &bash-env
BASH_ENV: "~/.nvm/nvm.sh" BASH_ENV: "~/.nvm/nvm.sh"
@ -143,15 +144,6 @@ commands:
fi fi
working_directory: android/app 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: - run:
name: Build App name: Build App
command: | command: |
@ -170,22 +162,20 @@ commands:
name: Upload sourcemaps to Bugsnag name: Upload sourcemaps to Bugsnag
command: | command: |
if [[ $CIRCLE_JOB == "android-build-official" ]]; then 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 \ --api-key=$BUGSNAG_KEY_OFFICIAL \
--app-version=$CIRCLE_BUILD_NUM \ --app-version-code=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/officialPlay/release/app.bundle \ --platform android \
--source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \ --source-map=android/app/build/generated/sourcemaps/react/officialPlay/release/app.bundle.map \
--minified-url=app.bundle \ --bundle android/app/build/generated/assets/react/officialPlay/release/app.bundle
--upload-sources
fi fi
if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then if [[ $CIRCLE_JOB == "android-build-experimental" ]]; then
yarn generate-source-maps-android upload \ npx bugsnag-source-maps upload-react-native \
--api-key=$BUGSNAG_KEY \ --api-key=$BUGSNAG_KEY \
--app-version=$CIRCLE_BUILD_NUM \ --app-version-code=$CIRCLE_BUILD_NUM \
--minifiedFile=android/app/build/generated/assets/react/experimentalPlay/release/app.bundle \ --platform android \
--source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \ --source-map=android/app/build/generated/sourcemaps/react/experimentalPlay/release/app.bundle.map \
--minified-url=app.bundle \ --bundle android/app/build/generated/assets/react/experimentalPlay/release/app.bundle
--upload-sources
fi fi
- store_artifacts: - store_artifacts:
@ -216,41 +206,20 @@ commands:
echo $GOOGLE_SERVICES_IOS | base64 --decode > GoogleService-Info.plist echo $GOOGLE_SERVICES_IOS | base64 --decode > GoogleService-Info.plist
fi fi
working_directory: ios 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: - run:
name: Fastlane Build name: Fastlane Build
no_output_timeout: 40m no_output_timeout: 40m
command: | command: |
agvtool new-version -all $CIRCLE_BUILD_NUM agvtool new-version -all $CIRCLE_BUILD_NUM
if [[ $CIRCLE_JOB == "ios-build-official" ]]; then 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" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./ShareRocketChatRN/Info.plist /usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./NotificationService/Info.plist /usr/libexec/PlistBuddy -c "Set IS_OFFICIAL YES" ./NotificationService/Info.plist
else 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" ./RocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./ShareRocketChatRN/Info.plist /usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./ShareRocketChatRN/Info.plist
/usr/libexec/PlistBuddy -c "Set IS_OFFICIAL NO" ./NotificationService/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", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -6211,7 +6211,7 @@ exports[`Storyshots List with bigger font 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 69, "height": 69,
}, },
@ -6625,7 +6625,7 @@ exports[`Storyshots List with bigger font 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 69, "height": 69,
}, },
@ -7080,7 +7080,7 @@ exports[`Storyshots List with black theme 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -7494,7 +7494,7 @@ exports[`Storyshots List with black theme 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -7972,7 +7972,7 @@ exports[`Storyshots List with custom colors 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -8129,7 +8129,7 @@ exports[`Storyshots List with dark theme 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -8543,7 +8543,7 @@ exports[`Storyshots List with dark theme 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 92, "height": 92,
}, },
@ -10410,7 +10410,7 @@ exports[`Storyshots List with small font 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 36.800000000000004, "height": 36.800000000000004,
}, },
@ -10824,7 +10824,7 @@ exports[`Storyshots List with small font 1`] = `
"justifyContent": "center", "justifyContent": "center",
"paddingHorizontal": 12, "paddingHorizontal": 12,
}, },
false, undefined,
Object { Object {
"height": 36.800000000000004, "height": 36.800000000000004,
}, },

View File

@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer versionCode VERSIONCODE as Integer
versionName "4.18.0" versionName "4.19.0"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
if (!isFoss) { if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String] 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.JsIOHelper;
import com.wix.reactnativenotifications.core.notification.INotificationsApplication; import com.wix.reactnativenotifications.core.notification.INotificationsApplication;
import com.wix.reactnativenotifications.core.notification.IPushNotification; import com.wix.reactnativenotifications.core.notification.IPushNotification;
import com.bugsnag.android.Bugsnag;
public class MainPlayApplication extends MainApplication implements INotificationsApplication { public class MainPlayApplication extends MainApplication implements INotificationsApplication {
@Override
public void onCreate() {
super.onCreate();
Bugsnag.start(this);
}
@Override @Override
public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) { public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) {
return new CustomPushNotification( return new CustomPushNotification(

View File

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

View File

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

View File

@ -6,39 +6,12 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk';
import { avatarURL } from '../../utils/avatar'; import { avatarURL } from '../../utils/avatar';
import Emoji from '../markdown/Emoji'; import Emoji from '../markdown/Emoji';
import {IAvatar} from './interfaces';
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;
}
const Avatar = React.memo(({ const Avatar = React.memo(({
text,
size,
server, server,
borderRadius, style,
style,
avatar, avatar,
type,
children, children,
user, user,
onPress, onPress,
@ -49,8 +22,13 @@ const Avatar = React.memo(({
isStatic, isStatic,
rid, rid,
blockUnauthenticatedAccess, blockUnauthenticatedAccess,
serverVersion serverVersion,
text,
size = 25,
borderRadius = 4,
type = 'd',
}: Partial<IAvatar>) => { }: Partial<IAvatar>) => {
if ((!text && !avatar && !emoji && !rid) || !server) { if ((!text && !avatar && !emoji && !rid) || !server) {
return null; return null;
} }

View File

@ -4,12 +4,19 @@ import { Q } from '@nozbe/watermelondb';
import database from '../../lib/database'; import database from '../../lib/database';
import { getUserSelector } from '../../selectors/login'; 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> { class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
private mounted: boolean; private mounted: boolean;
private subscription!: any; private subscription!: any;
static defaultProps = {
text: '',
type: 'd'
};
constructor(props: Partial<IAvatar>) { constructor(props: Partial<IAvatar>) {
super(props); super(props);
this.mounted = false; 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} /> <BackgroundContainer text={longText} />
)); ));
const ThemeStory = ({ theme, ...props }: any) => ( const ThemeStory = ({ theme, ...props }) => (
<ThemeContext.Provider <ThemeContext.Provider
value={{ theme }} value={{ theme }}
> >

View File

@ -40,6 +40,14 @@ const styles = StyleSheet.create({
export default class Button extends React.PureComponent<Partial<IButtonProps>, any> { 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() { render() {
const { const {
title, type, onPress, disabled, backgroundColor, color, loading, style, theme, fontSize, ...otherProps 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 { CustomIcon } from '../lib/Icons';
import { themes } from '../constants/colors'; import { themes } from '../constants/colors';
type TCheck = { interface ICheck {
style?: object, style?: object;
theme: string theme: string;
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
icon: { 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; export default Check;

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ export const getHeaderHeight = (isLandscape: boolean) => {
return 56; return 56;
}; };
type THeaderTitlePosition = { interface IHeaderTitlePosition {
insets: { insets: {
left: number; left: number;
right: number; right: number;
@ -28,7 +28,7 @@ type THeaderTitlePosition = {
numIconsRight: number; numIconsRight: number;
} }
export const getHeaderTitlePosition = ({ insets, numIconsRight }: THeaderTitlePosition) => ({ export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
left: insets.left + 60, left: insets.left + 60,
right: insets.right + Math.max(45 * numIconsRight, 15) 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]}> <View style={[styles.container, left ? styles.left : styles.right]}>
{children} {children}
</View> </View>

View File

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

View File

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

View File

@ -1,12 +1,13 @@
import React from 'react'; 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({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center'
backgroundColor: 'rgba(0, 0, 0, 0.25)'
}, },
image: { image: {
width: 100, width: 100,
@ -17,9 +18,10 @@ const styles = StyleSheet.create({
interface ILoadingProps { interface ILoadingProps {
visible: boolean; visible: boolean;
theme: string;
} }
export default class Loading extends React.PureComponent<ILoadingProps, any> { class Loading extends React.PureComponent<ILoadingProps, any> {
state = { state = {
scale: new Animated.Value(1), scale: new Animated.Value(1),
@ -36,7 +38,7 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
opacity, opacity,
{ {
toValue: 1, toValue: 1,
duration: 1000, duration: 200,
useNativeDriver: true useNativeDriver: true
} }
); );
@ -91,23 +93,40 @@ export default class Loading extends React.PureComponent<ILoadingProps, any> {
render() { render() {
const { opacity, scale } = this.state; const { opacity, scale } = this.state;
const { visible } = this.props; const { visible, theme } = this.props;
const scaleAnimation = scale.interpolate({ const scaleAnimation = scale.interpolate({
inputRange: [0, 0.5, 1], inputRange: [0, 0.5, 1],
outputRange: [1, 1.1, 1] outputRange: [1, 1.1, 1]
}); });
const opacityAnimation = opacity.interpolate({
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity],
extrapolate: 'clamp'
});
return ( return (
<Modal <Modal
visible={visible} visible={visible}
transparent transparent
onRequestClose={() => {}} 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 <Animated.Image
source={require('../static/images/logo.png')} source={require('../static/images/logo.png')}
style={[styles.image, { style={[styles.image, {
opacity,
transform: [{ transform: [{
scale: scaleAnimation 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; url?: string;
ssoToken?: string; ssoToken?: string;
authType?: string; authType?: string;
} }
type TService = { interface IService {
name: string; name: string;
service: string; service: string;
authType: string; authType: string;
buttonColor: string; buttonColor: string;
buttonLabelColor: string; buttonLabelColor: string;
}; }
interface ILoginServicesProps { interface ILoginServicesProps {
navigation: any; navigation: any;
@ -93,6 +93,10 @@ interface ILoginServicesProps {
class LoginServices extends React.PureComponent<ILoginServicesProps, any> { class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
private _animation: any; private _animation: any;
static defaultProps = {
separator: true
}
state = { state = {
collapsed: true, collapsed: true,
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT) servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
@ -251,7 +255,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
return Base64.encodeURI(JSON.stringify(obj)); return Base64.encodeURI(JSON.stringify(obj));
} }
openOAuth = ({ url, ssoToken, authType = 'oauth' }: TOpenOAuth) => { openOAuth = ({ url, ssoToken, authType = 'oauth' }: IOpenOAuth) => {
const { navigation } = this.props; const { navigation } = this.props;
navigation.navigate('AuthenticationWebView', { url, authType, ssoToken }); navigation.navigate('AuthenticationWebView', { url, authType, ssoToken });
} }
@ -322,7 +326,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
return null; return null;
} }
renderItem = (service: TService) => { renderItem = (service: IService) => {
const { CAS_enabled, theme } = this.props; const { CAS_enabled, theme } = this.props;
let { name } = service; let { name } = service;
name = name === 'meteor-developer' ? 'meteor' : name; name = name === 'meteor-developer' ? 'meteor' : name;

View File

@ -10,7 +10,7 @@ import database from '../../lib/database';
import { Button } from '../ActionSheet'; import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions'; import { useDimensions } from '../../dimensions';
import sharedStyles from '../../views/Styles'; import sharedStyles from '../../views/Styles';
import {TEmoji} from "../EmojiPicker"; import {IEmoji} from "../EmojiPicker/interfaces";
interface IHeader { interface IHeader {
handleReaction: Function; handleReaction: Function;
@ -21,7 +21,7 @@ interface IHeader {
} }
interface THeaderItem { interface THeaderItem {
item: TEmoji; item: IEmoji;
onReaction: Function; onReaction: Function;
server: string; server: string;
theme: string; theme: string;
@ -118,7 +118,7 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
setEmojis(); 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} />, []); 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 { interface IMessageBoxEmojiKeyboard {
theme: string theme: string
} }
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> { export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
private readonly baseUrl: any; private readonly baseUrl: any;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -141,7 +141,7 @@ const HeaderTitle = React.memo(({ title, tmid, prid, scale, theme, testID }: TRo
}); });
const Header = React.memo(({ 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) => { }: IRoomHeader) => {
const portrait = height > width; const portrait = height > width;
let scale = 1; let scale = 1;

View File

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

View File

@ -8,7 +8,7 @@ interface IStatus {
style: any; 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 name = `status-${ status }`;
const isNameValid = CustomIcon.hasIcon(name); const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline'; const iconName = isNameValid ? name : 'status-offline';

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ import { themes } from '../../constants/colors';
import { BUTTON_HIT_SLOP } from '../message/utils'; import { BUTTON_HIT_SLOP } from '../message/utils';
import * as List from '../List'; import * as List from '../List';
type TOption = { interface IOption {
option: { option: {
text: string; text: string;
value: string; value: string;
@ -17,14 +17,14 @@ type TOption = {
onOptionPress: Function; onOptionPress: Function;
parser: any; parser: any;
theme: string; theme: string;
}; }
type TOptions = { interface IOptions {
options: []; options: [];
onOptionPress: Function; onOptionPress: Function;
parser: object; parser: object;
theme: string; theme: string;
}; }
interface IOverflow { interface IOverflow {
element: any; 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 <Touchable
onPress={() => onOptionPress({ value })} onPress={() => onOptionPress({ value })}
background={Touchable.Ripple(themes[theme].bannerBackground)} background={Touchable.Ripple(themes[theme].bannerBackground)}
@ -60,7 +60,7 @@ const Option = ({ option: { text, value }, onOptionPress, parser, theme }: TOpti
</Touchable> </Touchable>
); );
const Options = ({ options, onOptionPress, parser, theme }: TOptions) => ( const Options = ({ options, onOptionPress, parser, theme }: IOptions) => (
<FlatList <FlatList
data={options} data={options}
renderItem={({ item }) => <Option option={item} onOptionPress={onOptionPress} parser={parser} theme={theme} />} 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; blockId?: string;
appId?: string; appId?: string;
element: any; element: any;
parser: any parser: any
} }
type TFields = { interface IFields {
fields: any; fields: any;
parser: any; parser: any;
theme: string; theme: string;
@ -46,13 +46,13 @@ interface ISection {
parser: any; parser: any;
} }
const Accessory = ({ blockId, appId, element, parser }: TAccessory) => parser.renderAccessories( const Accessory = ({ blockId, appId, element, parser }: IAccessory) => parser.renderAccessories(
{ blockId, appId, ...element }, { blockId, appId, ...element },
BLOCK_CONTEXT.SECTION, BLOCK_CONTEXT.SECTION,
parser 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 }]}> <Text style={[styles.text, styles.field, { color: themes[theme].bodyText }]}>
{parser.text(field)} {parser.text(field)}
</Text> </Text>

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@ interface IList {
numberOfLines: number; 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; let bulletWidth = 15;
if (ordered) { if (ordered) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,25 +11,7 @@ import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
import Encrypted from './Encrypted'; import Encrypted from './Encrypted';
import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants'; import { E2E_MESSAGE_TYPE } from '../../lib/encryption/constants';
import {TChannel} from "../markdown/Hashtag"; import {IMessageContent} from "./interfaces";
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;
}
const Content = React.memo((props: IMessageContent) => { const Content = React.memo((props: IMessageContent) => {
if (props.isInfo) { if (props.isInfo) {

View File

@ -10,13 +10,8 @@ import { DISCUSSION } from './constants';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import MessageContext from './Context'; import MessageContext from './Context';
import { formatDateThreads } from '../../utils/room'; 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) => { const Discussion = React.memo(({ msg, dcount, dlm, theme }: IMessageDiscussion) => {
let time; let time;

View File

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

View File

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

View File

@ -6,59 +6,22 @@ import MessageContext from './Context';
import User from './User'; import User from './User';
import styles from './styles'; import styles from './styles';
import RepliedThread, {IMessageRepliedThread} from './RepliedThread'; import RepliedThread from './RepliedThread';
import MessageAvatar, {IMessageAvatar} from './MessageAvatar'; import MessageAvatar from './MessageAvatar';
import Attachments, {IMessageAttachments} from './Attachments'; import Attachments from './Attachments';
import Urls from './Urls'; import Urls from './Urls';
import Thread, {IMessageThread} from './Thread'; import Thread from './Thread';
import Blocks, {IMessageBlocks} from './Blocks'; import Blocks from './Blocks';
import Reactions from './Reactions'; import Reactions from './Reactions';
import Broadcast, {IMessageBroadcast} from './Broadcast'; import Broadcast from './Broadcast';
import Discussion, {IMessageDiscussion} from './Discussion'; import Discussion from './Discussion';
import Content, {IMessageContent} from './Content'; import Content from './Content';
import ReadReceipt from './ReadReceipt'; import ReadReceipt from './ReadReceipt';
import CallButton, {IMessageCallButton} from './CallButton'; import CallButton from './CallButton';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import {IMessage, IMessageInner, IMessageTouchable} from "./interfaces";
const MessageInner = React.memo((props: IMessageInner) => {
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) => {
if (props.type === 'discussion-created') { if (props.type === 'discussion-created') {
return ( return (
<> <>
@ -100,7 +63,7 @@ const MessageInner = React.memo((props: TMessageInner) => {
}); });
MessageInner.displayName = 'MessageInner'; MessageInner.displayName = 'MessageInner';
const Message = React.memo((props: TMessage) => { const Message = React.memo((props: IMessage) => {
if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) { if (props.isThreadReply || props.isThreadSequential || props.isInfo || props.isIgnored) {
const thread = props.isThreadReply ? <RepliedThread {...props} /> : null; const thread = props.isThreadReply ? <RepliedThread {...props} /> : null;
return ( return (
@ -144,7 +107,7 @@ const Message = React.memo((props: TMessage) => {
}); });
Message.displayName = 'Message'; Message.displayName = 'Message';
const MessageTouchable = React.memo((props: IMessageTouchable & TMessage) => { const MessageTouchable = React.memo((props: IMessageTouchable & IMessage) => {
if (props.hasError) { if (props.hasError) {
return ( return (
<View> <View>

View File

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

View File

@ -10,18 +10,18 @@ import { themes } from '../../constants/colors';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import MessageContext from './Context'; import MessageContext from './Context';
type TMessageAddReaction = { interface IMessageAddReaction {
theme: string theme: string
}; }
type TMessageReaction = { interface IMessageReaction {
reaction: { reaction: {
usernames: []; usernames: [];
emoji: object; emoji: object;
}; };
getCustomEmoji: Function; getCustomEmoji: Function;
theme: string; theme: string;
}; }
interface IMessageReactions { interface IMessageReactions {
reactions: object[]; reactions: object[];
@ -29,7 +29,7 @@ interface IMessageReactions {
theme: string; theme: string;
} }
const AddReaction = React.memo(({ theme }: TMessageAddReaction) => { const AddReaction = React.memo(({ theme }: IMessageAddReaction) => {
const { reactionInit } = useContext(MessageContext); const { reactionInit } = useContext(MessageContext);
return ( return (
<Touchable <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 { 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 ( return (
<Touchable <Touchable
onPress={() => onReactionPress(reaction.emoji)} onPress={() => onReactionPress(reaction.emoji)}

View File

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

View File

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

View File

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

View File

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

View File

@ -64,6 +64,28 @@ interface IMessageContainerProps {
class MessageContainer extends React.Component<IMessageContainerProps, any> { 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 }; state = { isManualUnignored: false };
private subscription: any; 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?", "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_More": "Mehr laden",
"Load_Newer": "Neuere 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": "После прочтения предыдущих инструкций об этом поведении, вы все еще хотите переместить этот канал в выбранную Команду?", "Move_to_Team_Warning": "После прочтения предыдущих инструкций об этом поведении, вы все еще хотите переместить этот канал в выбранную Команду?",
"Load_More": "Загрузить еще", "Load_More": "Загрузить еще",
"Load_Newer": "Загрузить более позднее", "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(); RNScreens.enableScreens();
type TDimensions = { interface IDimensions {
width: number, width: number,
height: number, height: number,
scale: number, scale: number,
fontScale: number fontScale: number
} }
interface IProps {} interface IProps {}
interface IState { interface IState {
theme: string, theme: string,
@ -163,7 +164,7 @@ export default class Root extends React.Component<IProps, IState> {
window: { window: {
width, height, scale, fontScale width, height, scale, fontScale
} }
}: {window: TDimensions}) => { }: {window: IDimensions}) => {
this.setDimensions({ this.setDimensions({
width, height, scale, fontScale 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}); this.setState({width, height, scale, fontScale});
} }

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { ScrollView, StyleSheet } from 'react-native'; import { ScrollView, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { ImageComponent } from './ImageComponent'; import { ImageComponent } from './ImageComponent';
import { themes } from '../../constants/colors'; 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 = ({ export const ImageViewer = ({
uri, imageComponentType, theme, width, height, ...props uri, imageComponentType, theme, width, height, ...props
}) => { }: IImageViewer) => {
const backgroundColor = themes[theme].previewBackground; const backgroundColor = themes[theme].previewBackground;
const Component = ImageComponent(imageComponentType); const Component = ImageComponent(imageComponentType);
return ( return (
// @ts-ignore
<ScrollView <ScrollView
style={{ backgroundColor }} style={{ backgroundColor }}
contentContainerStyle={[ contentContainerStyle={[
@ -41,11 +49,3 @@ export const ImageViewer = ({
</ScrollView> </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 React from 'react';
import PropTypes from 'prop-types';
import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view'; import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
import scrollPersistTaps from '../utils/scrollPersistTaps'; import scrollPersistTaps from '../utils/scrollPersistTaps';
export default class KeyboardView extends React.PureComponent { interface IKeyboardViewProps {
static propTypes = { style: any,
style: PropTypes.any, contentContainerStyle: any,
contentContainerStyle: PropTypes.any, keyboardVerticalOffset: number,
keyboardVerticalOffset: PropTypes.number, scrollEnabled: boolean,
scrollEnabled: PropTypes.bool, children: JSX.Element;
children: PropTypes.oneOfType([ }
PropTypes.arrayOf(PropTypes.node),
PropTypes.node export default class KeyboardView extends React.PureComponent<IKeyboardViewProps, any> {
])
}
render() { render() {
const { const {
@ -28,6 +25,7 @@ export default class KeyboardView extends React.PureComponent {
scrollEnabled={scrollEnabled} scrollEnabled={scrollEnabled}
alwaysBounceVertical={false} alwaysBounceVertical={false}
extraHeight={keyboardVerticalOffset} extraHeight={keyboardVerticalOffset}
// @ts-ignore
behavior='position' behavior='position'
> >
{children} {children}

View File

@ -1,18 +1,34 @@
import React from 'react'; import React from 'react';
import { Animated, View, Text } from 'react-native'; import { Animated, View, Text } from 'react-native';
import { RectButton } from 'react-native-gesture-handler'; import { RectButton } from 'react-native-gesture-handler';
import PropTypes from 'prop-types';
import I18n, { isRTL } from '../../i18n'; import I18n, { isRTL } from '../../i18n';
import styles, { ACTION_WIDTH, LONG_SWIPE } from './styles'; import styles, { ACTION_WIDTH, LONG_SWIPE } from './styles';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import { themes } from '../../constants/colors'; 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); const reverse = new Animated.Value(isRTL() ? -1 : 1);
export const LeftActions = React.memo(({ export const LeftActions = React.memo(({
theme, transX, isRead, width, onToggleReadPress theme, transX, isRead, width, onToggleReadPress
}) => { }: ILeftActions) => {
const translateX = Animated.multiply( const translateX = Animated.multiply(
transX.interpolate({ transX.interpolate({
inputRange: [0, ACTION_WIDTH], inputRange: [0, ACTION_WIDTH],
@ -51,7 +67,7 @@ export const LeftActions = React.memo(({
export const RightActions = React.memo(({ export const RightActions = React.memo(({
transX, favorite, width, toggleFav, onHidePress, theme transX, favorite, width, toggleFav, onHidePress, theme
}) => { }: IRightActions) => {
const translateXFav = Animated.multiply( const translateXFav = Animated.multiply(
transX.interpolate({ transX.interpolate({
inputRange: [-width / 2, -ACTION_WIDTH * 2, 0], inputRange: [-width / 2, -ACTION_WIDTH * 2, 0],
@ -113,20 +129,3 @@ export const RightActions = React.memo(({
</View> </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 React from 'react';
import PropTypes from 'prop-types';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import I18n from '../../i18n'; import I18n from '../../i18n';
@ -8,9 +7,27 @@ import Markdown from '../../containers/markdown';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/encryption/constants'; 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 = ({ const formatMsg = ({
lastMessage, type, showLastMessage, username, useRealName lastMessage, type, showLastMessage, username, useRealName
}) => { }: Partial<ILastMessage>) => {
if (!showLastMessage) { if (!showLastMessage) {
return ''; return '';
} }
@ -45,11 +62,12 @@ const formatMsg = ({
return `${ prefix }${ lastMessage.msg }`; return `${ prefix }${ lastMessage.msg }`;
}; };
const arePropsEqual = (oldProps, newProps) => dequal(oldProps, newProps); const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
const LastMessage = React.memo(({ const LastMessage = React.memo(({
lastMessage, type, showLastMessage, username, alert, useRealName, theme lastMessage, type, showLastMessage, username, alert, useRealName, theme
}) => ( }: ILastMessage) => (
// @ts-ignore
<Markdown <Markdown
msg={formatMsg({ msg={formatMsg({
lastMessage, type, showLastMessage, username, useRealName lastMessage, type, showLastMessage, username, useRealName
@ -63,14 +81,4 @@ const LastMessage = React.memo(({
/> />
), arePropsEqual); ), 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; export default LastMessage;

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { View } from 'react-native'; import { View } from 'react-native';
import styles from './styles'; import styles from './styles';
@ -13,6 +12,53 @@ import Touchable from './Touchable';
import Tag from './Tag'; import Tag from './Tag';
import I18n from '../../i18n'; 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 = ({ const RoomItem = ({
rid, rid,
type, type,
@ -20,10 +66,10 @@ const RoomItem = ({
name, name,
avatar, avatar,
width, width,
avatarSize, avatarSize = 48,
username, username,
showLastMessage, showLastMessage,
status, status = 'offline',
useRealName, useRealName,
theme, theme,
isFocused, isFocused,
@ -42,7 +88,7 @@ const RoomItem = ({
tunreadUser, tunreadUser,
tunreadGroup, tunreadGroup,
testID, testID,
swipeEnabled, swipeEnabled = true,
onPress, onPress,
onLongPress, onLongPress,
toggleFav, toggleFav,
@ -50,7 +96,7 @@ const RoomItem = ({
hideChannel, hideChannel,
teamMain, teamMain,
autoJoin autoJoin
}) => ( }: IRoomItem) => (
<Touchable <Touchable
onPress={onPress} onPress={onPress}
onLongPress={onLongPress} onLongPress={onLongPress}
@ -158,49 +204,4 @@ const RoomItem = ({
</Touchable> </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; export default RoomItem;

View File

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

View File

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

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { Animated } from 'react-native'; import { Animated } from 'react-native';
import { import {
LongPressGestureHandler, PanGestureHandler, State LongPressGestureHandler, PanGestureHandler, State
@ -15,26 +14,34 @@ import { isRTL } from '../../i18n';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { LeftActions, RightActions } from './Actions'; import { LeftActions, RightActions } from './Actions';
class Touchable extends React.Component { interface ITouchableProps {
static propTypes = { children: JSX.Element;
type: PropTypes.string.isRequired, type: string;
onPress: PropTypes.func, onPress(): void;
onLongPress: PropTypes.func, onLongPress(): void;
testID: PropTypes.string, testID: string;
width: PropTypes.number, width: number;
favorite: PropTypes.bool, favorite: boolean;
isRead: PropTypes.bool, isRead: boolean;
rid: PropTypes.string, rid: string;
toggleFav: PropTypes.func, toggleFav: Function;
toggleRead: PropTypes.func, toggleRead: Function;
hideChannel: PropTypes.func, hideChannel: Function;
children: PropTypes.element, theme: string;
theme: PropTypes.string, isFocused: boolean;
isFocused: PropTypes.bool, swipeEnabled: boolean;
swipeEnabled: PropTypes.bool }
}
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); super(props);
this.dragX = new Animated.Value(0); this.dragX = new Animated.Value(0);
this.rowOffSet = new Animated.Value(0); this.rowOffSet = new Animated.Value(0);
@ -56,20 +63,20 @@ class Touchable extends React.Component {
this._value = 0; this._value = 0;
} }
_onHandlerStateChange = ({ nativeEvent }) => { _onHandlerStateChange = ({ nativeEvent }: any) => {
if (nativeEvent.oldState === State.ACTIVE) { if (nativeEvent.oldState === State.ACTIVE) {
this._handleRelease(nativeEvent); this._handleRelease(nativeEvent);
} }
} }
onLongPressHandlerStateChange = ({ nativeEvent }) => { onLongPressHandlerStateChange = ({ nativeEvent }: any) => {
if (nativeEvent.state === State.ACTIVE) { if (nativeEvent.state === State.ACTIVE) {
this.onLongPress(); this.onLongPress();
} }
} }
_handleRelease = (nativeEvent) => { _handleRelease = (nativeEvent: any) => {
const { translationX } = nativeEvent; const { translationX } = nativeEvent;
const { rowState } = this.state; const { rowState } = this.state;
this._value += translationX; this._value += translationX;
@ -152,7 +159,7 @@ class Touchable extends React.Component {
this._animateRow(toValue); this._animateRow(toValue);
} }
_animateRow = (toValue) => { _animateRow = (toValue: any) => {
this.rowOffSet.setValue(this._value); this.rowOffSet.setValue(this._value);
this._value = toValue; this._value = toValue;
this.dragX.setValue(0); 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 React from 'react';
import { Text } from 'react-native'; import { Text } from 'react-native';
import PropTypes from 'prop-types';
import styles from './styles'; import styles from './styles';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { capitalize } from '../../utils/room'; import { capitalize } from '../../utils/room';
const UpdatedAt = React.memo(({ interface IUpdatedAt {
date, theme, hideUnreadStatus, alert date: string;
}) => { theme: string;
hideUnreadStatus: boolean;
alert: boolean;
}
const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdatedAt) => {
if (!date) { if (!date) {
return null; 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; export default UpdatedAt;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import { TextInput, StyleSheet, I18nManager } from 'react-native'; import { TextInput, StyleSheet, I18nManager } from 'react-native';
import PropTypes from 'prop-types';
import { themes } from '../constants/colors'; 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 <TextInput
ref={ref} ref={ref}
style={[{ color: themes[theme].titleText }, style, styles.input]} 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; export default ThemedTextInput;

View File

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

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native'; import { View, Text, StyleSheet } from 'react-native';
import sharedStyles from '../../views/Styles'; 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(({ const UnreadBadge = React.memo(({
theme, unread, userMentions, groupMentions, style, tunread, tunreadUser, tunreadGroup, small theme, unread, userMentions, groupMentions, style, tunread, tunreadUser, tunreadGroup, small
}) => { }: IUnreadBadge) => {
if ((!unread || unread <= 0) && (!tunread?.length)) { if ((!unread || unread <= 0) && (!tunread?.length)) {
return null; return null;
} }
@ -43,7 +54,7 @@ const UnreadBadge = React.memo(({
if (!backgroundColor) { if (!backgroundColor) {
return null; return null;
} }
let text = unread || tunread?.length; let text: any = unread || tunread?.length;
if (small && text >= 100) { if (small && text >= 100) {
text = '+99'; 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); export default withTheme(UnreadBadge);

View File

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

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