[improve] - fix the errors with auto-save
This commit is contained in:
parent
3604e7d4b3
commit
7b9f00510d
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
SENT: 0,
|
||||
TEMP: 1,
|
||||
ERROR: 2
|
||||
ERROR: 2,
|
||||
};
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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) => (
|
||||
|
|
|
@ -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}) => (
|
||||
|
|
|
@ -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,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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}
|
||||
>
|
||||
|
|
|
@ -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' />);
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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]}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) => (
|
||||
|
|
|
@ -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}>
|
||||
<>
|
||||
{
|
||||
|
|
|
@ -11,8 +11,8 @@ const styles = StyleSheet.create({
|
|||
top: -3,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export const Badge = ({ ...props }) => (
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) => (
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 },
|
||||
]}
|
||||
/>
|
||||
));
|
||||
|
|
|
@ -2,6 +2,6 @@ import { StyleSheet } from 'react-native';
|
|||
|
||||
export const styles = StyleSheet.create({
|
||||
contentContainerStyleFlatList: {
|
||||
paddingVertical: 32
|
||||
}
|
||||
paddingVertical: 32,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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} />;
|
||||
|
|
|
@ -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} />;
|
||||
|
|
|
@ -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)}
|
||||
>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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} />;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import { SendButton } from './buttons';
|
||||
|
||||
interface IMessageBoxRightButtons {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import BaseButton from './BaseButton';
|
||||
|
||||
interface IActionsButton {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import BaseButton from './BaseButton';
|
||||
|
||||
interface ICancelEditingButton {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import BaseButton from './BaseButton';
|
||||
import { themes } from '../../../constants/colors';
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import BaseButton from './BaseButton';
|
||||
|
||||
interface IToggleEmojiButton {
|
||||
|
|
|
@ -7,5 +7,5 @@ export {
|
|||
CancelEditingButton,
|
||||
ToggleEmojiButton,
|
||||
SendButton,
|
||||
ActionsButton
|
||||
ActionsButton,
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>) => {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2,5 +2,5 @@ export const TYPE: any = {
|
|||
CHOOSE: 'choose',
|
||||
CONFIRM: 'confirm',
|
||||
ENTER: 'enter',
|
||||
LOCKED: 'locked'
|
||||
LOCKED: 'locked',
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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)} />)}
|
||||
</>
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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} />;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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)} />}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue