[improve] - fix the errors with auto-save

This commit is contained in:
AlexAlexandre 2021-08-19 21:01:17 -03:00
parent 3604e7d4b3
commit 7b9f00510d
354 changed files with 2119 additions and 2136 deletions

View File

@ -6,15 +6,12 @@ import { connect } from 'react-redux';
import Navigation from './lib/Navigation';
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
import {
ROOT_LOADING, ROOT_OUTSIDE, ROOT_NEW_SERVER, ROOT_INSIDE, ROOT_SET_USERNAME
ROOT_INSIDE, ROOT_LOADING, ROOT_NEW_SERVER, ROOT_OUTSIDE, ROOT_SET_USERNAME,
} from './actions/app';
// Stacks
import AuthLoadingView from './views/AuthLoadingView';
// SetUsername Stack
import SetUsernameView from './views/SetUsernameView';
import OutsideStack from './stacks/OutsideStack';
import InsideStack from './stacks/InsideStack';
import MasterDetailStack from './stacks/MasterDetailStack';
@ -101,7 +98,7 @@ const App = React.memo(({ root, isMasterDetail }: {root: string, isMasterDetail:
});
const mapStateToProps = (state: any) => ({
root: state.app.root,
isMasterDetail: state.app.isMasterDetail
isMasterDetail: state.app.isMasterDetail,
});
const AppContainer = connect(mapStateToProps)(App);

View File

@ -4,7 +4,7 @@ const FAILURE = 'FAILURE';
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
function createRequestTypes(base, types = defaultTypes) {
const res = {};
types.forEach(type => (res[type] = `${ base }_${ type }`));
types.forEach(type => res[type] = `${ base }_${ type }`);
return res;
}

View File

@ -125,15 +125,15 @@ const keyCommands = [
discoverabilityTitle: I18n.t('Add_server')
},
// Refers to select rooms on list
...([1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
...[1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
input: `${ value }`,
modifierFlags: constants.keyModifierCommand
}))),
})),
// Refers to select servers on list
...([1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
...[1, 2, 3, 4, 5, 6, 7, 8, 9].map(value => ({
input: `${ value }`,
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate
})))
}))
];
export const setKeyCommands = () => KeyCommands.setKeyCommands(keyCommands);

View File

@ -3,12 +3,12 @@ export const STATUS_COLORS: any = {
busy: '#f5455c',
away: '#ffd21f',
offline: '#cbced1',
loading: '#9ea2a8'
loading: '#9ea2a8',
};
export const SWITCH_TRACK_COLOR = {
false: '#f5455c',
true: '#2de0a5'
true: '#2de0a5',
};
const mentions = {
@ -16,7 +16,7 @@ const mentions = {
tunreadColor: '#1d74f5',
mentionMeColor: '#F5455C',
mentionGroupColor: '#F38C39',
mentionOtherColor: '#F3BE08'
mentionOtherColor: '#F3BE08',
};
export const themes: any = {
@ -65,7 +65,7 @@ export const themes: any = {
previewBackground: '#1F2329',
previewTintColor: '#ffffff',
backdropOpacity: 0.3,
...mentions
...mentions,
},
dark: {
backgroundColor: '#030b1b',
@ -112,7 +112,7 @@ export const themes: any = {
previewBackground: '#030b1b',
previewTintColor: '#ffffff',
backdropOpacity: 0.9,
...mentions
...mentions,
},
black: {
backgroundColor: '#000000',
@ -159,6 +159,6 @@ export const themes: any = {
previewBackground: '#000000',
previewTintColor: '#ffffff',
backdropOpacity: 0.9,
...mentions
}
...mentions,
},
};

View File

@ -1,5 +1,5 @@
export default {
SENT: 0,
TEMP: 1,
ERROR: 2
ERROR: 2,
};

View File

@ -1,206 +1,206 @@
export default {
Accounts_AllowEmailChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowPasswordChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowRealNameChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowUserAvatarChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowUserProfileChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowUserStatusMessageChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowUsernameChange: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AvatarBlockUnauthenticatedAccess: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_CustomFields: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_EmailOrUsernamePlaceholder: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_EmailVerification: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_NamePlaceholder: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_PasswordPlaceholder: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_PasswordReset: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_RegistrationForm: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_RegistrationForm_LinkReplacementText: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_ShowFormLogin: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_ManuallyApproveNewUsers: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
API_Use_REST_For_DDP_Calls: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_iframe_enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_Iframe_api_url: {
type: 'valueAsString'
type: 'valueAsString',
},
Accounts_Iframe_api_method: {
type: 'valueAsString'
type: 'valueAsString',
},
CROWD_Enable: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
DirectMesssage_maxUsers: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
E2E_Enable: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_Directory_DefaultView: {
type: 'valueAsString'
type: 'valueAsString',
},
FEDERATION_Enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Hide_System_Messages: {
type: 'valueAsArray'
type: 'valueAsArray',
},
LDAP_Enable: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Livechat_request_comment_when_closing_conversation: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_Enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_SSL: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_Domain: {
type: 'valueAsString'
type: 'valueAsString',
},
Jitsi_Enabled_TokenAuth: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_URL_Room_Hash: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_URL_Room_Prefix: {
type: 'valueAsString'
type: 'valueAsString',
},
Message_AllowDeleting: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_AllowDeleting_BlockDeleteInMinutes: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
Message_AllowEditing: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_AllowEditing_BlockEditInMinutes: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
Message_AllowPinning: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_AllowStarring: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_AudioRecorderEnabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_GroupingPeriod: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
Message_TimeFormat: {
type: 'valueAsString'
type: 'valueAsString',
},
Message_TimeAndDateFormat: {
type: 'valueAsString'
type: 'valueAsString',
},
Site_Name: {
type: 'valueAsString'
type: 'valueAsString',
},
Site_Url: {
type: 'valueAsString'
type: 'valueAsString',
},
Store_Last_Message: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
uniqueID: {
type: 'valueAsString'
type: 'valueAsString',
},
UI_Allow_room_names_with_special_chars: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
UI_Use_Real_Name: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Assets_favicon_512: {
type: null
type: null,
},
Message_Read_Receipt_Enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Message_Read_Receipt_Store_Users: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Threads_enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
FileUpload_MediaTypeWhiteList: {
type: 'valueAsString'
type: 'valueAsString',
},
FileUpload_MaxFileSize: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
API_Gitlab_URL: {
type: 'valueAsString'
type: 'valueAsString',
},
AutoTranslate_Enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
CAS_enabled: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
CAS_login_url: {
type: 'valueAsString'
type: 'valueAsString',
},
Force_Screen_Lock: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Force_Screen_Lock_After: {
type: 'valueAsNumber'
type: 'valueAsNumber',
},
Allow_Save_Media_to_Gallery: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Accounts_AllowInvisibleStatusOption: {
type: 'valueAsString'
type: 'valueAsString',
},
Jitsi_Enable_Teams: {
type: 'valueAsBoolean'
type: 'valueAsBoolean',
},
Jitsi_Enable_Channels: {
type: 'valuesAsBoolean'
}
type: 'valuesAsBoolean',
},
};

View File

@ -1,17 +1,17 @@
import React, {
forwardRef,
isValidElement,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
useEffect,
forwardRef,
useImperativeHandle,
useCallback,
isValidElement
} from 'react';
import { Keyboard, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { TapGestureHandler, State } from 'react-native-gesture-handler';
import { State, TapGestureHandler } from 'react-native-gesture-handler';
import ScrollBottomSheet from 'react-native-scroll-bottom-sheet';
import Animated, { Extrapolate, interpolate, Value, Easing} from 'react-native-reanimated';
import Animated, { Easing, Extrapolate, Value, interpolate } from 'react-native-reanimated';
import * as Haptics from 'expo-haptics';
import { useBackHandler } from '@react-native-community/hooks';
@ -20,10 +20,10 @@ import { Handle } from './Handle';
import { Button } from './Button';
import { themes } from '../../constants/colors';
import styles, { ITEM_HEIGHT } from './styles';
import { isTablet, isIOS } from '../../utils/deviceInfo';
import { isIOS, isTablet } from '../../utils/deviceInfo';
import * as List from '../List';
import I18n from '../../i18n';
import { useOrientation, useDimensions, IDimensionsContextProps } from '../../dimensions';
import { IDimensionsContextProps, useDimensions, useOrientation } from '../../dimensions';
interface IActionSheetData {
options: any;
@ -43,7 +43,7 @@ const ANIMATION_DURATION = 250;
const ANIMATION_CONFIG = {
duration: ANIMATION_DURATION,
// https://easings.net/#easeInOutCubic
easing: Easing.bezier(0.645, 0.045, 0.355, 1.0)
easing: Easing.bezier(0.645, 0.045, 0.355, 1.0),
};
const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.Element; theme: string}, ref) => {
@ -55,8 +55,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
const insets = useSafeAreaInsets();
const maxSnap = Math.max(
(
height!
height!
// Items height
- (ITEM_HEIGHT * (data?.options?.length || 0))
// Handle height
@ -67,8 +67,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
- insets.bottom
// Cancel button height
- (data?.hasCancel ? CANCEL_HEIGHT : 0)
),
MAX_SNAP_HEIGHT
,
MAX_SNAP_HEIGHT,
);
/*
@ -121,7 +121,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
useImperativeHandle(ref, () => ({
showActionSheet: show,
hideActionSheet: hide
hideActionSheet: hide,
}));
const renderHandle = useCallback(() => (
@ -149,7 +149,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
const opacity = interpolate(animatedPosition.current, {
inputRange: [0, 1],
outputRange: [0, themes[theme].backdropOpacity],
extrapolate: Extrapolate.CLAMP
extrapolate: Extrapolate.CLAMP,
});
return (
@ -164,8 +164,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
styles.backdrop,
{
backgroundColor: themes[theme].backdropColor,
opacity
}
opacity,
},
]}
/>
</TapGestureHandler>
@ -176,12 +176,12 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
snapPoints={snaps}
initialSnapIndex={closedSnapIndex}
renderHandle={renderHandle}
onSettle={index => (index === closedSnapIndex) && toggleVisible()}
onSettle={(index) => (index === closedSnapIndex) && toggleVisible()}
animatedPosition={animatedPosition.current}
containerStyle={[
styles.container,
{ backgroundColor: themes[theme].focusedBackground },
(isLandscape || isTablet) && styles.bottomSheet
(isLandscape || isTablet) && styles.bottomSheet,
] as any}
animationConfig={ANIMATION_CONFIG}
// FlatList props

View File

@ -1,4 +1,4 @@
import React, {useRef, useContext, forwardRef, ForwardedRef} from 'react';
import React, { ForwardedRef, forwardRef, useContext, useRef } from 'react';
import ActionSheet from './ActionSheet';
import { useTheme } from '../../theme';
@ -10,7 +10,7 @@ interface IActionSheetProvider {
const context: IActionSheetProvider = React.createContext({
showActionSheet: () => {},
hideActionSheet: () => {}
hideActionSheet: () => {},
});
export const useActionSheet = () => useContext(context);
@ -33,7 +33,7 @@ export const ActionSheetProvider = React.memo(({ children }: {children: JSX.Elem
},
hideActionSheet: () => {
ref.current?.hideActionSheet();
}
},
});
return (

View File

@ -8,46 +8,46 @@ export default StyleSheet.create({
container: {
overflow: 'hidden',
borderTopLeftRadius: 16,
borderTopRightRadius: 16
borderTopRightRadius: 16,
},
item: {
paddingHorizontal: 16,
height: ITEM_HEIGHT,
alignItems: 'center',
flexDirection: 'row'
flexDirection: 'row',
},
separator: {
marginHorizontal: 16
marginHorizontal: 16,
},
content: {
paddingTop: 16
paddingTop: 16,
},
titleContainer: {
flex: 1
flex: 1,
},
title: {
fontSize: 16,
marginLeft: 16,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
handle: {
justifyContent: 'center',
alignItems: 'center',
paddingBottom: 8
paddingBottom: 8,
},
handleIndicator: {
width: 40,
height: 4,
borderRadius: 4,
margin: 8
margin: 8,
},
backdrop: {
...StyleSheet.absoluteFillObject
...StyleSheet.absoluteFillObject,
},
bottomSheet: {
width: '50%',
alignSelf: 'center',
left: '25%'
left: '25%',
},
button: {
marginHorizontal: 16,
@ -55,14 +55,14 @@ export default StyleSheet.create({
justifyContent: 'center',
height: ITEM_HEIGHT,
borderRadius: 2,
marginBottom: 12
marginBottom: 12,
},
text: {
fontSize: 16,
...sharedStyles.textMedium,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
rightContainer: {
paddingLeft: 12
}
paddingLeft: 12,
},
});

View File

@ -1,5 +1,6 @@
import React from 'react';
import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-native';
import { themes } from '../constants/colors';
type TTheme = 'light' | 'dark' | 'black' | string;
@ -13,7 +14,7 @@ interface IActivityIndicator extends ActivityIndicatorProps{
const styles = StyleSheet.create({
indicator: {
padding: 16,
flex: 1
flex: 1,
},
absolute: {
position: 'absolute',
@ -22,8 +23,8 @@ const styles = StyleSheet.create({
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}
justifyContent: 'center',
},
});
const RCActivityIndicator = ({ theme = 'light', absolute, ...props }: IActivityIndicator) => (

View File

@ -1,5 +1,5 @@
import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import { themes } from '../constants/colors';
import sharedStyles from '../views/Styles';
@ -9,15 +9,15 @@ import I18n from '../i18n';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'flex-end'
justifyContent: 'flex-end',
},
text: {
...sharedStyles.textRegular,
fontSize: 13
fontSize: 13,
},
bold: {
...sharedStyles.textSemibold
}
...sharedStyles.textSemibold,
},
});
const AppVersion = React.memo(({ theme }: {theme: string}) => (

View File

@ -6,11 +6,11 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk';
import { avatarURL } from '../../utils/avatar';
import Emoji from '../markdown/Emoji';
import {IAvatar} from './interfaces';
import { IAvatar } from './interfaces';
const Avatar = React.memo(({
server,
style,
style,
avatar,
children,
user,
@ -23,12 +23,11 @@ const Avatar = React.memo(({
rid,
blockUnauthenticatedAccess,
serverVersion,
text,
size = 25,
borderRadius = 4,
type = 'd',
text,
size = 25,
borderRadius = 4,
type = 'd',
}: Partial<IAvatar>) => {
if ((!text && !avatar && !emoji && !rid) || !server) {
return null;
}
@ -36,7 +35,7 @@ const Avatar = React.memo(({
const avatarStyle = {
width: size,
height: size,
borderRadius
borderRadius,
};
let image;
@ -64,7 +63,7 @@ const Avatar = React.memo(({
avatarETag,
serverVersion,
rid,
blockUnauthenticatedAccess
blockUnauthenticatedAccess,
});
}
@ -74,7 +73,7 @@ const Avatar = React.memo(({
source={{
uri,
headers: RocketChatSettings.customHeaders,
priority: FastImage.priority.high
priority: FastImage.priority.high,
}}
/>
);

View File

@ -5,16 +5,16 @@ import { Q } from '@nozbe/watermelondb';
import database from '../../lib/database';
import { getUserSelector } from '../../selectors/login';
import Avatar from './Avatar';
import {IAvatar} from "./interfaces";
import { IAvatar } from './interfaces';
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
private mounted: boolean;
private subscription!: any;
static defaultProps = {
text: '',
type: 'd'
type: 'd',
};
constructor(props: Partial<IAvatar>) {
@ -46,7 +46,7 @@ class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
return type === 'd';
}
init = async() => {
init = async () => {
const db = database.active;
const usersCollection = db.get('users');
const subsCollection = db.get('subscriptions');
@ -99,6 +99,6 @@ const mapStateToProps = (state: any) => ({
blockUnauthenticatedAccess:
state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess
?? state.settings.Accounts_AvatarBlockUnauthenticatedAccess
?? true
?? true,
});
export default connect(mapStateToProps)(AvatarContainer);

View File

@ -1,23 +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;
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

@ -2,9 +2,9 @@
import React from 'react';
import { storiesOf } from '@storybook/react-native';
import BackgroundContainer from '.';
import { ThemeContext } from '../../theme';
import { longText } from '../../../storybook/utils';
import BackgroundContainer from '.';
const stories = storiesOf('BackgroundContainer', module);

View File

@ -1,5 +1,5 @@
import React from 'react';
import { ImageBackground, StyleSheet, Text, View, ActivityIndicator } from 'react-native';
import { ActivityIndicator, ImageBackground, StyleSheet, Text, View } from 'react-native';
import { withTheme } from '../../theme';
import sharedStyles from '../../views/Styles';
@ -13,12 +13,12 @@ interface IBackgroundContainer {
const styles = StyleSheet.create({
container: {
flex: 1
flex: 1,
},
image: {
width: '100%',
height: '100%',
position: 'absolute'
position: 'absolute',
},
text: {
position: 'absolute',
@ -28,15 +28,15 @@ const styles = StyleSheet.create({
fontSize: 16,
paddingHorizontal: 24,
...sharedStyles.textRegular,
...sharedStyles.textAlignCenter
}
...sharedStyles.textAlignCenter,
},
});
const BackgroundContainer = ({ theme, text, loading }: IBackgroundContainer) => (
<View style={styles.container}>
<ImageBackground source={{ uri: `message_empty_${ theme }` }} style={styles.image} />
{text ? <Text style={[styles.text, { color: themes[theme].auxiliaryTintColor }]}>{text}</Text> : null}
{/*@ts-ignore*/}
{/* @ts-ignore*/}
{loading ? <ActivityIndicator style={[styles.text, { color: themes[theme].auxiliaryTintColor }]} /> : null}
</View>
);

View File

@ -26,26 +26,25 @@ const styles = StyleSheet.create({
justifyContent: 'center',
height: 48,
borderRadius: 2,
marginBottom: 12
marginBottom: 12,
},
text: {
fontSize: 16,
...sharedStyles.textMedium,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
disabled: {
opacity: 0.3
}
opacity: 0.3,
},
});
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
loading: false,
}
render() {
@ -69,7 +68,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
? { backgroundColor }
: { backgroundColor: isPrimary ? themes[theme!].actionTintColor : themes[theme!].backgroundColor },
disabled && styles.disabled,
style
style,
]}
{...otherProps}
>
@ -81,7 +80,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
style={[
styles.text,
{ color: textColor },
fontSize && { fontSize }
fontSize && { fontSize },
]}
accessibilityLabel={title}
>

View File

@ -12,8 +12,8 @@ const styles = StyleSheet.create({
icon: {
width: 22,
height: 22,
marginHorizontal: 15
}
marginHorizontal: 15,
},
});
const Check = React.memo(({ theme, style }: ICheck) => <CustomIcon style={[styles.icon, style]} color={themes[theme].tintColor} size={22} name='check' />);

View File

@ -1,13 +1,14 @@
import React from 'react';
import FastImage from '@rocket.chat/react-native-fast-image';
import {ICustomEmoji} from "./interfaces";
import { ICustomEmoji } from './interfaces';
const CustomEmoji = React.memo(({ baseUrl, emoji, style }: ICustomEmoji) => (
<FastImage
style={style}
source={{
uri: `${ baseUrl }/emoji-custom/${ encodeURIComponent(emoji.content || emoji.name) }.${ emoji.extension }`,
priority: FastImage.priority.high
priority: FastImage.priority.high,
}}
resizeMode={FastImage.resizeMode.contain}
/>

View File

@ -1,11 +1,11 @@
import React from 'react';
import { Text, TouchableOpacity, FlatList } from 'react-native';
import { FlatList, Text, TouchableOpacity } from 'react-native';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
import styles from './styles';
import CustomEmoji from './CustomEmoji';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import {IEmoji, IEmojiCategory} from "./interfaces";
import { IEmoji, IEmojiCategory } from './interfaces';
const EMOJI_SIZE = 50;
@ -21,7 +21,6 @@ const renderEmoji = (emoji: IEmoji, size: number, baseUrl: string) => {
};
class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
renderItem(emoji: any) {
const { baseUrl, onEmojiSelected } = this.props;
return (
@ -52,7 +51,7 @@ class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
contentContainerStyle={{ marginHorizontal }}
// rerender FlatList in case of width changes
key={`emoji-category-${ width }`}
keyExtractor={item => (item && item.isCustom && item.content) || item}
keyExtractor={(item) => (item && item.isCustom && item.content) || item}
data={emojis}
extraData={this.props}
renderItem={({ item }) => this.renderItem(item)}

View File

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

View File

@ -2,43 +2,43 @@ const list = ['frequentlyUsed', 'custom', 'people', 'nature', 'food', 'activity'
const tabs = [
{
tabLabel: '🕒',
category: list[0]
category: list[0],
},
{
tabLabel: '🚀',
category: list[1]
category: list[1],
},
{
tabLabel: '😃',
category: list[2]
category: list[2],
},
{
tabLabel: '🐶',
category: list[3]
category: list[3],
},
{
tabLabel: '🍔',
category: list[4]
category: list[4],
},
{
tabLabel: '⚽',
category: list[5]
category: list[5],
},
{
tabLabel: '🚌',
category: list[6]
category: list[6],
},
{
tabLabel: '💡',
category: list[7]
category: list[7],
},
{
tabLabel: '💛',
category: list[8]
category: list[8],
},
{
tabLabel: '🏁',
category: list[9]
}
category: list[9],
},
];
export default { list, tabs };

View File

@ -17,11 +17,11 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
import log from '../../utils/log';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
import {IEmoji} from "./interfaces";
import { IEmoji } from './interfaces';
const scrollProps = {
keyboardShouldPersistTaps: 'always',
keyboardDismissMode: 'none'
keyboardDismissMode: 'none',
};
interface IEmojiPickerProps {
@ -43,21 +43,20 @@ interface IEmojiPickerState {
}
class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
constructor(props: IEmojiPickerProps) {
super(props);
const customEmojis = Object.keys(props.customEmojis)
.filter(item => item === props.customEmojis[item].name)
.map(item => ({
.filter((item) => item === props.customEmojis[item].name)
.map((item) => ({
content: props.customEmojis[item].name,
extension: props.customEmojis[item].extension,
isCustom: true
isCustom: true,
}));
this.state = {
frequentlyUsed: [],
customEmojis,
show: false,
width: null
width: null,
};
}
@ -89,7 +88,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
const { onEmojiSelected } = this.props;
if (emoji.isCustom) {
this._addFrequentlyUsed({
content: emoji.content, extension: emoji.extension, isCustom: true
content: emoji.content, extension: emoji.extension, isCustom: true,
});
onEmojiSelected!(`:${ emoji.content }:`);
} else {
@ -104,7 +103,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
}
// eslint-disable-next-line react/sort-comp
_addFrequentlyUsed = protectedFunction(async(emoji: IEmoji) => {
_addFrequentlyUsed = protectedFunction(async (emoji: IEmoji) => {
const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojiRecord: any;
@ -114,7 +113,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
// Do nothing
}
await db.action(async() => {
await db.action(async () => {
if (freqEmojiRecord) {
await freqEmojiRecord.update((f: any) => {
f.count += 1;
@ -129,7 +128,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
});
})
updateFrequentlyUsed = async() => {
updateFrequentlyUsed = async () => {
const db = database.active;
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
@ -159,7 +158,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
return (
<EmojiCategory
emojis={emojis}
onEmojiSelected={emoji => this.onEmojiSelected(emoji)}
onEmojiSelected={(emoji) => this.onEmojiSelected(emoji)}
style={styles.categoryContainer}
width={width!}
baseUrl={baseUrl}
@ -179,16 +178,15 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
<View onLayout={this.onLayout} style={{ flex: 1 }}>
<ScrollableTabView
renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} theme={theme} />}
/*@ts-ignore*/
/* @ts-ignore*/
contentProps={scrollProps}
style={{ backgroundColor: themes[theme!].focusedBackground }}
>
{
categories.tabs.map((tab, i) => (
(i === 0 && frequentlyUsed.length === 0) ? null // when no frequentlyUsed don't show the tab
: (
this.renderCategory(tab.category, i, tab.tabLabel)
)))
i === 0 && frequentlyUsed.length === 0 ? null // when no frequentlyUsed don't show the tab
: this.renderCategory(tab.category, i, tab.tabLabel)
))
}
</ScrollableTabView>
</View>
@ -197,7 +195,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
}
const mapStateToProps = (state: any) => ({
customEmojis: state.customEmojis
customEmojis: state.customEmojis,
});
export default connect(mapStateToProps)(withTheme(EmojiPicker));

View File

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

View File

@ -4,29 +4,29 @@ import sharedStyles from '../../views/Styles';
export default StyleSheet.create({
container: {
flex: 1
flex: 1,
},
tabsContainer: {
height: 45,
flexDirection: 'row',
paddingTop: 5
paddingTop: 5,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingBottom: 10
paddingBottom: 10,
},
tabEmoji: {
fontSize: 20,
color: 'black'
color: 'black',
},
activeTabLine: {
position: 'absolute',
left: 0,
right: 0,
height: 2,
bottom: 0
bottom: 0,
},
tabLine: {
position: 'absolute',
@ -34,25 +34,25 @@ export default StyleSheet.create({
right: 0,
height: 2,
backgroundColor: 'rgba(0,0,0,0.05)',
bottom: 0
bottom: 0,
},
categoryContainer: {
flex: 1,
alignItems: 'flex-start'
alignItems: 'flex-start',
},
categoryInner: {
flexWrap: 'wrap',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
flex: 1
flex: 1,
},
categoryEmoji: {
...sharedStyles.textAlignCenter,
backgroundColor: 'transparent',
color: '#ffffff'
color: '#ffffff',
},
customCategoryEmoji: {
margin: 8
}
margin: 8,
},
});

View File

@ -18,8 +18,8 @@ interface IFormContainer {
const styles = StyleSheet.create({
scrollView: {
minHeight: '100%'
}
minHeight: '100%',
},
});
export const FormContainerInner = ({ children }: {children: JSX.Element}) => (
@ -36,7 +36,7 @@ const FormContainer = ({ children, theme, testID, ...props }: IFormContainer) =>
keyboardVerticalOffset={128}
>
<StatusBar />
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<ScrollView
style={sharedStyles.container}
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}

View File

@ -1,6 +1,7 @@
import React from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { themes } from '../../constants/colors';
import { themedHeader } from '../../utils/navigation';
import { isIOS, isTablet } from '../../utils/deviceInfo';
@ -13,9 +14,8 @@ export const getHeaderHeight = (isLandscape: boolean) => {
if (isIOS) {
if (isLandscape && !isTablet) {
return 32;
} else {
return 44;
}
return 44;
}
return 56;
};
@ -30,7 +30,7 @@ interface IHeaderTitlePosition {
export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
left: insets.left + 60,
right: insets.right + Math.max(45 * numIconsRight, 15)
right: insets.right + Math.max(45 * numIconsRight, 15),
});
const styles = StyleSheet.create({
@ -38,8 +38,8 @@ const styles = StyleSheet.create({
height: headerHeight,
flexDirection: 'row',
justifyContent: 'center',
elevation: 4
}
elevation: 4,
},
});
interface IHeader {

View File

@ -18,7 +18,7 @@ export const Drawer = React.memo(({ navigation, testID, ...props }: Partial<IHea
</Container>
));
export const CloseModal = React.memo(({navigation, testID, onPress = () => navigation.pop(), ...props}: IHeaderButtonCommon) => (
export const CloseModal = React.memo(({ navigation, testID, onPress = () => navigation.pop(), ...props }: IHeaderButtonCommon) => (
<Container left>
<Item iconName='close' onPress={onPress} testID={testID} {...props} />
</Container>

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
interface IHeaderButtonContainer {
children: JSX.Element;
@ -10,14 +10,14 @@ const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
left: {
marginLeft: 5
marginLeft: 5,
},
right: {
marginRight: 5
}
marginRight: 5,
},
});
const Container = ({ children, left = false }: IHeaderButtonContainer) => (

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Text, StyleSheet, Platform } from 'react-native';
import { Platform, StyleSheet, Text } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import { CustomIcon } from '../../lib/Icons';
@ -17,27 +17,27 @@ interface IHeaderButtonItem {
}
export const BUTTON_HIT_SLOP = {
top: 5, right: 5, bottom: 5, left: 5
top: 5, right: 5, bottom: 5, left: 5,
};
const styles = StyleSheet.create({
container: {
marginHorizontal: 6
marginHorizontal: 6,
},
title: {
...Platform.select({
android: {
fontSize: 14
fontSize: 14,
},
default: {
fontSize: 17
}
fontSize: 17,
},
}),
...sharedStyles.textRegular
}
...sharedStyles.textRegular,
},
});
const Item = ({title, iconName, onPress, testID, theme, badge}: IHeaderButtonItem) => (
const Item = ({ title, iconName, onPress, testID, theme, badge }: IHeaderButtonItem) => (
<Touchable onPress={onPress} testID={testID} hitSlop={BUTTON_HIT_SLOP} style={styles.container}>
<>
{

View File

@ -11,8 +11,8 @@ const styles = StyleSheet.create({
top: -3,
borderRadius: 10,
alignItems: 'center',
justifyContent: 'center'
}
justifyContent: 'center',
},
});
export const Badge = ({ ...props }) => (

View File

@ -1,5 +1,5 @@
import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import { connect } from 'react-redux';
import { Notifier } from 'react-native-notifier';
@ -32,36 +32,36 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
marginHorizontal: 10,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 4
borderRadius: 4,
},
content: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
inner: {
flex: 1
flex: 1,
},
avatar: {
marginRight: 10
marginRight: 10,
},
roomName: {
fontSize: 17,
lineHeight: 20,
...sharedStyles.textMedium
...sharedStyles.textMedium,
},
message: {
fontSize: 14,
lineHeight: 17,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
close: {
marginLeft: 10
marginLeft: 10,
},
small: {
width: '50%',
alignSelf: 'center'
}
alignSelf: 'center',
},
});
const hideNotification = () => Notifier.hideNotification();
@ -83,7 +83,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
return;
}
const item = {
rid, name: title, t: type, prid
rid, name: title, t: type, prid,
};
if (isMasterDetail) {
@ -102,8 +102,8 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
{
backgroundColor: themes[theme].focusedBackground,
borderColor: themes[theme].separatorColor,
marginTop: insets.top
}
marginTop: insets.top,
},
]}
>
<Touchable
@ -132,7 +132,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
});
const mapStateToProps = (state: any) => ({
isMasterDetail: state.app.isMasterDetail
isMasterDetail: state.app.isMasterDetail,
});
export default connect(mapStateToProps)(NotifierComponent);

View File

@ -1,5 +1,5 @@
import React, { memo, useEffect } from 'react';
import { NotifierRoot, Notifier, Easing } from 'react-native-notifier';
import { Easing, Notifier, NotifierRoot } from 'react-native-notifier';
import { connect } from 'react-redux';
import { dequal } from 'dequal';
@ -27,8 +27,8 @@ const InAppNotification = memo(({ rooms, appState }: {rooms: any, appState: stri
showEasing: Easing.inOut(Easing.quad),
Component: NotifierComponent,
componentProps: {
notification
}
notification,
},
});
}
};
@ -45,7 +45,7 @@ const InAppNotification = memo(({ rooms, appState }: {rooms: any, appState: stri
const mapStateToProps = (state: any) => ({
rooms: state.room.rooms,
appState: state.app.ready && state.app.foreground ? 'foreground' : 'background'
appState: state.app.ready && state.app.foreground ? 'foreground' : 'background',
});
export default connect(mapStateToProps)(InAppNotification);

View File

@ -1,12 +1,13 @@
import React from 'react';
import { ScrollView, StyleSheet } from 'react-native';
import { withTheme } from '../../theme';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
const styles = StyleSheet.create({
container: {
paddingVertical: 16
}
paddingVertical: 16,
},
});
interface IListContainer {

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import sharedStyles from '../../views/Styles';
import { themes } from '../../constants/colors';
@ -10,12 +10,12 @@ import { PADDING_HORIZONTAL } from './constants';
const styles = StyleSheet.create({
container: {
paddingBottom: 12,
paddingHorizontal: PADDING_HORIZONTAL
paddingHorizontal: PADDING_HORIZONTAL,
},
title: {
fontSize: 16,
...sharedStyles.textRegular
}
...sharedStyles.textRegular,
},
});
interface IListHeader {

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
@ -17,8 +17,8 @@ interface IListIcon {
const styles = StyleSheet.create({
icon: {
alignItems: 'center',
justifyContent: 'center'
}
justifyContent: 'center',
},
});
const ListIcon = React.memo(({ theme, name, color, style, testID }: IListIcon) => (

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import sharedStyles from '../../views/Styles';
import { themes } from '../../constants/colors';
@ -10,12 +10,12 @@ import I18n from '../../i18n';
const styles = StyleSheet.create({
container: {
paddingTop: 8,
paddingHorizontal: PADDING_HORIZONTAL
paddingHorizontal: PADDING_HORIZONTAL,
},
text: {
fontSize: 14,
...sharedStyles.textRegular
}
...sharedStyles.textRegular,
},
});
interface IListHeader {

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet, I18nManager } from 'react-native';
import { I18nManager, StyleSheet, Text, View } from 'react-native';
import Touch from '../../utils/touch';
import { themes } from '../../constants/colors';
@ -17,42 +17,42 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: PADDING_HORIZONTAL
paddingHorizontal: PADDING_HORIZONTAL,
},
leftContainer: {
paddingRight: PADDING_HORIZONTAL
paddingRight: PADDING_HORIZONTAL,
},
rightContainer: {
paddingLeft: PADDING_HORIZONTAL
paddingLeft: PADDING_HORIZONTAL,
},
disabled: {
opacity: 0.3
opacity: 0.3,
},
textContainer: {
flex: 1,
justifyContent: 'center'
justifyContent: 'center',
},
textAlertContainer: {
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
alertIcon: {
paddingLeft: 4
paddingLeft: 4,
},
title: {
flexShrink: 1,
fontSize: 16,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
subtitle: {
fontSize: 14,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
actionIndicator: {
...I18nManager.isRTL
? { transform: [{ rotate: '180deg' }] }
: {}
}
: {},
},
});
interface IListItemContent {
@ -72,7 +72,7 @@ interface IListItemContent {
}
const Content = React.memo(({
title, subtitle, disabled, testID, left, right, color, theme, fontScale, alert, translateTitle = true, translateSubtitle = true, showActionIndicator = false
title, subtitle, disabled, testID, left, right, color, theme, fontScale, alert, translateTitle = true, translateSubtitle = true, showActionIndicator = false,
}: IListItemContent) => (
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale! }]} testID={testID}>
{left

View File

@ -1,12 +1,13 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { withTheme } from '../../theme';
import { Header } from '.';
const styles = StyleSheet.create({
container: {
marginVertical: 16
}
marginVertical: 16,
},
});
interface IListSection {

View File

@ -1,13 +1,13 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { themes } from '../../constants/colors';
import { withTheme } from '../../theme';
const styles = StyleSheet.create({
separator: {
height: StyleSheet.hairlineWidth
}
height: StyleSheet.hairlineWidth,
},
});
interface IListSeparator {
@ -20,7 +20,7 @@ const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
style={[
styles.separator,
style,
{ backgroundColor: themes[theme].separatorColor }
{ backgroundColor: themes[theme].separatorColor },
]}
/>
));

View File

@ -2,6 +2,6 @@ import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
contentContainerStyleFlatList: {
paddingVertical: 32
}
paddingVertical: 32,
},
});

View File

@ -1,5 +1,6 @@
import React from 'react';
import { StyleSheet, Modal, Animated , View } from 'react-native';
import { Animated, Modal, StyleSheet, View } from 'react-native';
import { withTheme } from '../theme';
import { themes } from '../constants/colors';
@ -7,13 +8,13 @@ const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
image: {
width: 100,
height: 100,
resizeMode: 'contain'
}
resizeMode: 'contain',
},
});
interface ILoadingProps {
@ -22,12 +23,13 @@ interface ILoadingProps {
}
class Loading extends React.PureComponent<ILoadingProps, any> {
state = {
scale: new Animated.Value(1),
opacity: new Animated.Value(0)
opacity: new Animated.Value(0),
}
private opacityAnimation: any;
private scaleAnimation: any;
componentDidMount() {
@ -39,8 +41,8 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
{
toValue: 1,
duration: 200,
useNativeDriver: true
}
useNativeDriver: true,
},
);
this.scaleAnimation = Animated.loop(Animated.sequence([
Animated.timing(
@ -48,17 +50,17 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
{
toValue: 0,
duration: 1000,
useNativeDriver: true
}
useNativeDriver: true,
},
),
Animated.timing(
scale,
{
toValue: 1,
duration: 1000,
useNativeDriver: true
}
)
useNativeDriver: true,
},
),
]));
if (visible) {
@ -97,13 +99,13 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
const scaleAnimation = scale.interpolate({
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'
extrapolate: 'clamp',
});
return (
@ -121,15 +123,15 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
// @ts-ignore
...StyleSheet.absoluteFill,
backgroundColor: themes[theme].backdropColor,
opacity: opacityAnimation
opacity: opacityAnimation,
}]}
/>
<Animated.Image
source={require('../static/images/logo.png')}
style={[styles.image, {
transform: [{
scale: scaleAnimation
}]
scale: scaleAnimation,
}],
}]}
/>
</View>
@ -138,4 +140,4 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
}
}
export default (withTheme(Loading));
export default withTheme(Loading);

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet, Text, Animated, Easing, Linking } from 'react-native';
import { Animated, Easing, Linking, StyleSheet, Text, View } from 'react-native';
import { connect } from 'react-redux';
import { Base64 } from 'js-base64';
import * as AppleAuthentication from 'expo-apple-authentication';
@ -12,7 +12,7 @@ import OrSeparator from './OrSeparator';
import Touch from '../utils/touch';
import I18n from '../i18n';
import random from '../utils/random';
import { logEvent, events } from '../utils/log';
import { events, logEvent } from '../utils/log';
import RocketChat from '../lib/rocketchat';
import { CustomIcon } from '../lib/Icons';
@ -27,7 +27,7 @@ const LOGIN_STYPE_REDIRECT = 'redirect';
const styles = StyleSheet.create({
serviceButton: {
borderRadius: BORDER_RADIUS,
marginBottom: 10
marginBottom: 10,
},
serviceButtonContainer: {
borderRadius: BORDER_RADIUS,
@ -36,25 +36,25 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 15
paddingHorizontal: 15,
},
serviceIcon: {
position: 'absolute',
left: 15,
top: 12,
width: 24,
height: 24
height: 24,
},
serviceText: {
...sharedStyles.textRegular,
fontSize: 16
fontSize: 16,
},
serviceName: {
...sharedStyles.textSemibold
...sharedStyles.textSemibold,
},
options: {
marginBottom: 0
}
marginBottom: 0,
},
});
interface IOpenOAuth {
@ -94,12 +94,12 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
private _animation: any;
static defaultProps = {
separator: true
separator: true,
}
state = {
collapsed: true,
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT),
}
onPressFacebook = () => {
@ -198,7 +198,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
logEvent(events.ENTER_WITH_CUSTOM_OAUTH);
const { server } = this.props;
const {
serverURL, authorizePath, clientId, scope, service
serverURL, authorizePath, clientId, scope, service,
} = loginService;
const redirectUri = `${ server }/_oauth/${ service }`;
const state = this.getOAuthState();
@ -227,14 +227,14 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
this.openOAuth({ url, ssoToken, authType: 'cas' });
}
onPressAppleLogin = async() => {
onPressAppleLogin = async () => {
logEvent(events.ENTER_WITH_APPLE);
try {
const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL
]
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
await RocketChat.loginOAuthOrSso({ fullName, email, identityToken });
@ -249,7 +249,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
if (loginStyle === LOGIN_STYPE_REDIRECT) {
obj = {
...obj,
redirectUrl: 'rocketchat://auth'
redirectUrl: 'rocketchat://auth',
};
}
return Base64.encodeURI(JSON.stringify(obj));
@ -270,7 +270,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
toValue: height,
duration: 300,
// @ts-ignore
easing: Easing.easeOutCubic
easing: Easing.easeOutCubic,
}).start();
}
@ -295,7 +295,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
linkedin: this.onPressLinkedin,
'meteor-developer': this.onPressMeteor,
twitter: this.onPressTwitter,
wordpress: this.onPressWordpress
wordpress: this.onPressWordpress,
};
return oauthProviders[name];
}
@ -396,7 +396,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
const { length } = Object.values(services);
const style = {
overflow: 'hidden',
height: servicesHeight
height: servicesHeight,
};
if (length > 3 && separator) {
@ -423,7 +423,7 @@ const mapStateToProps = (state: any) => ({
Gitlab_URL: state.settings.API_Gitlab_URL,
CAS_enabled: state.settings.CAS_enabled,
CAS_login_url: state.settings.CAS_login_url,
services: state.login.services
services: state.login.services,
});
export default connect(mapStateToProps)(withTheme(LoginServices));

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState, useCallback } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import React, { useCallback, useEffect, useState } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import { withTheme } from '../../theme';
import { themes } from '../../constants/colors';
@ -10,7 +10,7 @@ import database from '../../lib/database';
import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions';
import sharedStyles from '../../views/Styles';
import {IEmoji} from "../EmojiPicker/interfaces";
import { IEmoji } from '../EmojiPicker/interfaces';
interface IHeader {
handleReaction: Function;
@ -40,7 +40,7 @@ const ITEM_MARGIN = 8;
const styles = StyleSheet.create({
container: {
alignItems: 'center',
marginHorizontal: CONTAINER_MARGIN
marginHorizontal: CONTAINER_MARGIN,
},
headerItem: {
height: ITEM_SIZE,
@ -48,17 +48,17 @@ const styles = StyleSheet.create({
borderRadius: ITEM_SIZE / 2,
marginHorizontal: ITEM_MARGIN,
justifyContent: 'center',
alignItems: 'center'
alignItems: 'center',
},
headerIcon: {
...sharedStyles.textAlignCenter,
fontSize: 20,
color: '#fff'
color: '#fff',
},
customEmoji: {
height: 20,
width: 20
}
width: 20,
},
});
const keyExtractor = (item: any) => item?.id || item;
@ -97,7 +97,7 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
const [items, setItems] = useState([]);
const { width, height }: any = useDimensions();
const setEmojis = async() => {
const setEmojis = async () => {
try {
const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis');

View File

@ -68,12 +68,12 @@ const MessageActions = React.memo(forwardRef(({
editMessagePermission,
deleteMessagePermission,
forceDeleteMessagePermission,
pinMessagePermission
pinMessagePermission,
}: IMessageActions, ref): any => {
let permissions: any = {};
const { showActionSheet, hideActionSheet }: any = useActionSheet();
const getPermissions = async() => {
const getPermissions = async () => {
try {
const permission = [editMessagePermission, deleteMessagePermission, forceDeleteMessagePermission, pinMessagePermission];
const result = await RocketChat.hasPermission(permission, room.rid);
@ -81,7 +81,7 @@ const MessageActions = React.memo(forwardRef(({
hasEditPermission: result[0],
hasDeletePermission: result[1],
hasForceDeletePermission: result[2],
hasPinPermission: result[3]
hasPinPermission: result[3],
};
} catch {
// Do nothing
@ -167,7 +167,7 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handleUnread = async(message: any) => {
const handleUnread = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_UNREAD);
const { id: messageId, ts } = message;
const { rid } = room;
@ -177,7 +177,7 @@ const MessageActions = React.memo(forwardRef(({
if (result.success) {
const subCollection = db.get('subscriptions');
const subRecord = await subCollection.find(rid);
await db.action(async() => {
await db.action(async () => {
try {
await subRecord.update((sub: any) => sub.lastOpen = ts);
} catch {
@ -192,7 +192,7 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handlePermalink = async(message: any) => {
const handlePermalink = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_PERMALINK);
try {
const permalink: any = await getPermalink(message);
@ -203,13 +203,13 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handleCopy = async(message: any) => {
const handleCopy = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_COPY);
await Clipboard.setString(message?.attachments?.[0]?.description || message.msg);
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
};
const handleShare = async(message: any) => {
const handleShare = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_SHARE);
try {
const permalink: any = await getPermalink(message);
@ -224,7 +224,7 @@ const MessageActions = React.memo(forwardRef(({
replyInit(message, false);
};
const handleStar = async(message: any) => {
const handleStar = async (message: any) => {
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
try {
await RocketChat.toggleStarMessage(message.id, message.starred);
@ -235,7 +235,7 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handlePin = async(message: any) => {
const handlePin = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_PIN);
try {
await RocketChat.togglePinMessage(message.id, message.pinned);
@ -264,10 +264,10 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handleToggleTranslation = async(message: any) => {
const handleToggleTranslation = async (message: any) => {
try {
const db = database.active;
await db.action(async() => {
await db.action(async () => {
await message.update((m: any) => {
m.autoTranslate = !m.autoTranslate;
m._updatedAt = new Date();
@ -279,7 +279,7 @@ const MessageActions = React.memo(forwardRef(({
_id: message.id,
rid: message.subscription.id,
u: message.u,
msg: message.msg
msg: message.msg,
};
await RocketChat.translateMessage(m, room.autoTranslateLanguage);
}
@ -288,7 +288,7 @@ const MessageActions = React.memo(forwardRef(({
}
};
const handleReport = async(message: any) => {
const handleReport = async (message: any) => {
logEvent(events.ROOM_MSG_ACTION_REPORT);
try {
await RocketChat.reportMessage(message.id);
@ -305,7 +305,7 @@ const MessageActions = React.memo(forwardRef(({
showConfirmationAlert({
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
confirmationText: I18n.t('Delete'),
onPress: async() => {
onPress: async () => {
try {
logEvent(events.ROOM_MSG_ACTION_DELETE);
await RocketChat.deleteMessage(message.id, message.subscription.id);
@ -313,7 +313,7 @@ const MessageActions = React.memo(forwardRef(({
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
log(e);
}
}
},
});
};
@ -325,7 +325,7 @@ const MessageActions = React.memo(forwardRef(({
options = [{
title: I18n.t('Reply_in_Thread'),
icon: 'threads',
onPress: () => handleReply(message)
onPress: () => handleReply(message),
}];
}
@ -334,7 +334,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Quote'),
icon: 'quote',
onPress: () => handleQuote(message)
onPress: () => handleQuote(message),
});
}
@ -343,7 +343,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Edit'),
icon: 'edit',
onPress: () => handleEdit(message)
onPress: () => handleEdit(message),
});
}
@ -351,14 +351,14 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Permalink'),
icon: 'link',
onPress: () => handlePermalink(message)
onPress: () => handlePermalink(message),
});
// Create Discussion
options.push({
title: I18n.t('Start_a_Discussion'),
icon: 'discussions',
onPress: () => handleCreateDiscussion(message)
onPress: () => handleCreateDiscussion(message),
});
// Mark as unread
@ -366,7 +366,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Mark_unread'),
icon: 'flag',
onPress: () => handleUnread(message)
onPress: () => handleUnread(message),
});
}
@ -374,14 +374,14 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Copy'),
icon: 'copy',
onPress: () => handleCopy(message)
onPress: () => handleCopy(message),
});
// Share
options.push({
title: I18n.t('Share'),
icon: 'share',
onPress: () => handleShare(message)
onPress: () => handleShare(message),
});
// Star
@ -389,7 +389,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t(message.starred ? 'Unstar' : 'Star'),
icon: message.starred ? 'star-filled' : 'star',
onPress: () => handleStar(message)
onPress: () => handleStar(message),
});
}
@ -398,7 +398,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t(message.pinned ? 'Unpin' : 'Pin'),
icon: 'pin',
onPress: () => handlePin(message)
onPress: () => handlePin(message),
});
}
@ -407,7 +407,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t('Read_Receipt'),
icon: 'info',
onPress: () => handleReadReceipt(message)
onPress: () => handleReadReceipt(message),
});
}
@ -416,7 +416,7 @@ const MessageActions = React.memo(forwardRef(({
options.push({
title: I18n.t(message.autoTranslate ? 'View_Original' : 'Translate'),
icon: 'language',
onPress: () => handleToggleTranslation(message)
onPress: () => handleToggleTranslation(message),
});
}
@ -425,7 +425,7 @@ const MessageActions = React.memo(forwardRef(({
title: I18n.t('Report'),
icon: 'warning',
danger: true,
onPress: () => handleReport(message)
onPress: () => handleReport(message),
});
// Delete
@ -434,27 +434,27 @@ const MessageActions = React.memo(forwardRef(({
title: I18n.t('Delete'),
icon: 'delete',
danger: true,
onPress: () => handleDelete(message)
onPress: () => handleDelete(message),
});
}
return options;
};
const showMessageActions = async(message: any) => {
const showMessageActions = async (message: any) => {
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
await getPermissions();
showActionSheet({
options: getOptions(message),
headerHeight: HEADER_HEIGHT,
customHeader: (!isReadOnly || room.reactWhenReadOnly ? (
customHeader: !isReadOnly || room.reactWhenReadOnly ? (
<Header
server={server}
handleReaction={handleReaction}
isMasterDetail={isMasterDetail}
message={message}
/>
) : null)
) : null,
});
};
@ -476,7 +476,7 @@ const mapStateToProps = (state: any) => ({
editMessagePermission: state.permissions['edit-message'],
deleteMessagePermission: state.permissions['delete-message'],
forceDeleteMessagePermission: state.permissions['force-delete-message'],
pinMessagePermission: state.permissions['pin-message']
pinMessagePermission: state.permissions['pin-message'],
});
export default connect(mapStateToProps, null, null, { forwardRef: true })(MessageActions);

View File

@ -1,4 +1,5 @@
import React from 'react';
import { CancelEditingButton, ToggleEmojiButton } from './buttons';
interface IMessageBoxLeftButtons {
@ -11,7 +12,7 @@ interface IMessageBoxLeftButtons {
}
const LeftButtons = React.memo(({
theme, showEmojiKeyboard, editing, editCancel, openEmoji, closeEmoji
theme, showEmojiKeyboard, editing, editCancel, openEmoji, closeEmoji,
}: IMessageBoxLeftButtons) => {
if (editing) {
return <CancelEditingButton onPress={editCancel} theme={theme} />;

View File

@ -1,7 +1,7 @@
import React from 'react';
import { View } from 'react-native';
import { CancelEditingButton, ActionsButton } from './buttons';
import { ActionsButton, CancelEditingButton } from './buttons';
import styles from './styles';
interface IMessageBoxLeftButtons {
@ -13,7 +13,7 @@ interface IMessageBoxLeftButtons {
}
const LeftButtons = React.memo(({
theme, showMessageBoxActions, editing, editCancel, isActionsEnabled
theme, showMessageBoxActions, editing, editCancel, isActionsEnabled,
}: IMessageBoxLeftButtons) => {
if (editing) {
return <CancelEditingButton onPress={editCancel} theme={theme} />;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { Text, TouchableOpacity } from 'react-native';
import styles from '../styles';
import I18n from '../../../i18n';
@ -9,7 +9,7 @@ interface IMessageBoxFixedMentionItem {
item: {
username: string;
};
onPress({}): void;
onPress: Function;
theme: string;
}
@ -19,8 +19,8 @@ const FixedMentionItem = ({ item, onPress, theme }: IMessageBoxFixedMentionItem)
styles.mentionItem,
{
backgroundColor: themes[theme].auxiliaryBackground,
borderTopColor: themes[theme].separatorColor
}
borderTopColor: themes[theme].separatorColor,
},
]}
onPress={() => onPress(item)}
>

View File

@ -6,7 +6,7 @@ import shortnameToUnicode from '../../../utils/shortnameToUnicode';
import styles from '../styles';
import MessageboxContext from '../Context';
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
import {IEmoji} from "../../EmojiPicker/interfaces";
import { IEmoji } from '../../EmojiPicker/interfaces';
interface IMessageBoxMentionEmoji {
item: IEmoji;
@ -33,7 +33,7 @@ const MentionEmoji = ({ item }: IMessageBoxMentionEmoji) => {
};
MentionEmoji.propTypes = {
item: PropTypes.object
item: PropTypes.object,
};
export default MentionEmoji;

View File

@ -1,14 +1,14 @@
import React, { useContext } from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { Text, TouchableOpacity } from 'react-native';
import styles from '../styles';
import Avatar from '../../Avatar';
import MessageboxContext from '../Context';
import FixedMentionItem from './FixedMentionItem';
import MentionEmoji from './MentionEmoji';
import { MENTIONS_TRACKING_TYPE_EMOJIS, MENTIONS_TRACKING_TYPE_COMMANDS } from '../constants';
import { MENTIONS_TRACKING_TYPE_COMMANDS, MENTIONS_TRACKING_TYPE_EMOJIS } from '../constants';
import { themes } from '../../../constants/colors';
import {IEmoji} from "../../EmojiPicker/interfaces";
import { IEmoji } from '../../EmojiPicker/interfaces';
interface IMessageBoxMentionItem {
item: {
@ -79,8 +79,8 @@ const MentionItem = ({ item, trackingType, theme }: IMessageBoxMentionItem) => {
styles.mentionItem,
{
backgroundColor: themes[theme].auxiliaryBackground,
borderTopColor: themes[theme].separatorColor
}
borderTopColor: themes[theme].separatorColor,
},
]}
onPress={() => onPressMention(item)}
testID={testID}

View File

@ -1,20 +1,20 @@
import React from 'react';
import { View, Text } from 'react-native';
import { Text, View } from 'react-native';
import { Audio } from 'expo-av';
import { BorderlessButton } from 'react-native-gesture-handler';
import { getInfoAsync } from 'expo-file-system';
import { deactivateKeepAwake, activateKeepAwake } from 'expo-keep-awake';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import styles from './styles';
import I18n from '../../i18n';
import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';
import { logEvent, events } from '../../utils/log';
import { events, logEvent } from '../../utils/log';
interface IMessageBoxRecordAudioProps {
theme: string;
recordingCallback({}): void;
onFinish({}): void;
recordingCallback: Function;
onFinish: Function;
}
const RECORDING_EXTENSION = '.aac';
@ -25,7 +25,7 @@ const RECORDING_SETTINGS = {
audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.bitRate
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.bitRate,
},
ios: {
extension: RECORDING_EXTENSION,
@ -33,8 +33,8 @@ const RECORDING_SETTINGS = {
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.sampleRate,
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.numberOfChannels,
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.bitRate,
outputFormat: Audio.RECORDING_OPTION_IOS_OUTPUT_FORMAT_MPEG4AAC
}
outputFormat: Audio.RECORDING_OPTION_IOS_OUTPUT_FORMAT_MPEG4AAC,
},
};
const RECORDING_MODE = {
allowsRecordingIOS: true,
@ -43,7 +43,7 @@ const RECORDING_MODE = {
shouldDuckAndroid: true,
playThroughEarpieceAndroid: false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
};
const formatTime = function(seconds: any) {
@ -56,6 +56,7 @@ const formatTime = function(seconds: any) {
export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAudioProps, any> {
private isRecorderBusy: boolean;
private recording: any;
constructor(props: IMessageBoxRecordAudioProps) {
@ -63,7 +64,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
this.isRecorderBusy = false;
this.state = {
isRecording: false,
recordingDurationMillis: 0
recordingDurationMillis: 0,
};
}
@ -85,7 +86,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
return formatTime(Math.floor(recordingDurationMillis / 1000));
}
isRecordingPermissionGranted = async() => {
isRecordingPermissionGranted = async () => {
try {
const permission = await Audio.getPermissionsAsync();
if (permission.status === 'granted') {
@ -101,11 +102,11 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
onRecordingStatusUpdate = (status: any) => {
this.setState({
isRecording: status.isRecording,
recordingDurationMillis: status.durationMillis
recordingDurationMillis: status.durationMillis,
});
}
startRecordingAudio = async() => {
startRecordingAudio = async () => {
logEvent(events.ROOM_AUDIO_RECORD);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;
@ -130,7 +131,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
}
};
finishRecordingAudio = async() => {
finishRecordingAudio = async () => {
logEvent(events.ROOM_AUDIO_FINISH);
if (!this.isRecorderBusy) {
const { onFinish } = this.props;
@ -147,7 +148,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
type: 'audio/aac',
store: 'Uploads',
path: fileURI,
size: fileData.size
size: fileData.size,
};
onFinish(fileInfo);
@ -160,7 +161,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
}
};
cancelRecordingAudio = async() => {
cancelRecordingAudio = async () => {
logEvent(events.ROOM_AUDIO_CANCEL);
if (!this.isRecorderBusy) {
this.isRecorderBusy = true;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import moment from 'moment';
import { connect } from 'react-redux';
@ -11,33 +11,33 @@ import { themes } from '../../constants/colors';
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
paddingTop: 10
paddingTop: 10,
},
messageContainer: {
flex: 1,
marginHorizontal: 10,
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 4
borderRadius: 4,
},
header: {
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
username: {
fontSize: 16,
...sharedStyles.textMedium
...sharedStyles.textMedium,
},
time: {
fontSize: 12,
lineHeight: 16,
marginLeft: 6,
...sharedStyles.textRegular,
fontWeight: '300'
fontWeight: '300',
},
close: {
marginRight: 10
}
marginRight: 10,
},
});
interface IMessageBoxReplyPreview {
@ -51,13 +51,13 @@ interface IMessageBoxReplyPreview {
close(): void;
baseUrl: string;
username: string;
getCustomEmoji(): void;
getCustomEmoji: Function;
theme: string;
useRealName: boolean;
}
const ReplyPreview = React.memo(({
message, Message_TimeFormat, baseUrl, username, replying, getCustomEmoji, close, theme, useRealName
message, Message_TimeFormat, baseUrl, username, replying, getCustomEmoji, close, theme, useRealName,
}: IMessageBoxReplyPreview) => {
if (!replying) {
return null;
@ -68,7 +68,7 @@ const ReplyPreview = React.memo(({
<View
style={[
styles.container,
{ backgroundColor: themes[theme].messageboxBackground }
{ backgroundColor: themes[theme].messageboxBackground },
]}
>
<View style={[styles.messageContainer, { backgroundColor: themes[theme].chatComponentBackground }]}>
@ -76,7 +76,7 @@ const ReplyPreview = React.memo(({
<Text style={[styles.username, { color: themes[theme].tintColor }]}>{useRealName ? message.u?.name : message.u?.username}</Text>
<Text style={[styles.time, { color: themes[theme].auxiliaryText }]}>{time}</Text>
</View>
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<Markdown
msg={message.msg}
baseUrl={baseUrl}
@ -95,7 +95,7 @@ const ReplyPreview = React.memo(({
const mapStateToProps = (state: any) => ({
Message_TimeFormat: state.settings.Message_TimeFormat,
baseUrl: state.server.server,
useRealName: state.settings.UI_Use_Real_Name
useRealName: state.settings.UI_Use_Real_Name,
});
export default connect(mapStateToProps)(ReplyPreview);

View File

@ -1,7 +1,7 @@
import React from 'react';
import { View } from 'react-native';
import { SendButton, ActionsButton } from './buttons';
import { ActionsButton, SendButton } from './buttons';
import styles from './styles';
interface IMessageBoxRightButtons {
@ -13,7 +13,7 @@ interface IMessageBoxRightButtons {
}
const RightButtons = React.memo(({
theme, showSend, submit, showMessageBoxActions, isActionsEnabled
theme, showSend, submit, showMessageBoxActions, isActionsEnabled,
}: IMessageBoxRightButtons) => {
if (showSend) {
return <SendButton onPress={submit} theme={theme} />;

View File

@ -1,4 +1,5 @@
import React from 'react';
import { SendButton } from './buttons';
interface IMessageBoxRightButtons {

View File

@ -1,4 +1,5 @@
import React from 'react';
import BaseButton from './BaseButton';
interface IActionsButton {

View File

@ -1,4 +1,5 @@
import React from 'react';
import BaseButton from './BaseButton';
interface ICancelEditingButton {

View File

@ -1,4 +1,5 @@
import React from 'react';
import BaseButton from './BaseButton';
import { themes } from '../../../constants/colors';

View File

@ -1,4 +1,5 @@
import React from 'react';
import BaseButton from './BaseButton';
interface IToggleEmojiButton {

View File

@ -7,5 +7,5 @@ export {
CancelEditingButton,
ToggleEmojiButton,
SendButton,
ActionsButton
ActionsButton,
};

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import {View, Alert, Keyboard, Text, NativeModules} from 'react-native';
import { Alert, Keyboard, NativeModules, Text, View } from 'react-native';
import { connect } from 'react-redux';
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
import ImagePicker from 'react-native-image-crop-picker';
@ -15,33 +15,35 @@ import RocketChat from '../../lib/rocketchat';
import styles from './styles';
import database from '../../lib/database';
import { emojis } from '../../emojis';
import log, { logEvent, events } from '../../utils/log';
import log, { events, logEvent } from '../../utils/log';
import RecordAudio from './RecordAudio';
import I18n from '../../i18n';
import ReplyPreview from './ReplyPreview';
import debounce from '../../utils/debounce';
import { themes } from '../../constants/colors';
// @ts-ignore
// eslint-disable-next-line import/extensions,import/no-unresolved
import LeftButtons from './LeftButtons';
// @ts-ignore
// eslint-disable-next-line import/extensions,import/no-unresolved
import RightButtons from './RightButtons';
import { isAndroid, isTablet } from '../../utils/deviceInfo';
import { canUploadFile } from '../../utils/media';
import EventEmiter from '../../utils/events';
import {
KEY_COMMAND,
handleCommandTyping,
handleCommandShowUpload,
handleCommandSubmit,
handleCommandShowUpload
handleCommandTyping,
} from '../../commands';
import Mentions from './Mentions';
import MessageboxContext from './Context';
import {
MENTIONS_TRACKING_TYPE_EMOJIS,
MENTIONS_TRACKING_TYPE_COMMANDS,
MENTIONS_COUNT_TO_DISPLAY,
MENTIONS_TRACKING_TYPE_COMMANDS,
MENTIONS_TRACKING_TYPE_EMOJIS,
MENTIONS_TRACKING_TYPE_ROOMS,
MENTIONS_TRACKING_TYPE_USERS,
MENTIONS_TRACKING_TYPE_ROOMS
} from './constants';
import CommandsPreview from './CommandsPreview';
import { getUserSelector } from '../../selectors/login';
@ -58,17 +60,17 @@ const imagePickerConfig = {
cropping: true,
compressImageQuality: 0.8,
avoidEmptySpaceAroundImage: false,
freeStyleCropEnabled: true
freeStyleCropEnabled: true,
};
const libraryPickerConfig = {
multiple: true,
compressVideoPreset: 'Passthrough',
mediaType: 'any'
mediaType: 'any',
};
const videoPickerConfig = {
mediaType: 'video'
mediaType: 'video',
};
interface IMessageBoxProps {
@ -95,18 +97,18 @@ interface IMessageBoxProps {
FileUpload_MediaTypeWhiteList: string;
FileUpload_MaxFileSize: number;
Message_AudioRecorderEnabled: boolean;
getCustomEmoji(): void;
editCancel(): void;
editRequest({}): void;
onSubmit({}, {}?, {}?): void;
typing({}, {}): void;
getCustomEmoji: Function;
editCancel: Function;
editRequest: Function;
onSubmit: Function;
typing: Function;
theme: string;
replyCancel(): void;
showSend: boolean;
navigation: any;
children: JSX.Element;
isMasterDetail: boolean;
showActionSheet({}): void;
showActionSheet: Function;
iOSScrollBehavior: number;
sharing: boolean;
isActionsEnabled: boolean;
@ -127,31 +129,44 @@ interface IMessageBoxState {
}
class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
private text: string;
private selection: { start: number; end: number };
private focused: boolean;
private options: any;
private imagePickerConfig: any;
private libraryPickerConfig: any;
private videoPickerConfig: any;
private room: any;
private thread: any;
private unsubscribeFocus: any;
private trackingTimeout: any;
private tracking: any;
private unsubscribeBlur: any;
private component: any;
private typingTimeout: any;
static defaultProps = {
message: {
id: ''
id: '',
},
sharing: false,
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
isActionsEnabled: true,
getCustomEmoji: () => {}
getCustomEmoji: () => {},
}
constructor(props: IMessageBoxProps) {
@ -165,7 +180,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
commandPreview: [],
showCommandPreview: false,
command: {},
tshow: false
tshow: false,
};
this.text = '';
this.selection = { start: 0, end: 0 };
@ -176,49 +191,49 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
{
title: I18n.t('Take_a_photo'),
icon: 'camera-photo',
onPress: this.takePhoto
onPress: this.takePhoto,
},
{
title: I18n.t('Take_a_video'),
icon: 'camera',
onPress: this.takeVideo
onPress: this.takeVideo,
},
{
title: I18n.t('Choose_from_library'),
icon: 'image',
onPress: this.chooseFromLibrary
onPress: this.chooseFromLibrary,
},
{
title: I18n.t('Choose_file'),
icon: 'attach',
onPress: this.chooseFile
onPress: this.chooseFile,
},
{
title: I18n.t('Create_Discussion'),
icon: 'discussions',
onPress: this.createDiscussion
}
onPress: this.createDiscussion,
},
];
const libPickerLabels = {
cropperChooseText: I18n.t('Choose'),
cropperCancelText: I18n.t('Cancel'),
loadingLabelText: I18n.t('Processing')
loadingLabelText: I18n.t('Processing'),
};
this.imagePickerConfig = {
...imagePickerConfig,
...libPickerLabels
...libPickerLabels,
};
this.libraryPickerConfig = {
...libraryPickerConfig,
...libPickerLabels
...libPickerLabels,
};
this.videoPickerConfig = {
...videoPickerConfig,
...libPickerLabels
...libPickerLabels,
};
}
@ -302,11 +317,11 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
shouldComponentUpdate(nextProps: any, nextState: any) {
const {
showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow
showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow,
} = this.state;
const {
roomType, replying, editing, isFocused, message, theme
roomType, replying, editing, isFocused, message, theme,
} = this.props;
if (nextProps.theme !== theme) {
@ -388,7 +403,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
// eslint-disable-next-line react/sort-comp
debouncedOnChangeText = debounce(async(text: any) => {
debouncedOnChangeText = debounce(async (text: any) => {
const { sharing } = this.props;
const isTextEmpty = text.length === 0;
if (isTextEmpty) {
@ -424,15 +439,14 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}
return this.identifyMentionKeyword(command, MENTIONS_TRACKING_TYPE_COMMANDS);
} else if (channelMention) {
} if (channelMention) {
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_ROOMS);
} else if (userMention) {
} if (userMention) {
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_USERS);
} else if (emojiMention) {
} if (emojiMention) {
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_EMOJIS);
} else {
return this.stopTrackingMention();
}
return this.stopTrackingMention();
}, 100)
onKeyboardResigned = () => {
@ -451,7 +465,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
const result = msg.substr(0, cursor).replace(regexp, '');
const mentionName = trackingType === MENTIONS_TRACKING_TYPE_EMOJIS
? `${ item.name || item }:`
: (item.username || item.name || item.command);
: item.username || item.name || item.command;
const text = `${ result }${ mentionName } ${ msg.slice(cursor) }`;
if ((trackingType === MENTIONS_TRACKING_TYPE_COMMANDS) && item.providesPreview) {
@ -467,7 +481,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
onPressCommandPreview = (item: any) => {
const { command } = this.state;
const {
rid, tmid, message: { id: messageTmid }, replyCancel
rid, tmid, message: { id: messageTmid }, replyCancel,
} = this.props;
const { text } = this;
const name = text.substr(0, text.indexOf(' ')).slice(1);
@ -500,7 +514,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
this.setShowSend(true);
}
getPermalink = async(message: any) => {
getPermalink = async (message: any) => {
try {
return await RocketChat.getPermalinkMessage(message);
} catch (error) {
@ -519,18 +533,18 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
return result;
}
getUsers = debounce(async(keyword: any) => {
getUsers = debounce(async (keyword: any) => {
let res = await RocketChat.search({ text: keyword, filterRooms: false, filterUsers: true });
res = [...this.getFixedMentions(keyword), ...res];
this.setState({ mentions: res });
}, 300)
getRooms = debounce(async(keyword = '') => {
getRooms = debounce(async (keyword = '') => {
const res = await RocketChat.search({ text: keyword, filterRooms: true, filterUsers: false });
this.setState({ mentions: res });
}, 300)
getEmojis = debounce(async(keyword: any) => {
getEmojis = debounce(async (keyword: any) => {
const db = database.active;
const customEmojisCollection = db.get('custom_emojis');
const likeString = sanitizeLikeString(keyword);
@ -540,17 +554,17 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
let customEmojis = await customEmojisCollection.query(...whereClause).fetch();
customEmojis = customEmojis.slice(0, MENTIONS_COUNT_TO_DISPLAY);
const filteredEmojis = emojis.filter(emoji => emoji.indexOf(keyword) !== -1).slice(0, MENTIONS_COUNT_TO_DISPLAY);
const filteredEmojis = emojis.filter((emoji) => emoji.indexOf(keyword) !== -1).slice(0, MENTIONS_COUNT_TO_DISPLAY);
const mergedEmojis = [...customEmojis, ...filteredEmojis].slice(0, MENTIONS_COUNT_TO_DISPLAY);
this.setState({ mentions: mergedEmojis || [] });
}, 300)
getSlashCommands = debounce(async(keyword: any) => {
getSlashCommands = debounce(async (keyword: any) => {
const db = database.active;
const commandsCollection = db.get('slash_commands');
const likeString = sanitizeLikeString(keyword);
const commands = await commandsCollection.query(
Q.where('id', Q.like(`${ likeString }%`))
Q.where('id', Q.like(`${ likeString }%`)),
).fetch();
this.setState({ mentions: commands || [] });
}, 300)
@ -585,7 +599,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}, 1000);
}
setCommandPreview = async(command: any, name: string, params: any) => {
setCommandPreview = async (command: any, name: string, params: any) => {
const { rid } = this.props;
try {
const { success, preview } = await RocketChat.getCommandPreview(name, rid, params);
@ -630,7 +644,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
return false;
}
takePhoto = async() => {
takePhoto = async () => {
logEvent(events.ROOM_BOX_ACTION_PHOTO);
try {
const image = await ImagePicker.openCamera(this.imagePickerConfig);
@ -642,7 +656,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}
takeVideo = async() => {
takeVideo = async () => {
logEvent(events.ROOM_BOX_ACTION_VIDEO);
try {
const video = await ImagePicker.openCamera(this.videoPickerConfig);
@ -654,7 +668,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}
chooseFromLibrary = async() => {
chooseFromLibrary = async () => {
logEvent(events.ROOM_BOX_ACTION_LIBRARY);
try {
const attachments = await ImagePicker.openPicker(this.libraryPickerConfig);
@ -664,17 +678,17 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
}
chooseFile = async() => {
chooseFile = async () => {
logEvent(events.ROOM_BOX_ACTION_FILE);
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles]
type: [DocumentPicker.types.allFiles],
});
const file = {
filename: res.name,
size: res.size,
mime: res.type,
path: res.uri
path: res.uri,
};
if (this.canUploadFile(file)) {
this.openShareView([file]);
@ -730,9 +744,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
this.setState({ recording });
}
finishAudioMessage = async(fileInfo: any) => {
finishAudioMessage = async (fileInfo: any) => {
const {
rid, tmid, baseUrl: server, user
rid, tmid, baseUrl: server, user,
} = this.props;
if (fileInfo) {
@ -750,10 +764,10 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
this.setState({ showEmojiKeyboard: false });
}
submit = async() => {
submit = async () => {
const { tshow } = this.state;
const {
onSubmit, rid: roomId, tmid, showSend, sharing
onSubmit, rid: roomId, tmid, showSend, sharing,
} = this.props;
const message = this.text;
@ -773,7 +787,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
}
const {
editing, replying, message: { id: messageTmid }, replyCancel
editing, replying, message: { id: messageTmid }, replyCancel,
} = this.props;
// Slash command
@ -783,7 +797,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
const command = message.replace(/ .*/, '').slice(1);
const likeString = sanitizeLikeString(command);
const slashCommand = await commandsCollection.query(
Q.where('id', Q.like(`${ likeString }%`))
Q.where('id', Q.like(`${ likeString }%`)),
).fetch();
if (slashCommand.length > 0) {
logEvent(events.COMMAND_RUN);
@ -811,7 +825,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
// Reply
} else if (replying) {
const {
message: replyingMessage, threadsEnabled, replyWithMention
message: replyingMessage, threadsEnabled, replyWithMention,
} = this.props;
// Thread
@ -856,7 +870,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
identifyMentionKeyword = (keyword: any, type: string) => {
this.setState({
showEmojiKeyboard: false,
trackingType: type
trackingType: type,
});
this.updateMentions(keyword, type);
}
@ -870,7 +884,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
mentions: [],
trackingType: '',
commandPreview: [],
showCommandPreview: false
showCommandPreview: false,
});
}
@ -912,16 +926,16 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
renderContent = () => {
const {
recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview
recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview,
} = this.state;
const {
editing, message, replying, replyCancel, user, getCustomEmoji, theme, Message_AudioRecorderEnabled, children, isActionsEnabled, tmid
editing, message, replying, replyCancel, user, getCustomEmoji, theme, Message_AudioRecorderEnabled, children, isActionsEnabled, tmid,
} = this.props;
const isAndroidTablet = isTablet && isAndroid ? {
multiline: false,
onSubmitEditing: this.submit,
returnKeyType: 'send'
returnKeyType: 'send',
} : {};
const recordAudio = showSend || !Message_AudioRecorderEnabled ? null : (
@ -935,7 +949,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
const commandsPreviewAndMentions = !recording ? (
<>
<CommandsPreview commandPreview={commandPreview} showCommandPreview={showCommandPreview} />
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<Mentions mentions={mentions} trackingType={trackingType} theme={theme} />
</>
) : null;
@ -965,11 +979,11 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
isActionsEnabled={isActionsEnabled}
/>
<TextInput
ref={component => this.component = component}
//@ts-ignore
ref={(component) => this.component = component}
// @ts-ignore
style={[styles.textBoxInput, { color: themes[theme].bodyText }]}
returnKeyType='default'
//@ts-ignore
// @ts-ignore
keyboardType='twitter'
blurOnSubmit={false}
placeholder={I18n.t('New_Message')}
@ -1002,7 +1016,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
style={[
styles.textArea,
{ backgroundColor: themes[theme].messageboxBackground },
!recording && editing && { backgroundColor: themes[theme].chatComponentBackground }
!recording && editing && { backgroundColor: themes[theme].chatComponentBackground },
]}
testID='messagebox'
>
@ -1020,7 +1034,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
console.count(`${ this.constructor.name }.render calls`);
const { showEmojiKeyboard } = this.state;
const {
user, baseUrl, theme, iOSScrollBehavior
user, baseUrl, theme, iOSScrollBehavior,
} = this.props;
return (
<MessageboxContext.Provider
@ -1028,7 +1042,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
user,
baseUrl,
onPressMention: this.onPressMention,
onPressCommandPreview: this.onPressCommandPreview
onPressCommandPreview: this.onPressCommandPreview,
}}
>
<KeyboardAccessoryView
@ -1056,11 +1070,11 @@ const mapStateToProps = (state: any) => ({
user: getUserSelector(state),
FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList,
FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize,
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled,
});
const dispatchToProps = ({
typing: (rid: any, status: any) => userTypingAction(rid, status)
});
const dispatchToProps = {
typing: (rid: any, status: any) => userTypingAction(rid, status),
};
// @ts-ignore
export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox));

View File

@ -9,12 +9,12 @@ const SCROLLVIEW_MENTION_HEIGHT = 4 * MENTION_HEIGHT;
export default StyleSheet.create({
composer: {
flexDirection: 'column',
borderTopWidth: 1
borderTopWidth: 1,
},
textArea: {
flexDirection: 'row',
alignItems: 'center',
flexGrow: 0
flexGrow: 0,
},
textBoxInput: {
textAlignVertical: 'center',
@ -28,48 +28,48 @@ export default StyleSheet.create({
paddingRight: 0,
fontSize: 16,
letterSpacing: 0,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
actionButton: {
alignItems: 'center',
justifyContent: 'center',
width: 60,
height: 48
height: 48,
},
mentionList: {
maxHeight: MENTION_HEIGHT * 4
maxHeight: MENTION_HEIGHT * 4,
},
mentionItem: {
height: MENTION_HEIGHT,
borderTopWidth: StyleSheet.hairlineWidth,
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 5
paddingHorizontal: 5,
},
mentionItemCustomEmoji: {
margin: 8,
width: 30,
height: 30
height: 30,
},
mentionItemEmoji: {
width: 46,
height: 36,
fontSize: isIOS ? 30 : 25,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
fixedMentionAvatar: {
width: 46,
fontSize: 14,
...sharedStyles.textBold,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
mentionText: {
fontSize: 14,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
emojiKeyboardContainer: {
flex: 1,
borderTopWidth: StyleSheet.hairlineWidth
borderTopWidth: StyleSheet.hairlineWidth,
},
slash: {
height: 30,
@ -77,48 +77,48 @@ export default StyleSheet.create({
padding: 5,
paddingHorizontal: 12,
marginHorizontal: 10,
borderRadius: 2
borderRadius: 2,
},
commandPreviewImage: {
justifyContent: 'center',
margin: 3,
width: 120,
height: 80,
borderRadius: 4
borderRadius: 4,
},
commandPreview: {
height: 100,
flex: 1,
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
avatar: {
margin: 8
margin: 8,
},
scrollViewMention: {
maxHeight: SCROLLVIEW_MENTION_HEIGHT
maxHeight: SCROLLVIEW_MENTION_HEIGHT,
},
recordingContent: {
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between'
justifyContent: 'space-between',
},
recordingCancelText: {
fontSize: 16,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
buttonsWhitespace: {
width: 15
width: 15,
},
sendToChannelButton: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 8,
paddingHorizontal: 18
paddingHorizontal: 18,
},
sendToChannelText: {
fontSize: 12,
marginLeft: 4,
...sharedStyles.textRegular
}
...sharedStyles.textRegular,
},
});

View File

@ -1,4 +1,4 @@
import { useImperativeHandle, forwardRef } from 'react';
import { forwardRef, useImperativeHandle } from 'react';
import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
@ -10,11 +10,11 @@ import log from '../utils/log';
const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
const { showActionSheet }: any = useActionSheet();
const handleResend = protectedFunction(async(message: any) => {
const handleResend = protectedFunction(async (message: any) => {
await RocketChat.resendMessage(message, tmid);
});
const handleDelete = async(message: any) => {
const handleDelete = async (message: any) => {
try {
const db = database.active;
const deleteBatch: any = [];
@ -41,7 +41,7 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
msg.prepareUpdate((m: any) => {
m.tcount = null;
m.tlm = null;
})
}),
);
try {
@ -55,14 +55,14 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
deleteBatch.push(
msg.prepareUpdate((m: any) => {
m.tcount -= 1;
})
}),
);
}
} catch {
// Do nothing: message not found
}
}
await db.action(async() => {
await db.action(async () => {
await db.batch(...deleteBatch);
});
} catch (e) {
@ -76,21 +76,21 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
{
title: I18n.t('Resend'),
icon: 'send',
onPress: () => handleResend(message)
onPress: () => handleResend(message),
},
{
title: I18n.t('Delete'),
icon: 'delete',
danger: true,
onPress: () => handleDelete(message)
}
onPress: () => handleDelete(message),
},
],
hasCancel: true
hasCancel: true,
});
};
useImperativeHandle(ref, () => ({
showMessageErrorActions
showMessageErrorActions,
}));
return null;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import I18n from '../i18n';
import sharedStyles from '../views/Styles';
@ -9,18 +9,18 @@ const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 24
marginVertical: 24,
},
line: {
height: 1,
flex: 1
flex: 1,
},
text: {
fontSize: 14,
marginLeft: 14,
marginRight: 14,
...sharedStyles.textMedium
}
...sharedStyles.textMedium,
},
});
interface IOrSeparator {

View File

@ -11,7 +11,7 @@ interface IPasscodeButton {
icon: string;
theme: string;
disabled: boolean;
onPress({}?): void;
onPress: Function;
}
const Button = React.memo(({ text, disabled, theme, onPress, icon }: Partial<IPasscodeButton>) => {

View File

@ -17,7 +17,7 @@ interface IPasscodeDots {
const Dots = React.memo(({ passcode, theme, length }: IPasscodeDots) => (
<View style={styles.dotsContainer}>
{range(length).map((val) => {
const lengthSup = (passcode.length >= val + 1);
const lengthSup = passcode.length >= val + 1;
const height = lengthSup ? SIZE_FULL : SIZE_EMPTY;
const width = lengthSup ? SIZE_FULL : SIZE_EMPTY;
let backgroundColor = '';
@ -38,7 +38,7 @@ const Dots = React.memo(({ passcode, theme, length }: IPasscodeDots) => (
borderRadius,
backgroundColor,
marginRight,
marginLeft
marginLeft,
}}
/>
</View>

View File

@ -4,7 +4,7 @@ import { Grid } from 'react-native-easy-grid';
import { themes } from '../../../constants/colors';
import { resetAttempts } from '../../../utils/localAuthentication';
import { TYPE } from '../constants';
import { getLockedUntil, getDiff } from '../utils';
import { getDiff, getLockedUntil } from '../utils';
import I18n from '../../../i18n';
import styles from './styles';
import Title from './Title';
@ -52,7 +52,7 @@ const Timer = React.memo(({ time, theme, setStatus }: IPasscodeTimer) => {
const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
const [lockedUntil, setLockedUntil] = useState<any>(null);
const readItemFromStorage = async() => {
const readItemFromStorage = async () => {
const l = await getLockedUntil();
setLockedUntil(l);
};
@ -62,7 +62,7 @@ const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
}, []);
return (
//TODO - verify if this 'r' it's correct
// TODO - verify if this 'r' it's correct
// @ts-ignore
<Grid style={[styles.grid, { backgroundColor: themes[theme].passcodeBackground }]} r>
<LockIcon theme={theme} />

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text } from 'react-native';
import { Text, View } from 'react-native';
import { Row } from 'react-native-easy-grid';
import styles from './styles';

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text } from 'react-native';
import { Text, View } from 'react-native';
import { Row } from 'react-native-easy-grid';
import styles from './styles';

View File

@ -1,5 +1,5 @@
import React, { useState, forwardRef, useImperativeHandle, useRef } from 'react';
import { Col, Row, Grid } from 'react-native-easy-grid';
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { Col, Grid, Row } from 'react-native-easy-grid';
import range from 'lodash/range';
import * as Animatable from 'react-native-animatable';
import * as Haptics from 'expo-haptics';
@ -27,7 +27,7 @@ interface IPasscodeBase {
}
const Base = forwardRef(({
theme, type, onEndProcess, previousPasscode, title, subtitle, onError, showBiometry, onBiometryPress
theme, type, onEndProcess, previousPasscode, title, subtitle, onError, showBiometry, onBiometryPress,
}: IPasscodeBase, ref) => {
const rootRef = useRef<any>();
const dotsRef = useRef<any>();
@ -78,7 +78,7 @@ const Base = forwardRef(({
});
useImperativeHandle(ref, () => ({
wrongPasscode, animate, clearPasscode
wrongPasscode, animate, clearPasscode,
}));
return (

View File

@ -4,22 +4,22 @@ import sharedStyles from '../../../views/Styles';
export default StyleSheet.create({
container: {
flex: 1
flex: 1,
},
titleView: {
justifyContent: 'center'
justifyContent: 'center',
},
subtitleView: {
justifyContent: 'center',
height: 32
height: 32,
},
row: {
flex: 0,
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
buttonRow: {
height: 102
height: 102,
},
colButton: {
flex: 0,
@ -27,44 +27,44 @@ export default StyleSheet.create({
marginRight: 12,
alignItems: 'center',
width: 78,
height: 78
height: 78,
},
buttonText: {
fontSize: 28,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
buttonView: {
alignItems: 'center',
justifyContent: 'center',
width: 78,
height: 78,
borderRadius: 4
borderRadius: 4,
},
textTitle: {
fontSize: 22,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
textSubtitle: {
fontSize: 16,
...sharedStyles.textMedium
...sharedStyles.textMedium,
},
dotsContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: 24,
marginBottom: 40
marginBottom: 40,
},
dotsView: {
justifyContent: 'center',
alignItems: 'center',
height: 16
height: 16,
},
grid: {
justifyContent: 'center',
flexDirection: 'column'
flexDirection: 'column',
},
iconView: {
marginVertical: 16
}
marginVertical: 16,
},
});

View File

@ -1,4 +1,4 @@
import React, { useState, useRef } from 'react';
import React, { useRef, useState } from 'react';
import * as Haptics from 'expo-haptics';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';

View File

@ -8,10 +8,10 @@ import Base from './Base';
import Locked from './Base/Locked';
import { TYPE } from './constants';
import {
ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, PASSCODE_KEY, MAX_ATTEMPTS
ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, MAX_ATTEMPTS, PASSCODE_KEY,
} from '../../constants/localAuthentication';
import { resetAttempts, biometryAuth } from '../../utils/localAuthentication';
import { getLockedUntil, getDiff } from './utils';
import { biometryAuth, resetAttempts } from '../../utils/localAuthentication';
import { getDiff, getLockedUntil } from './utils';
import UserPreferences from '../../lib/userPreferences';
import I18n from '../../i18n';
@ -31,12 +31,12 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
const { getItem: getAttempts, setItem: setAttempts } = useAsyncStorage(ATTEMPTS_KEY);
const { setItem: setLockedUntil } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
const fetchPasscode = async() => {
const fetchPasscode = async () => {
const p: any = await UserPreferences.getStringAsync(PASSCODE_KEY);
setPasscode(p);
};
const biometry = async() => {
const biometry = async () => {
if (hasBiometry && status === TYPE.ENTER) {
const result = await biometryAuth();
if (result?.success) {
@ -45,7 +45,7 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
}
};
const readStorage = async() => {
const readStorage = async () => {
lockedUntil = await getLockedUntil();
if (lockedUntil) {
const diff = getDiff(lockedUntil);

View File

@ -2,5 +2,5 @@ export const TYPE: any = {
CHOOSE: 'choose',
CONFIRM: 'confirm',
ENTER: 'enter',
LOCKED: 'locked'
LOCKED: 'locked',
};

View File

@ -3,7 +3,7 @@ import moment from 'moment';
import { LOCKED_OUT_TIMER_KEY, TIME_TO_LOCK } from '../../constants/localAuthentication';
export const getLockedUntil = async() => {
export const getLockedUntil = async () => {
const t: any = await AsyncStorage.getItem(LOCKED_OUT_TIMER_KEY);
if (t) {
return moment(t).add(TIME_TO_LOCK);
@ -11,4 +11,4 @@ export const getLockedUntil = async() => {
return null;
};
// @ts-ignore
export const getDiff = t => new Date(t) - new Date();
export const getDiff = (t) => new Date(t) - new Date();

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import Modal from 'react-native-modal';
import Touchable from 'react-native-platform-touchable';
@ -13,48 +13,48 @@ import SafeAreaView from './SafeAreaView';
const styles = StyleSheet.create({
safeArea: {
backgroundColor: 'transparent'
backgroundColor: 'transparent',
},
titleContainer: {
alignItems: 'center',
paddingVertical: 10
paddingVertical: 10,
},
title: {
fontSize: 16,
...sharedStyles.textSemibold,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
reactCount: {
fontSize: 13,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
peopleReacted: {
fontSize: 14,
...sharedStyles.textMedium
...sharedStyles.textMedium,
},
peopleItemContainer: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
justifyContent: 'center',
},
emojiContainer: {
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center'
justifyContent: 'center',
},
itemContainer: {
height: 50,
flexDirection: 'row'
flexDirection: 'row',
},
listContainer: {
flex: 1
flex: 1,
},
closeButton: {
position: 'absolute',
left: 0,
top: 10
}
top: 10,
},
});
const standardEmojiStyle = { fontSize: 20 };
const customEmojiStyle = { width: 20, height: 20 };
@ -132,7 +132,7 @@ const ModalContent = React.memo(({ message, onClose, ...props }: IModalContent)
style={styles.listContainer}
data={message.reactions}
renderItem={({ item }) => <Item item={item} {...props} />}
keyExtractor={item => item.emoji}
keyExtractor={(item) => item.emoji}
/>
</SafeAreaView>
);
@ -149,7 +149,7 @@ const ReactionsModal = React.memo(({ isVisible, onClose, theme, ...props }: IRea
onSwipeComplete={onClose}
swipeDirection={['up', 'left', 'right', 'down']}
>
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<ModalContent onClose={onClose} theme={theme} {...props} />
</Modal>
), (prevProps, nextProps) => prevProps.isVisible === nextProps.isVisible && prevProps.theme === nextProps.theme);

View File

@ -1,12 +1,12 @@
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types, react/destructuring-assignment */
import React from 'react';
import { View, Dimensions } from 'react-native';
import { Dimensions, View } from 'react-native';
import { storiesOf } from '@storybook/react-native';
import RoomHeaderComponent from './RoomHeader';
import Header from '../Header';
import { longText } from '../../../storybook/utils';
import { ThemeContext } from '../../theme';
import RoomHeaderComponent from './RoomHeader';
const stories = storiesOf('RoomHeader', module);

View File

@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import I18n from '../../i18n';
import sharedStyles from '../../views/Styles';
@ -9,7 +9,7 @@ import RoomTypeIcon from '../RoomTypeIcon';
import { withTheme } from '../../theme';
const HIT_SLOP = {
top: 5, right: 5, bottom: 5, left: 5
top: 5, right: 5, bottom: 5, left: 5,
};
const TITLE_SIZE = 16;
const SUBTITLE_SIZE = 12;
@ -19,23 +19,23 @@ const getSubTitleSize = (scale: number) => SUBTITLE_SIZE * scale;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center'
justifyContent: 'center',
},
titleContainer: {
alignItems: 'center',
flexDirection: 'row'
flexDirection: 'row',
},
title: {
flexShrink: 1,
...sharedStyles.textSemibold
...sharedStyles.textSemibold,
},
subtitle: {
flexShrink: 1,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
typingUsers: {
...sharedStyles.textSemibold
}
...sharedStyles.textSemibold,
},
});
type TRoomHeaderSubTitle = {
@ -141,7 +141,7 @@ const HeaderTitle = React.memo(({ title, tmid, prid, scale, theme, testID }: TRo
});
const Header = React.memo(({
title, subtitle, parentTitle, type, status, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID, usersTyping = []
title, subtitle, parentTitle, type, status, width, height, prid, tmid, onPress, theme, isGroupChat, teamMain, testID, usersTyping = [],
}: IRoomHeader) => {
const portrait = height > width;
let scale = 1;

View File

@ -29,10 +29,9 @@ interface IRoomHeaderContainerProps {
}
class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
shouldComponentUpdate(nextProps: IRoomHeaderContainerProps) {
const {
type, title, subtitle, status, statusText, connecting, connected, onPress, usersTyping, width, height, teamMain
type, title, subtitle, status, statusText, connecting, connected, onPress, usersTyping, width, height, teamMain,
} = this.props;
if (nextProps.type !== type) {
return true;
@ -93,7 +92,7 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
height,
parentTitle,
isGroupChat,
testID
testID,
} = this.props;
let subtitle;
@ -147,7 +146,7 @@ const mapStateToProps = (state: any, ownProps: any) => {
connected: state.meteor.connected,
usersTyping: state.usersTyping,
status,
statusText
statusText,
};
};

View File

@ -1,5 +1,6 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { CustomIcon } from '../lib/Icons';
import { STATUS_COLORS, themes } from '../constants/colors';
import Status from './Status/Status';
@ -7,8 +8,8 @@ import { withTheme } from '../theme';
const styles = StyleSheet.create({
icon: {
marginRight: 4
}
marginRight: 4,
},
});
interface IRoomTypeIcon {
@ -22,7 +23,7 @@ interface IRoomTypeIcon {
}
const RoomTypeIcon = React.memo(({
type, isGroupChat, status, style, theme, teamMain, size = 16
type, isGroupChat, status, style, theme, teamMain, size = 16,
}: IRoomTypeIcon) => {
if (!type) {
return null;
@ -32,7 +33,7 @@ const RoomTypeIcon = React.memo(({
const iconStyle = [
styles.icon,
{ color },
style
style,
];
if (type === 'd' && !isGroupChat) {

View File

@ -1,13 +1,14 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { SafeAreaView as SafeAreaContext } from 'react-native-safe-area-context';
import { themes } from '../constants/colors';
import { withTheme } from '../theme';
const styles = StyleSheet.create({
view: {
flex: 1
}
flex: 1,
},
});
interface ISafeAreaView {

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import TextInput from '../presentation/TextInput';
@ -14,7 +14,7 @@ const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
flex: 1
flex: 1,
},
searchBox: {
alignItems: 'center',
@ -25,7 +25,7 @@ const styles = StyleSheet.create({
margin: 16,
marginVertical: 10,
paddingHorizontal: 10,
flex: 1
flex: 1,
},
input: {
flex: 1,
@ -33,15 +33,15 @@ const styles = StyleSheet.create({
marginLeft: 8,
paddingTop: 0,
paddingBottom: 0,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
cancel: {
marginRight: 15
marginRight: 15,
},
cancelText: {
...sharedStyles.textRegular,
fontSize: 17
}
fontSize: 17,
},
});
interface ISearchBox {
@ -66,14 +66,14 @@ const SearchBox = ({
<View
style={[
styles.container,
{ backgroundColor: isIOS ? themes[theme].headerBackground : themes[theme].headerSecondaryBackground }
{ backgroundColor: isIOS ? themes[theme].headerBackground : themes[theme].headerSecondaryBackground },
]}
>
<View style={[styles.searchBox, { backgroundColor: themes[theme].searchboxBackground }]}>
<CustomIcon name='search' size={14} color={themes[theme].auxiliaryText} />
<TextInput
ref={inputRef}
/*@ts-ignore*/
/* @ts-ignore*/
autoCapitalize='none'
autoCorrect={false}
blurOnSubmit

View File

@ -1,4 +1,5 @@
import React from 'react';
import { CustomIcon } from '../../lib/Icons';
import { STATUS_COLORS } from '../../constants/colors';
@ -13,7 +14,7 @@ const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: I
const isNameValid = CustomIcon.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';
const calculatedStyle = [{
width: size, height: size, textAlignVertical: 'center'
width: size, height: size, textAlignVertical: 'center',
}, style];
return (

View File

@ -12,7 +12,7 @@ interface IStatusContainer {
const StatusContainer = memo(({ style, size = 32, status }: IStatusContainer) => <Status size={size} style={style} status={status} />);
const mapStateToProps = (state: any, ownProps: any) => ({
status: state.meteor.connected ? (state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status) : 'loading'
status: state.meteor.connected ? state.activeUsers[ownProps.id] && state.activeUsers[ownProps.id].status : 'loading',
});
export default connect(mapStateToProps)(StatusContainer);

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import { BorderlessButton } from 'react-native-gesture-handler';
import sharedStyles from '../views/Styles';
@ -11,15 +11,15 @@ import ActivityIndicator from './ActivityIndicator';
const styles = StyleSheet.create({
error: {
...sharedStyles.textAlignCenter,
paddingTop: 5
paddingTop: 5,
},
inputContainer: {
marginBottom: 10
marginBottom: 10,
},
label: {
marginBottom: 10,
fontSize: 14,
...sharedStyles.textSemibold
...sharedStyles.textSemibold,
},
input: {
...sharedStyles.textRegular,
@ -27,27 +27,27 @@ const styles = StyleSheet.create({
fontSize: 16,
paddingHorizontal: 14,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 2
borderRadius: 2,
},
inputIconLeft: {
paddingLeft: 45
paddingLeft: 45,
},
inputIconRight: {
paddingRight: 45
paddingRight: 45,
},
wrap: {
position: 'relative'
position: 'relative',
},
iconContainer: {
position: 'absolute',
top: 14
top: 14,
},
iconLeft: {
left: 15
left: 15,
},
iconRight: {
right: 15
}
right: 15,
},
});
interface IRCTextInputProps {
@ -71,14 +71,13 @@ interface IRCTextInputProps {
}
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, any> {
static defaultProps = {
error: {},
theme: 'light'
theme: 'light',
}
state = {
showPassword: false
showPassword: false,
}
get iconLeft() {
@ -147,7 +146,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
style={[
styles.label,
{ color: themes[theme].titleText },
error.error && { color: dangerColor }
error.error && { color: dangerColor },
]}
>
{label}
@ -155,7 +154,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
) : null}
<View style={styles.wrap}>
<TextInput
/*@ts-ignore*/
/* @ts-ignore*/
style={[
styles.input,
iconLeft && styles.inputIconLeft,
@ -163,16 +162,16 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
{
backgroundColor: themes[theme].backgroundColor,
borderColor: themes[theme].separatorColor,
color: themes[theme].titleText
color: themes[theme].titleText,
},
error.error && {
color: dangerColor,
borderColor: dangerColor
borderColor: dangerColor,
},
inputStyle
inputStyle,
]}
ref={inputRef}
/*@ts-ignore*/
/* @ts-ignore*/
autoCorrect={false}
autoCapitalize='none'
underlineColorAndroid='transparent'

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import { CustomIcon } from '../lib/Icons';
@ -11,32 +11,32 @@ const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
detailsContainer: {
flex: 1,
flexDirection: 'row'
flexDirection: 'row',
},
detailContainer: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 8
marginRight: 8,
},
detailText: {
fontSize: 10,
marginLeft: 2,
...sharedStyles.textSemibold
...sharedStyles.textSemibold,
},
badgeContainer: {
flexDirection: 'row',
alignItems: 'center'
alignItems: 'center',
},
badge: {
width: 8,
height: 8,
borderRadius: 4,
marginRight: 8
}
marginRight: 8,
},
});
interface IThreadDetails {
@ -60,7 +60,7 @@ const ThreadDetails = ({
badgeColor,
toggleFollowThread,
style,
theme
theme,
}: IThreadDetails) => {
let { tcount } = item;
if (tcount >= 1000) {

View File

@ -10,13 +10,13 @@ import { withTheme } from '../theme';
const styles = StyleSheet.create({
toast: {
maxWidth: 300,
padding: 10
padding: 10,
},
text: {
fontSize: 14,
...sharedStyles.textRegular,
...sharedStyles.textAlignCenter
}
...sharedStyles.textAlignCenter,
},
});
export const LISTENER = 'Toast';
@ -27,6 +27,7 @@ interface IToastProps {
class Toast extends React.Component<IToastProps, any> {
private listener: any;
private toast: any;
componentDidMount() {

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { View, Text, InteractionManager } from 'react-native';
import { InteractionManager, Text, View } from 'react-native';
import isEmpty from 'lodash/isEmpty';
import { sha256 } from 'js-sha256';
import Modal from 'react-native-modal';
@ -26,18 +26,18 @@ interface ITwoFactor {
const methods: any = {
totp: {
text: 'Open_your_authentication_app_and_enter_the_code',
keyboardType: 'numeric'
keyboardType: 'numeric',
},
email: {
text: 'Verify_your_email_for_the_code_we_sent',
keyboardType: 'numeric'
keyboardType: 'numeric',
},
password: {
title: 'Please_enter_your_password',
text: 'For_your_security_you_must_enter_your_current_password_to_continue',
secureTextEntry: true,
keyboardType: 'default'
}
keyboardType: 'default',
},
};
const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
@ -90,7 +90,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
const color = themes[theme].titleText;
return (
<Modal
//@ts-ignore
// @ts-ignore
transparent
avoidKeyboard
useNativeDriver
@ -102,7 +102,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
<Text style={[styles.title, { color }]}>{I18n.t(method?.title || 'Two_Factor_Authentication')}</Text>
{method?.text ? <Text style={[styles.subtitle, { color }]}>{I18n.t(method.text)}</Text> : null}
<TextInput
/*@ts-ignore*/
/* @ts-ignore*/
value={code}
theme={theme}
inputRef={(e: any) => InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}
@ -141,7 +141,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
});
const mapStateToProps = (state: any) => ({
isMasterDetail: state.app.isMasterDetail
isMasterDetail: state.app.isMasterDetail,
});
export default connect(mapStateToProps)(withTheme(TwoFactor));

View File

@ -6,40 +6,40 @@ export default StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
alignItems: 'center',
},
content: {
padding: 16,
width: '100%',
borderRadius: 4
borderRadius: 4,
},
title: {
fontSize: 16,
paddingBottom: 8,
...sharedStyles.textBold,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
subtitle: {
fontSize: 14,
paddingBottom: 8,
...sharedStyles.textRegular,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
sendEmail: {
fontSize: 14,
paddingBottom: 24,
paddingTop: 8,
alignSelf: 'center',
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
button: {
marginBottom: 0
marginBottom: 0,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between'
justifyContent: 'space-between',
},
tablet: {
height: undefined
}
height: undefined,
},
});

View File

@ -21,7 +21,7 @@ export const Actions = ({ blockId, appId, elements, parser, theme }: IActions) =
return (
<>
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<Elements />
{showMoreVisible && (<Button theme={theme} title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />)}
</>

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import PropTypes from 'prop-types';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
@ -7,8 +7,8 @@ const styles = StyleSheet.create({
container: {
minHeight: 36,
alignItems: 'center',
flexDirection: 'row'
}
flexDirection: 'row',
},
});
export const Context = ({ elements, parser }: any) => (
@ -19,5 +19,5 @@ export const Context = ({ elements, parser }: any) => (
Context.propTypes = {
elements: PropTypes.array,
parser: PropTypes.object
parser: PropTypes.object,
};

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, View } from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker';
import Touchable from 'react-native-platform-touchable';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
@ -8,7 +8,6 @@ import moment from 'moment';
import Button from '../Button';
import { textParser } from './utils';
import { themes } from '../../constants/colors';
import sharedStyles from '../../views/Styles';
import { CustomIcon } from '../../lib/Icons';
import { isAndroid } from '../../utils/deviceInfo';
@ -21,19 +20,19 @@ const styles = StyleSheet.create({
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 2,
alignItems: 'center',
flexDirection: 'row'
flexDirection: 'row',
},
inputText: {
...sharedStyles.textRegular,
fontSize: 14
fontSize: 14,
},
icon: {
right: 16,
position: 'absolute'
position: 'absolute',
},
loading: {
padding: 0
}
padding: 0,
},
});
interface IDatePicker {
@ -51,7 +50,7 @@ interface IDatePicker {
}
export const DatePicker = ({
element, language, action, context, theme, loading, value, error
element, language, action, context, theme, loading, value, error,
}: IDatePicker) => {
const [show, onShow] = useState(false);
const { initial_date, placeholder } = element;
@ -86,7 +85,7 @@ export const DatePicker = ({
<Text
style={[
styles.inputText,
{ color: error ? themes[theme].dangerColor : themes[theme].titleText }
{ color: error ? themes[theme].dangerColor : themes[theme].titleText },
]}
>
{currentDate.toLocaleDateString(language)}

View File

@ -7,8 +7,8 @@ const styles = StyleSheet.create({
separator: {
width: '100%',
alignSelf: 'center',
marginBottom: 16
}
marginBottom: 16,
},
});
export const Divider = () => <List.Separator style={styles.separator} />;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { StyleSheet, View } from 'react-native';
import FastImage from '@rocket.chat/react-native-fast-image';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
@ -8,11 +8,11 @@ import Navigation from '../../lib/Navigation';
const styles = StyleSheet.create({
image: {
borderRadius: 2
borderRadius: 2,
},
mediaContext: {
marginRight: 8
}
marginRight: 8,
},
});
interface IThumb {

View File

@ -7,28 +7,28 @@ import { themes } from '../../constants/colors';
const styles = StyleSheet.create({
container: {
marginBottom: 16
marginBottom: 16,
},
label: {
fontSize: 14,
marginVertical: 10,
...sharedStyles.textSemibold
...sharedStyles.textSemibold,
},
description: {
marginBottom: 10,
fontSize: 15,
...sharedStyles.textRegular
...sharedStyles.textRegular,
},
error: {
marginTop: 8,
fontSize: 14,
...sharedStyles.textRegular,
...sharedStyles.textAlignCenter
...sharedStyles.textAlignCenter,
},
hint: {
fontSize: 14,
...sharedStyles.textRegular
}
...sharedStyles.textRegular,
},
});
interface IInput {
@ -42,7 +42,7 @@ interface IInput {
}
export const Input = ({
element, parser, label, description, error, hint, theme
element, parser, label, description, error, hint, theme,
}: IInput) => (
<View style={styles.container}>
{label ? <Text style={[styles.label, { color: error ? themes[theme].dangerColor : themes[theme].titleText }]}>{label}</Text> : null}

View File

@ -6,7 +6,6 @@ import FastImage from '@rocket.chat/react-native-fast-image';
import { themes } from '../../../constants/colors';
import { textParser } from '../utils';
import { CustomIcon } from '../../../lib/Icons';
import styles from './styles';
interface IChip {
@ -50,7 +49,7 @@ Chip.propTypes = {
const Chips = ({ items, onSelect, style, theme }: IChips) => (
<View style={styles.chips}>
{items.map(item => <Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} theme={theme} />)}
{items.map((item) => <Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} theme={theme} />)}
</View>
);

View File

@ -1,5 +1,5 @@
import React from 'react';
import { View, Text } from 'react-native';
import { Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import { CustomIcon } from '../../../lib/Icons';
@ -18,7 +18,7 @@ interface IInput {
}
const Input = ({
children, onPress, theme, loading, inputStyle, placeholder, disabled
children, onPress, theme, loading, inputStyle, placeholder, disabled,
}: IInput) => (
<Touchable
onPress={onPress}

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Text, FlatList } from 'react-native';
import { FlatList, Text } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import FastImage from '@rocket.chat/react-native-fast-image';
@ -7,7 +7,6 @@ import Check from '../../Check';
import * as List from '../../List';
import { textParser } from '../utils';
import { themes } from '../../../constants/colors';
import styles from './styles';
interface IItem {
@ -40,7 +39,7 @@ const Item = ({ item, selected, onSelect, theme }: IItem) => {
onPress={() => onSelect(item)}
style={[
styles.item,
{ backgroundColor: themes[theme].backgroundColor }
{ backgroundColor: themes[theme].backgroundColor },
]}
>
<>
@ -60,7 +59,7 @@ const Items = ({ items, selected, onSelect, theme }: IItems) => (
keyboardShouldPersistTaps='always'
ItemSeparatorComponent={List.Separator}
keyExtractor={keyExtractor}
renderItem={({ item }) => <Item item={item} onSelect={onSelect} theme={theme} selected={selected.find(s => s === item.value)} />}
renderItem={({ item }) => <Item item={item} onSelect={onSelect} theme={theme} selected={selected.find((s) => s === item.value)} />}
/>
);

View File

@ -1,21 +1,18 @@
import React, { useState, useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import {
View, Text, TouchableWithoutFeedback, Modal, KeyboardAvoidingView, Animated, Easing, StyleSheet
Animated, Easing, KeyboardAvoidingView, Modal, StyleSheet, Text, TouchableWithoutFeedback, View,
} from 'react-native';
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import Button from '../../Button';
import TextInput from '../../TextInput';
import { textParser } from '../utils';
import { themes } from '../../../constants/colors';
import I18n from '../../../i18n';
import { isIOS } from '../../../utils/deviceInfo';
import Chips from './Chips';
import Items from './Items';
import Input from './Input';
import styles from './styles';
interface IMultiSelect {
@ -39,7 +36,7 @@ const ANIMATION_DURATION = 200;
const ANIMATION_PROPS = {
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
useNativeDriver: true,
};
const animatedValue = new Animated.Value(0);
@ -57,7 +54,7 @@ export const MultiSelect = React.memo(({
onClose = () => {},
disabled,
inputStyle,
theme
theme,
}: IMultiSelect) => {
const [selected, select] = useState<any>(Array.isArray(values) ? values : []);
const [open, setOpen] = useState(false);
@ -86,8 +83,8 @@ export const MultiSelect = React.memo(({
animatedValue,
{
toValue: 1,
...ANIMATION_PROPS
}
...ANIMATION_PROPS,
},
).start();
setShowContent(true);
};
@ -98,8 +95,8 @@ export const MultiSelect = React.memo(({
animatedValue,
{
toValue: 0,
...ANIMATION_PROPS
}
...ANIMATION_PROPS,
},
).start(() => setShowContent(false));
};
@ -129,7 +126,7 @@ export const MultiSelect = React.memo(({
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
<TextInput
testID='multi-select-search'
/*@ts-ignore*/
/* @ts-ignore*/
onChangeText={onSearch || onSearchChange}
placeholder={I18n.t('Search')}
theme={theme}
@ -142,7 +139,7 @@ export const MultiSelect = React.memo(({
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [600, 0]
outputRange: [600, 0],
});
let button = multiselect ? (
@ -176,7 +173,7 @@ export const MultiSelect = React.memo(({
disabled={disabled}
inputStyle={inputStyle}
>
{/*@ts-ignore*/}
{/* @ts-ignore*/}
{items.length ? <Chips items={items} onSelect={onSelect} theme={theme} /> : <Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder.text}</Text>}
</Input>
);
@ -193,9 +190,9 @@ export const MultiSelect = React.memo(({
>
<TouchableWithoutFeedback onPress={onHide}>
<View style={styles.container}>
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<View style={{ ...StyleSheet.absoluteFill, opacity: themes[theme].backdropOpacity, backgroundColor: themes[theme].backdropColor }} />
{/*@ts-ignore*/}
{/* @ts-ignore*/}
<KeyboardAvoidingView style={styles.keyboardView} behavior={behavior}>
<Animated.View style={[styles.animatedContent, { transform: [{ translateY }] }]}>
{showContent ? renderContent() : null}

View File

@ -6,34 +6,34 @@ export default StyleSheet.create<any>({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'flex-end'
justifyContent: 'flex-end',
},
modal: {
height: 300,
width: '100%',
borderTopRightRadius: 16,
borderTopLeftRadius: 16,
overflow: 'hidden'
overflow: 'hidden',
},
content: {
padding: 16
padding: 16,
},
animatedContent: {
width: '100%'
width: '100%',
},
keyboardView: {
width: '100%'
width: '100%',
},
pickerText: {
...sharedStyles.textRegular,
paddingLeft: 6,
fontSize: 16
fontSize: 16,
},
item: {
height: 48,
maxWidth: '85%',
alignItems: 'center',
flexDirection: 'row'
flexDirection: 'row',
},
input: {
minHeight: 48,
@ -42,23 +42,23 @@ export default StyleSheet.create<any>({
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 2,
alignItems: 'center',
flexDirection: 'row'
flexDirection: 'row',
},
icon: {
position: 'absolute',
right: 16
right: 16,
},
itemContent: {
paddingBottom: 36
paddingBottom: 36,
},
items: {
height: 226
height: 226,
},
chips: {
paddingTop: 8,
flexDirection: 'row',
flexWrap: 'wrap',
marginRight: 50
marginRight: 50,
},
chip: {
flexDirection: 'row',
@ -67,24 +67,24 @@ export default StyleSheet.create<any>({
alignItems: 'center',
paddingHorizontal: 4,
marginBottom: 8,
marginRight: 8
marginRight: 8,
},
chipText: {
paddingHorizontal: 8,
flexShrink: 1,
...sharedStyles.textMedium,
fontSize: 14
fontSize: 14,
},
chipImage: {
marginLeft: 4,
borderRadius: 2,
width: 20,
height: 20
height: 20,
},
itemImage: {
marginRight: 8,
borderRadius: 2,
width: 24,
height: 24
}
height: 24,
},
});

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Text, FlatList, StyleSheet } from 'react-native';
import { FlatList, StyleSheet, Text } from 'react-native';
import Popover from 'react-native-popover-view';
import Touchable from 'react-native-platform-touchable';
@ -39,15 +39,15 @@ const keyExtractor = (item: any) => item.value;
const styles = StyleSheet.create({
menu: {
justifyContent: 'center'
justifyContent: 'center',
},
option: {
padding: 8,
minHeight: 32
minHeight: 32,
},
loading: {
padding: 0
}
padding: 0,
},
});
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: IOption) => (
@ -83,8 +83,8 @@ export const Overflow = ({ element, loading, action, parser, theme }: IOverflow)
return (
<>
<Touchable
/*@ts-ignore*/
ref={ref => touchable[blockId] = ref}
/* @ts-ignore*/
ref={(ref) => touchable[blockId] = ref}
background={Touchable.Ripple(themes[theme].bannerBackground)}
onPress={() => onShow(!show)}
hitSlop={BUTTON_HIT_SLOP}
@ -94,7 +94,7 @@ export const Overflow = ({ element, loading, action, parser, theme }: IOverflow)
</Touchable>
<Popover
isVisible={show}
/*@ts-ignore*/
/* @ts-ignore*/
fromView={touchable[blockId]}
onRequestClose={() => onShow(false)}
>

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