[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 Navigation from './lib/Navigation';
|
||||||
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
||||||
import {
|
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';
|
} from './actions/app';
|
||||||
|
|
||||||
// Stacks
|
// Stacks
|
||||||
import AuthLoadingView from './views/AuthLoadingView';
|
import AuthLoadingView from './views/AuthLoadingView';
|
||||||
|
|
||||||
// SetUsername Stack
|
// SetUsername Stack
|
||||||
import SetUsernameView from './views/SetUsernameView';
|
import SetUsernameView from './views/SetUsernameView';
|
||||||
|
|
||||||
import OutsideStack from './stacks/OutsideStack';
|
import OutsideStack from './stacks/OutsideStack';
|
||||||
import InsideStack from './stacks/InsideStack';
|
import InsideStack from './stacks/InsideStack';
|
||||||
import MasterDetailStack from './stacks/MasterDetailStack';
|
import MasterDetailStack from './stacks/MasterDetailStack';
|
||||||
|
@ -101,7 +98,7 @@ const App = React.memo(({ root, isMasterDetail }: {root: string, isMasterDetail:
|
||||||
});
|
});
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
root: state.app.root,
|
root: state.app.root,
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppContainer = connect(mapStateToProps)(App);
|
const AppContainer = connect(mapStateToProps)(App);
|
||||||
|
|
|
@ -4,7 +4,7 @@ const FAILURE = 'FAILURE';
|
||||||
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
||||||
function createRequestTypes(base, types = defaultTypes) {
|
function createRequestTypes(base, types = defaultTypes) {
|
||||||
const res = {};
|
const res = {};
|
||||||
types.forEach(type => (res[type] = `${ base }_${ type }`));
|
types.forEach(type => res[type] = `${ base }_${ type }`);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,15 +125,15 @@ const keyCommands = [
|
||||||
discoverabilityTitle: I18n.t('Add_server')
|
discoverabilityTitle: I18n.t('Add_server')
|
||||||
},
|
},
|
||||||
// Refers to select rooms on list
|
// 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 }`,
|
input: `${ value }`,
|
||||||
modifierFlags: constants.keyModifierCommand
|
modifierFlags: constants.keyModifierCommand
|
||||||
}))),
|
})),
|
||||||
// Refers to select servers on list
|
// 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 }`,
|
input: `${ value }`,
|
||||||
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate
|
modifierFlags: constants.keyModifierCommand | constants.keyModifierAlternate
|
||||||
})))
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
export const setKeyCommands = () => KeyCommands.setKeyCommands(keyCommands);
|
export const setKeyCommands = () => KeyCommands.setKeyCommands(keyCommands);
|
||||||
|
|
|
@ -3,12 +3,12 @@ export const STATUS_COLORS: any = {
|
||||||
busy: '#f5455c',
|
busy: '#f5455c',
|
||||||
away: '#ffd21f',
|
away: '#ffd21f',
|
||||||
offline: '#cbced1',
|
offline: '#cbced1',
|
||||||
loading: '#9ea2a8'
|
loading: '#9ea2a8',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SWITCH_TRACK_COLOR = {
|
export const SWITCH_TRACK_COLOR = {
|
||||||
false: '#f5455c',
|
false: '#f5455c',
|
||||||
true: '#2de0a5'
|
true: '#2de0a5',
|
||||||
};
|
};
|
||||||
|
|
||||||
const mentions = {
|
const mentions = {
|
||||||
|
@ -16,7 +16,7 @@ const mentions = {
|
||||||
tunreadColor: '#1d74f5',
|
tunreadColor: '#1d74f5',
|
||||||
mentionMeColor: '#F5455C',
|
mentionMeColor: '#F5455C',
|
||||||
mentionGroupColor: '#F38C39',
|
mentionGroupColor: '#F38C39',
|
||||||
mentionOtherColor: '#F3BE08'
|
mentionOtherColor: '#F3BE08',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const themes: any = {
|
export const themes: any = {
|
||||||
|
@ -65,7 +65,7 @@ export const themes: any = {
|
||||||
previewBackground: '#1F2329',
|
previewBackground: '#1F2329',
|
||||||
previewTintColor: '#ffffff',
|
previewTintColor: '#ffffff',
|
||||||
backdropOpacity: 0.3,
|
backdropOpacity: 0.3,
|
||||||
...mentions
|
...mentions,
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
backgroundColor: '#030b1b',
|
backgroundColor: '#030b1b',
|
||||||
|
@ -112,7 +112,7 @@ export const themes: any = {
|
||||||
previewBackground: '#030b1b',
|
previewBackground: '#030b1b',
|
||||||
previewTintColor: '#ffffff',
|
previewTintColor: '#ffffff',
|
||||||
backdropOpacity: 0.9,
|
backdropOpacity: 0.9,
|
||||||
...mentions
|
...mentions,
|
||||||
},
|
},
|
||||||
black: {
|
black: {
|
||||||
backgroundColor: '#000000',
|
backgroundColor: '#000000',
|
||||||
|
@ -159,6 +159,6 @@ export const themes: any = {
|
||||||
previewBackground: '#000000',
|
previewBackground: '#000000',
|
||||||
previewTintColor: '#ffffff',
|
previewTintColor: '#ffffff',
|
||||||
backdropOpacity: 0.9,
|
backdropOpacity: 0.9,
|
||||||
...mentions
|
...mentions,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export default {
|
export default {
|
||||||
SENT: 0,
|
SENT: 0,
|
||||||
TEMP: 1,
|
TEMP: 1,
|
||||||
ERROR: 2
|
ERROR: 2,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,206 +1,206 @@
|
||||||
export default {
|
export default {
|
||||||
Accounts_AllowEmailChange: {
|
Accounts_AllowEmailChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowPasswordChange: {
|
Accounts_AllowPasswordChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowRealNameChange: {
|
Accounts_AllowRealNameChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowUserAvatarChange: {
|
Accounts_AllowUserAvatarChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowUserProfileChange: {
|
Accounts_AllowUserProfileChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowUserStatusMessageChange: {
|
Accounts_AllowUserStatusMessageChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowUsernameChange: {
|
Accounts_AllowUsernameChange: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AvatarBlockUnauthenticatedAccess: {
|
Accounts_AvatarBlockUnauthenticatedAccess: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_CustomFields: {
|
Accounts_CustomFields: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_EmailOrUsernamePlaceholder: {
|
Accounts_EmailOrUsernamePlaceholder: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_EmailVerification: {
|
Accounts_EmailVerification: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_NamePlaceholder: {
|
Accounts_NamePlaceholder: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_PasswordPlaceholder: {
|
Accounts_PasswordPlaceholder: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_PasswordReset: {
|
Accounts_PasswordReset: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_RegistrationForm: {
|
Accounts_RegistrationForm: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_RegistrationForm_LinkReplacementText: {
|
Accounts_RegistrationForm_LinkReplacementText: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_ShowFormLogin: {
|
Accounts_ShowFormLogin: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_ManuallyApproveNewUsers: {
|
Accounts_ManuallyApproveNewUsers: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
API_Use_REST_For_DDP_Calls: {
|
API_Use_REST_For_DDP_Calls: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_iframe_enabled: {
|
Accounts_iframe_enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_Iframe_api_url: {
|
Accounts_Iframe_api_url: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Accounts_Iframe_api_method: {
|
Accounts_Iframe_api_method: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
CROWD_Enable: {
|
CROWD_Enable: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
DirectMesssage_maxUsers: {
|
DirectMesssage_maxUsers: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
E2E_Enable: {
|
E2E_Enable: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_Directory_DefaultView: {
|
Accounts_Directory_DefaultView: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
FEDERATION_Enabled: {
|
FEDERATION_Enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Hide_System_Messages: {
|
Hide_System_Messages: {
|
||||||
type: 'valueAsArray'
|
type: 'valueAsArray',
|
||||||
},
|
},
|
||||||
LDAP_Enable: {
|
LDAP_Enable: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Livechat_request_comment_when_closing_conversation: {
|
Livechat_request_comment_when_closing_conversation: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_Enabled: {
|
Jitsi_Enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_SSL: {
|
Jitsi_SSL: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_Domain: {
|
Jitsi_Domain: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Jitsi_Enabled_TokenAuth: {
|
Jitsi_Enabled_TokenAuth: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_URL_Room_Hash: {
|
Jitsi_URL_Room_Hash: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_URL_Room_Prefix: {
|
Jitsi_URL_Room_Prefix: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Message_AllowDeleting: {
|
Message_AllowDeleting: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_AllowDeleting_BlockDeleteInMinutes: {
|
Message_AllowDeleting_BlockDeleteInMinutes: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
Message_AllowEditing: {
|
Message_AllowEditing: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_AllowEditing_BlockEditInMinutes: {
|
Message_AllowEditing_BlockEditInMinutes: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
Message_AllowPinning: {
|
Message_AllowPinning: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_AllowStarring: {
|
Message_AllowStarring: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_AudioRecorderEnabled: {
|
Message_AudioRecorderEnabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_GroupingPeriod: {
|
Message_GroupingPeriod: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
Message_TimeFormat: {
|
Message_TimeFormat: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Message_TimeAndDateFormat: {
|
Message_TimeAndDateFormat: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Site_Name: {
|
Site_Name: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Site_Url: {
|
Site_Url: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Store_Last_Message: {
|
Store_Last_Message: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
uniqueID: {
|
uniqueID: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
UI_Allow_room_names_with_special_chars: {
|
UI_Allow_room_names_with_special_chars: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
UI_Use_Real_Name: {
|
UI_Use_Real_Name: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Assets_favicon_512: {
|
Assets_favicon_512: {
|
||||||
type: null
|
type: null,
|
||||||
},
|
},
|
||||||
Message_Read_Receipt_Enabled: {
|
Message_Read_Receipt_Enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Message_Read_Receipt_Store_Users: {
|
Message_Read_Receipt_Store_Users: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Threads_enabled: {
|
Threads_enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
FileUpload_MediaTypeWhiteList: {
|
FileUpload_MediaTypeWhiteList: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
FileUpload_MaxFileSize: {
|
FileUpload_MaxFileSize: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
API_Gitlab_URL: {
|
API_Gitlab_URL: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
AutoTranslate_Enabled: {
|
AutoTranslate_Enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
CAS_enabled: {
|
CAS_enabled: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
CAS_login_url: {
|
CAS_login_url: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Force_Screen_Lock: {
|
Force_Screen_Lock: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Force_Screen_Lock_After: {
|
Force_Screen_Lock_After: {
|
||||||
type: 'valueAsNumber'
|
type: 'valueAsNumber',
|
||||||
},
|
},
|
||||||
Allow_Save_Media_to_Gallery: {
|
Allow_Save_Media_to_Gallery: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Accounts_AllowInvisibleStatusOption: {
|
Accounts_AllowInvisibleStatusOption: {
|
||||||
type: 'valueAsString'
|
type: 'valueAsString',
|
||||||
},
|
},
|
||||||
Jitsi_Enable_Teams: {
|
Jitsi_Enable_Teams: {
|
||||||
type: 'valueAsBoolean'
|
type: 'valueAsBoolean',
|
||||||
},
|
},
|
||||||
Jitsi_Enable_Channels: {
|
Jitsi_Enable_Channels: {
|
||||||
type: 'valuesAsBoolean'
|
type: 'valuesAsBoolean',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import React, {
|
import React, {
|
||||||
|
forwardRef,
|
||||||
|
isValidElement,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
useEffect,
|
|
||||||
forwardRef,
|
|
||||||
useImperativeHandle,
|
|
||||||
useCallback,
|
|
||||||
isValidElement
|
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { Keyboard, Text } from 'react-native';
|
import { Keyboard, Text } from 'react-native';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
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 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 * as Haptics from 'expo-haptics';
|
||||||
import { useBackHandler } from '@react-native-community/hooks';
|
import { useBackHandler } from '@react-native-community/hooks';
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ import { Handle } from './Handle';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import styles, { ITEM_HEIGHT } from './styles';
|
import styles, { ITEM_HEIGHT } from './styles';
|
||||||
import { isTablet, isIOS } from '../../utils/deviceInfo';
|
import { isIOS, isTablet } from '../../utils/deviceInfo';
|
||||||
import * as List from '../List';
|
import * as List from '../List';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { useOrientation, useDimensions, IDimensionsContextProps } from '../../dimensions';
|
import { IDimensionsContextProps, useDimensions, useOrientation } from '../../dimensions';
|
||||||
|
|
||||||
interface IActionSheetData {
|
interface IActionSheetData {
|
||||||
options: any;
|
options: any;
|
||||||
|
@ -43,7 +43,7 @@ const ANIMATION_DURATION = 250;
|
||||||
const ANIMATION_CONFIG = {
|
const ANIMATION_CONFIG = {
|
||||||
duration: ANIMATION_DURATION,
|
duration: ANIMATION_DURATION,
|
||||||
// https://easings.net/#easeInOutCubic
|
// 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) => {
|
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 insets = useSafeAreaInsets();
|
||||||
|
|
||||||
const maxSnap = Math.max(
|
const maxSnap = Math.max(
|
||||||
(
|
|
||||||
height!
|
height!
|
||||||
// Items height
|
// Items height
|
||||||
- (ITEM_HEIGHT * (data?.options?.length || 0))
|
- (ITEM_HEIGHT * (data?.options?.length || 0))
|
||||||
// Handle height
|
// Handle height
|
||||||
|
@ -67,8 +67,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
|
||||||
- insets.bottom
|
- insets.bottom
|
||||||
// Cancel button height
|
// Cancel button height
|
||||||
- (data?.hasCancel ? CANCEL_HEIGHT : 0)
|
- (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, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
showActionSheet: show,
|
showActionSheet: show,
|
||||||
hideActionSheet: hide
|
hideActionSheet: hide,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const renderHandle = useCallback(() => (
|
const renderHandle = useCallback(() => (
|
||||||
|
@ -149,7 +149,7 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
|
||||||
const opacity = interpolate(animatedPosition.current, {
|
const opacity = interpolate(animatedPosition.current, {
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: [0, themes[theme].backdropOpacity],
|
outputRange: [0, themes[theme].backdropOpacity],
|
||||||
extrapolate: Extrapolate.CLAMP
|
extrapolate: Extrapolate.CLAMP,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -164,8 +164,8 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
|
||||||
styles.backdrop,
|
styles.backdrop,
|
||||||
{
|
{
|
||||||
backgroundColor: themes[theme].backdropColor,
|
backgroundColor: themes[theme].backdropColor,
|
||||||
opacity
|
opacity,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</TapGestureHandler>
|
</TapGestureHandler>
|
||||||
|
@ -176,12 +176,12 @@ const ActionSheet = React.memo(forwardRef(({ children, theme }: {children: JSX.E
|
||||||
snapPoints={snaps}
|
snapPoints={snaps}
|
||||||
initialSnapIndex={closedSnapIndex}
|
initialSnapIndex={closedSnapIndex}
|
||||||
renderHandle={renderHandle}
|
renderHandle={renderHandle}
|
||||||
onSettle={index => (index === closedSnapIndex) && toggleVisible()}
|
onSettle={(index) => (index === closedSnapIndex) && toggleVisible()}
|
||||||
animatedPosition={animatedPosition.current}
|
animatedPosition={animatedPosition.current}
|
||||||
containerStyle={[
|
containerStyle={[
|
||||||
styles.container,
|
styles.container,
|
||||||
{ backgroundColor: themes[theme].focusedBackground },
|
{ backgroundColor: themes[theme].focusedBackground },
|
||||||
(isLandscape || isTablet) && styles.bottomSheet
|
(isLandscape || isTablet) && styles.bottomSheet,
|
||||||
] as any}
|
] as any}
|
||||||
animationConfig={ANIMATION_CONFIG}
|
animationConfig={ANIMATION_CONFIG}
|
||||||
// FlatList props
|
// 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 ActionSheet from './ActionSheet';
|
||||||
import { useTheme } from '../../theme';
|
import { useTheme } from '../../theme';
|
||||||
|
@ -10,7 +10,7 @@ interface IActionSheetProvider {
|
||||||
|
|
||||||
const context: IActionSheetProvider = React.createContext({
|
const context: IActionSheetProvider = React.createContext({
|
||||||
showActionSheet: () => {},
|
showActionSheet: () => {},
|
||||||
hideActionSheet: () => {}
|
hideActionSheet: () => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useActionSheet = () => useContext(context);
|
export const useActionSheet = () => useContext(context);
|
||||||
|
@ -33,7 +33,7 @@ export const ActionSheetProvider = React.memo(({ children }: {children: JSX.Elem
|
||||||
},
|
},
|
||||||
hideActionSheet: () => {
|
hideActionSheet: () => {
|
||||||
ref.current?.hideActionSheet();
|
ref.current?.hideActionSheet();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -8,46 +8,46 @@ export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderTopLeftRadius: 16,
|
borderTopLeftRadius: 16,
|
||||||
borderTopRightRadius: 16
|
borderTopRightRadius: 16,
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
height: ITEM_HEIGHT,
|
height: ITEM_HEIGHT,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
separator: {
|
separator: {
|
||||||
marginHorizontal: 16
|
marginHorizontal: 16,
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
paddingTop: 16
|
paddingTop: 16,
|
||||||
},
|
},
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
handle: {
|
handle: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingBottom: 8
|
paddingBottom: 8,
|
||||||
},
|
},
|
||||||
handleIndicator: {
|
handleIndicator: {
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 4,
|
height: 4,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
margin: 8
|
margin: 8,
|
||||||
},
|
},
|
||||||
backdrop: {
|
backdrop: {
|
||||||
...StyleSheet.absoluteFillObject
|
...StyleSheet.absoluteFillObject,
|
||||||
},
|
},
|
||||||
bottomSheet: {
|
bottomSheet: {
|
||||||
width: '50%',
|
width: '50%',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
left: '25%'
|
left: '25%',
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
|
@ -55,14 +55,14 @@ export default StyleSheet.create({
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
height: ITEM_HEIGHT,
|
height: ITEM_HEIGHT,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
marginBottom: 12
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textMedium,
|
...sharedStyles.textMedium,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
rightContainer: {
|
rightContainer: {
|
||||||
paddingLeft: 12
|
paddingLeft: 12,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-native';
|
import { ActivityIndicator, ActivityIndicatorProps, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
|
|
||||||
type TTheme = 'light' | 'dark' | 'black' | string;
|
type TTheme = 'light' | 'dark' | 'black' | string;
|
||||||
|
@ -13,7 +14,7 @@ interface IActivityIndicator extends ActivityIndicatorProps{
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
indicator: {
|
indicator: {
|
||||||
padding: 16,
|
padding: 16,
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
absolute: {
|
absolute: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -22,8 +23,8 @@ const styles = StyleSheet.create({
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const RCActivityIndicator = ({ theme = 'light', absolute, ...props }: IActivityIndicator) => (
|
const RCActivityIndicator = ({ theme = 'light', absolute, ...props }: IActivityIndicator) => (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, View, Text } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import sharedStyles from '../views/Styles';
|
import sharedStyles from '../views/Styles';
|
||||||
|
@ -9,15 +9,15 @@ import I18n from '../i18n';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'flex-end'
|
justifyContent: 'flex-end',
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
fontSize: 13
|
fontSize: 13,
|
||||||
},
|
},
|
||||||
bold: {
|
bold: {
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppVersion = React.memo(({ theme }: {theme: string}) => (
|
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 { avatarURL } from '../../utils/avatar';
|
||||||
import Emoji from '../markdown/Emoji';
|
import Emoji from '../markdown/Emoji';
|
||||||
import {IAvatar} from './interfaces';
|
import { IAvatar } from './interfaces';
|
||||||
|
|
||||||
const Avatar = React.memo(({
|
const Avatar = React.memo(({
|
||||||
server,
|
server,
|
||||||
style,
|
style,
|
||||||
avatar,
|
avatar,
|
||||||
children,
|
children,
|
||||||
user,
|
user,
|
||||||
|
@ -23,12 +23,11 @@ const Avatar = React.memo(({
|
||||||
rid,
|
rid,
|
||||||
blockUnauthenticatedAccess,
|
blockUnauthenticatedAccess,
|
||||||
serverVersion,
|
serverVersion,
|
||||||
text,
|
text,
|
||||||
size = 25,
|
size = 25,
|
||||||
borderRadius = 4,
|
borderRadius = 4,
|
||||||
type = 'd',
|
type = 'd',
|
||||||
}: Partial<IAvatar>) => {
|
}: Partial<IAvatar>) => {
|
||||||
|
|
||||||
if ((!text && !avatar && !emoji && !rid) || !server) {
|
if ((!text && !avatar && !emoji && !rid) || !server) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +35,7 @@ const Avatar = React.memo(({
|
||||||
const avatarStyle = {
|
const avatarStyle = {
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
borderRadius
|
borderRadius,
|
||||||
};
|
};
|
||||||
|
|
||||||
let image;
|
let image;
|
||||||
|
@ -64,7 +63,7 @@ const Avatar = React.memo(({
|
||||||
avatarETag,
|
avatarETag,
|
||||||
serverVersion,
|
serverVersion,
|
||||||
rid,
|
rid,
|
||||||
blockUnauthenticatedAccess
|
blockUnauthenticatedAccess,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ const Avatar = React.memo(({
|
||||||
source={{
|
source={{
|
||||||
uri,
|
uri,
|
||||||
headers: RocketChatSettings.customHeaders,
|
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 database from '../../lib/database';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import Avatar from './Avatar';
|
import Avatar from './Avatar';
|
||||||
import {IAvatar} from "./interfaces";
|
import { IAvatar } from './interfaces';
|
||||||
|
|
||||||
|
|
||||||
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
|
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
|
||||||
private mounted: boolean;
|
private mounted: boolean;
|
||||||
|
|
||||||
private subscription!: any;
|
private subscription!: any;
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
text: '',
|
text: '',
|
||||||
type: 'd'
|
type: 'd',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: Partial<IAvatar>) {
|
constructor(props: Partial<IAvatar>) {
|
||||||
|
@ -46,7 +46,7 @@ class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
|
||||||
return type === 'd';
|
return type === 'd';
|
||||||
}
|
}
|
||||||
|
|
||||||
init = async() => {
|
init = async () => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const usersCollection = db.get('users');
|
const usersCollection = db.get('users');
|
||||||
const subsCollection = db.get('subscriptions');
|
const subsCollection = db.get('subscriptions');
|
||||||
|
@ -99,6 +99,6 @@ const mapStateToProps = (state: any) => ({
|
||||||
blockUnauthenticatedAccess:
|
blockUnauthenticatedAccess:
|
||||||
state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess
|
state.share.settings?.Accounts_AvatarBlockUnauthenticatedAccess
|
||||||
?? state.settings.Accounts_AvatarBlockUnauthenticatedAccess
|
?? state.settings.Accounts_AvatarBlockUnauthenticatedAccess
|
||||||
?? true
|
?? true,
|
||||||
});
|
});
|
||||||
export default connect(mapStateToProps)(AvatarContainer);
|
export default connect(mapStateToProps)(AvatarContainer);
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
export interface IAvatar {
|
export interface IAvatar {
|
||||||
server: string;
|
server: string;
|
||||||
style: any,
|
style: any,
|
||||||
text: string;
|
text: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
emoji: string;
|
emoji: string;
|
||||||
size: number;
|
size: number;
|
||||||
borderRadius: number;
|
borderRadius: number;
|
||||||
type: string;
|
type: string;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
theme: string;
|
theme: string;
|
||||||
onPress(): void;
|
onPress(): void;
|
||||||
getCustomEmoji(): any;
|
getCustomEmoji(): any;
|
||||||
avatarETag: string;
|
avatarETag: string;
|
||||||
isStatic: boolean;
|
isStatic: boolean;
|
||||||
rid: string;
|
rid: string;
|
||||||
blockUnauthenticatedAccess: boolean;
|
blockUnauthenticatedAccess: boolean;
|
||||||
serverVersion: string;
|
serverVersion: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { storiesOf } from '@storybook/react-native';
|
import { storiesOf } from '@storybook/react-native';
|
||||||
|
|
||||||
import BackgroundContainer from '.';
|
|
||||||
import { ThemeContext } from '../../theme';
|
import { ThemeContext } from '../../theme';
|
||||||
import { longText } from '../../../storybook/utils';
|
import { longText } from '../../../storybook/utils';
|
||||||
|
import BackgroundContainer from '.';
|
||||||
|
|
||||||
const stories = storiesOf('BackgroundContainer', module);
|
const stories = storiesOf('BackgroundContainer', module);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 { withTheme } from '../../theme';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
|
@ -13,12 +13,12 @@ interface IBackgroundContainer {
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
position: 'absolute'
|
position: 'absolute',
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -28,15 +28,15 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
paddingHorizontal: 24,
|
paddingHorizontal: 24,
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BackgroundContainer = ({ theme, text, loading }: IBackgroundContainer) => (
|
const BackgroundContainer = ({ theme, text, loading }: IBackgroundContainer) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ImageBackground source={{ uri: `message_empty_${ theme }` }} style={styles.image} />
|
<ImageBackground source={{ uri: `message_empty_${ theme }` }} style={styles.image} />
|
||||||
{text ? <Text style={[styles.text, { color: themes[theme].auxiliaryTintColor }]}>{text}</Text> : null}
|
{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}
|
{loading ? <ActivityIndicator style={[styles.text, { color: themes[theme].auxiliaryTintColor }]} /> : null}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -26,26 +26,25 @@ const styles = StyleSheet.create({
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
height: 48,
|
height: 48,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
marginBottom: 12
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textMedium,
|
...sharedStyles.textMedium,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
opacity: 0.3
|
opacity: 0.3,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class Button extends React.PureComponent<Partial<IButtonProps>, any> {
|
export default class Button extends React.PureComponent<Partial<IButtonProps>, any> {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
title: 'Press me!',
|
title: 'Press me!',
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
onPress: () => alert('It works!'),
|
onPress: () => alert('It works!'),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
loading: false
|
loading: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -69,7 +68,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
|
||||||
? { backgroundColor }
|
? { backgroundColor }
|
||||||
: { backgroundColor: isPrimary ? themes[theme!].actionTintColor : themes[theme!].backgroundColor },
|
: { backgroundColor: isPrimary ? themes[theme!].actionTintColor : themes[theme!].backgroundColor },
|
||||||
disabled && styles.disabled,
|
disabled && styles.disabled,
|
||||||
style
|
style,
|
||||||
]}
|
]}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
|
@ -81,7 +80,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
|
||||||
style={[
|
style={[
|
||||||
styles.text,
|
styles.text,
|
||||||
{ color: textColor },
|
{ color: textColor },
|
||||||
fontSize && { fontSize }
|
fontSize && { fontSize },
|
||||||
]}
|
]}
|
||||||
accessibilityLabel={title}
|
accessibilityLabel={title}
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,8 +12,8 @@ const styles = StyleSheet.create({
|
||||||
icon: {
|
icon: {
|
||||||
width: 22,
|
width: 22,
|
||||||
height: 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' />);
|
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 React from 'react';
|
||||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
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) => (
|
const CustomEmoji = React.memo(({ baseUrl, emoji, style }: ICustomEmoji) => (
|
||||||
<FastImage
|
<FastImage
|
||||||
style={style}
|
style={style}
|
||||||
source={{
|
source={{
|
||||||
uri: `${ baseUrl }/emoji-custom/${ encodeURIComponent(emoji.content || emoji.name) }.${ emoji.extension }`,
|
uri: `${ baseUrl }/emoji-custom/${ encodeURIComponent(emoji.content || emoji.name) }.${ emoji.extension }`,
|
||||||
priority: FastImage.priority.high
|
priority: FastImage.priority.high,
|
||||||
}}
|
}}
|
||||||
resizeMode={FastImage.resizeMode.contain}
|
resizeMode={FastImage.resizeMode.contain}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, TouchableOpacity, FlatList } from 'react-native';
|
import { FlatList, Text, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import CustomEmoji from './CustomEmoji';
|
import CustomEmoji from './CustomEmoji';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import {IEmoji, IEmojiCategory} from "./interfaces";
|
import { IEmoji, IEmojiCategory } from './interfaces';
|
||||||
|
|
||||||
const EMOJI_SIZE = 50;
|
const EMOJI_SIZE = 50;
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ const renderEmoji = (emoji: IEmoji, size: number, baseUrl: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
|
class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
|
||||||
|
|
||||||
renderItem(emoji: any) {
|
renderItem(emoji: any) {
|
||||||
const { baseUrl, onEmojiSelected } = this.props;
|
const { baseUrl, onEmojiSelected } = this.props;
|
||||||
return (
|
return (
|
||||||
|
@ -52,7 +51,7 @@ class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
|
||||||
contentContainerStyle={{ marginHorizontal }}
|
contentContainerStyle={{ marginHorizontal }}
|
||||||
// rerender FlatList in case of width changes
|
// rerender FlatList in case of width changes
|
||||||
key={`emoji-category-${ width }`}
|
key={`emoji-category-${ width }`}
|
||||||
keyExtractor={item => (item && item.isCustom && item.content) || item}
|
keyExtractor={(item) => (item && item.isCustom && item.content) || item}
|
||||||
data={emojis}
|
data={emojis}
|
||||||
extraData={this.props}
|
extraData={this.props}
|
||||||
renderItem={({ item }) => this.renderItem(item)}
|
renderItem={({ item }) => this.renderItem(item)}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, TouchableOpacity, Text } from 'react-native';
|
import { Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
|
||||||
interface ITabBarProps {
|
interface ITabBarProps {
|
||||||
goToPage({}): void;
|
goToPage: Function;
|
||||||
activeTab: number,
|
activeTab: number,
|
||||||
tabs: [],
|
tabs: [],
|
||||||
tabEmojiStyle: object,
|
tabEmojiStyle: object,
|
||||||
|
@ -12,7 +13,6 @@ interface ITabBarProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TabBar extends React.Component<Partial<ITabBarProps>> {
|
export default class TabBar extends React.Component<Partial<ITabBarProps>> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: any) {
|
shouldComponentUpdate(nextProps: any) {
|
||||||
const { activeTab, theme } = this.props;
|
const { activeTab, theme } = this.props;
|
||||||
if (nextProps.activeTab !== activeTab) {
|
if (nextProps.activeTab !== activeTab) {
|
||||||
|
|
|
@ -2,43 +2,43 @@ const list = ['frequentlyUsed', 'custom', 'people', 'nature', 'food', 'activity'
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
tabLabel: '🕒',
|
tabLabel: '🕒',
|
||||||
category: list[0]
|
category: list[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '🚀',
|
tabLabel: '🚀',
|
||||||
category: list[1]
|
category: list[1],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '😃',
|
tabLabel: '😃',
|
||||||
category: list[2]
|
category: list[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '🐶',
|
tabLabel: '🐶',
|
||||||
category: list[3]
|
category: list[3],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '🍔',
|
tabLabel: '🍔',
|
||||||
category: list[4]
|
category: list[4],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '⚽',
|
tabLabel: '⚽',
|
||||||
category: list[5]
|
category: list[5],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '🚌',
|
tabLabel: '🚌',
|
||||||
category: list[6]
|
category: list[6],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '💡',
|
tabLabel: '💡',
|
||||||
category: list[7]
|
category: list[7],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '💛',
|
tabLabel: '💛',
|
||||||
category: list[8]
|
category: list[8],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tabLabel: '🏁',
|
tabLabel: '🏁',
|
||||||
category: list[9]
|
category: list[9],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
export default { list, tabs };
|
export default { list, tabs };
|
||||||
|
|
|
@ -17,11 +17,11 @@ import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import {IEmoji} from "./interfaces";
|
import { IEmoji } from './interfaces';
|
||||||
|
|
||||||
const scrollProps = {
|
const scrollProps = {
|
||||||
keyboardShouldPersistTaps: 'always',
|
keyboardShouldPersistTaps: 'always',
|
||||||
keyboardDismissMode: 'none'
|
keyboardDismissMode: 'none',
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IEmojiPickerProps {
|
interface IEmojiPickerProps {
|
||||||
|
@ -43,21 +43,20 @@ interface IEmojiPickerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
|
|
||||||
constructor(props: IEmojiPickerProps) {
|
constructor(props: IEmojiPickerProps) {
|
||||||
super(props);
|
super(props);
|
||||||
const customEmojis = Object.keys(props.customEmojis)
|
const customEmojis = Object.keys(props.customEmojis)
|
||||||
.filter(item => item === props.customEmojis[item].name)
|
.filter((item) => item === props.customEmojis[item].name)
|
||||||
.map(item => ({
|
.map((item) => ({
|
||||||
content: props.customEmojis[item].name,
|
content: props.customEmojis[item].name,
|
||||||
extension: props.customEmojis[item].extension,
|
extension: props.customEmojis[item].extension,
|
||||||
isCustom: true
|
isCustom: true,
|
||||||
}));
|
}));
|
||||||
this.state = {
|
this.state = {
|
||||||
frequentlyUsed: [],
|
frequentlyUsed: [],
|
||||||
customEmojis,
|
customEmojis,
|
||||||
show: false,
|
show: false,
|
||||||
width: null
|
width: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +88,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
const { onEmojiSelected } = this.props;
|
const { onEmojiSelected } = this.props;
|
||||||
if (emoji.isCustom) {
|
if (emoji.isCustom) {
|
||||||
this._addFrequentlyUsed({
|
this._addFrequentlyUsed({
|
||||||
content: emoji.content, extension: emoji.extension, isCustom: true
|
content: emoji.content, extension: emoji.extension, isCustom: true,
|
||||||
});
|
});
|
||||||
onEmojiSelected!(`:${ emoji.content }:`);
|
onEmojiSelected!(`:${ emoji.content }:`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,7 +103,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
_addFrequentlyUsed = protectedFunction(async(emoji: IEmoji) => {
|
_addFrequentlyUsed = protectedFunction(async (emoji: IEmoji) => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const freqEmojiCollection = db.get('frequently_used_emojis');
|
const freqEmojiCollection = db.get('frequently_used_emojis');
|
||||||
let freqEmojiRecord: any;
|
let freqEmojiRecord: any;
|
||||||
|
@ -114,7 +113,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.action(async() => {
|
await db.action(async () => {
|
||||||
if (freqEmojiRecord) {
|
if (freqEmojiRecord) {
|
||||||
await freqEmojiRecord.update((f: any) => {
|
await freqEmojiRecord.update((f: any) => {
|
||||||
f.count += 1;
|
f.count += 1;
|
||||||
|
@ -129,7 +128,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
updateFrequentlyUsed = async() => {
|
updateFrequentlyUsed = async () => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
|
const frequentlyUsedRecords = await db.get('frequently_used_emojis').query().fetch();
|
||||||
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
|
let frequentlyUsed: any = orderBy(frequentlyUsedRecords, ['count'], ['desc']);
|
||||||
|
@ -159,7 +158,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
return (
|
return (
|
||||||
<EmojiCategory
|
<EmojiCategory
|
||||||
emojis={emojis}
|
emojis={emojis}
|
||||||
onEmojiSelected={emoji => this.onEmojiSelected(emoji)}
|
onEmojiSelected={(emoji) => this.onEmojiSelected(emoji)}
|
||||||
style={styles.categoryContainer}
|
style={styles.categoryContainer}
|
||||||
width={width!}
|
width={width!}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
|
@ -179,16 +178,15 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
<View onLayout={this.onLayout} style={{ flex: 1 }}>
|
<View onLayout={this.onLayout} style={{ flex: 1 }}>
|
||||||
<ScrollableTabView
|
<ScrollableTabView
|
||||||
renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} theme={theme} />}
|
renderTabBar={() => <TabBar tabEmojiStyle={tabEmojiStyle} theme={theme} />}
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
contentProps={scrollProps}
|
contentProps={scrollProps}
|
||||||
style={{ backgroundColor: themes[theme!].focusedBackground }}
|
style={{ backgroundColor: themes[theme!].focusedBackground }}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
categories.tabs.map((tab, i) => (
|
categories.tabs.map((tab, i) => (
|
||||||
(i === 0 && frequentlyUsed.length === 0) ? null // when no frequentlyUsed don't show the tab
|
i === 0 && frequentlyUsed.length === 0 ? null // when no frequentlyUsed don't show the tab
|
||||||
: (
|
: this.renderCategory(tab.category, i, tab.tabLabel)
|
||||||
this.renderCategory(tab.category, i, tab.tabLabel)
|
))
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
</ScrollableTabView>
|
</ScrollableTabView>
|
||||||
</View>
|
</View>
|
||||||
|
@ -197,7 +195,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
customEmojis: state.customEmojis
|
customEmojis: state.customEmojis,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(EmojiPicker));
|
export default connect(mapStateToProps)(withTheme(EmojiPicker));
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
export interface IEmoji {
|
export interface IEmoji {
|
||||||
content: any;
|
content: any;
|
||||||
name: string;
|
name: string;
|
||||||
extension: any;
|
extension: any;
|
||||||
isCustom: boolean;
|
isCustom: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICustomEmoji {
|
export interface ICustomEmoji {
|
||||||
baseUrl: string,
|
baseUrl: string,
|
||||||
emoji: IEmoji,
|
emoji: IEmoji,
|
||||||
style: any
|
style: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEmojiCategory {
|
export interface IEmojiCategory {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
emojis: IEmoji[];
|
emojis: IEmoji[];
|
||||||
onEmojiSelected({}: any): void;
|
onEmojiSelected: Function;
|
||||||
emojisPerRow: number;
|
emojisPerRow: number;
|
||||||
width: number;
|
width: number;
|
||||||
style: any;
|
style: any;
|
||||||
tabLabel: string;
|
tabLabel: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,29 +4,29 @@ import sharedStyles from '../../views/Styles';
|
||||||
|
|
||||||
export default StyleSheet.create({
|
export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
tabsContainer: {
|
tabsContainer: {
|
||||||
height: 45,
|
height: 45,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
paddingTop: 5
|
paddingTop: 5,
|
||||||
},
|
},
|
||||||
tab: {
|
tab: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
paddingBottom: 10
|
paddingBottom: 10,
|
||||||
},
|
},
|
||||||
tabEmoji: {
|
tabEmoji: {
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
color: 'black'
|
color: 'black',
|
||||||
},
|
},
|
||||||
activeTabLine: {
|
activeTabLine: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
height: 2,
|
height: 2,
|
||||||
bottom: 0
|
bottom: 0,
|
||||||
},
|
},
|
||||||
tabLine: {
|
tabLine: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -34,25 +34,25 @@ export default StyleSheet.create({
|
||||||
right: 0,
|
right: 0,
|
||||||
height: 2,
|
height: 2,
|
||||||
backgroundColor: 'rgba(0,0,0,0.05)',
|
backgroundColor: 'rgba(0,0,0,0.05)',
|
||||||
bottom: 0
|
bottom: 0,
|
||||||
},
|
},
|
||||||
categoryContainer: {
|
categoryContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'flex-start'
|
alignItems: 'flex-start',
|
||||||
},
|
},
|
||||||
categoryInner: {
|
categoryInner: {
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'flex-start',
|
justifyContent: 'flex-start',
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
categoryEmoji: {
|
categoryEmoji: {
|
||||||
...sharedStyles.textAlignCenter,
|
...sharedStyles.textAlignCenter,
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
color: '#ffffff'
|
color: '#ffffff',
|
||||||
},
|
},
|
||||||
customCategoryEmoji: {
|
customCategoryEmoji: {
|
||||||
margin: 8
|
margin: 8,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,8 +18,8 @@ interface IFormContainer {
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
scrollView: {
|
scrollView: {
|
||||||
minHeight: '100%'
|
minHeight: '100%',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const FormContainerInner = ({ children }: {children: JSX.Element}) => (
|
export const FormContainerInner = ({ children }: {children: JSX.Element}) => (
|
||||||
|
@ -36,7 +36,7 @@ const FormContainer = ({ children, theme, testID, ...props }: IFormContainer) =>
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={sharedStyles.container}
|
style={sharedStyles.container}
|
||||||
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}
|
contentContainerStyle={[sharedStyles.containerScrollView, styles.scrollView]}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
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 { themes } from '../../constants/colors';
|
||||||
import { themedHeader } from '../../utils/navigation';
|
import { themedHeader } from '../../utils/navigation';
|
||||||
import { isIOS, isTablet } from '../../utils/deviceInfo';
|
import { isIOS, isTablet } from '../../utils/deviceInfo';
|
||||||
|
@ -13,9 +14,8 @@ export const getHeaderHeight = (isLandscape: boolean) => {
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
if (isLandscape && !isTablet) {
|
if (isLandscape && !isTablet) {
|
||||||
return 32;
|
return 32;
|
||||||
} else {
|
|
||||||
return 44;
|
|
||||||
}
|
}
|
||||||
|
return 44;
|
||||||
}
|
}
|
||||||
return 56;
|
return 56;
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ interface IHeaderTitlePosition {
|
||||||
|
|
||||||
export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
|
export const getHeaderTitlePosition = ({ insets, numIconsRight }: IHeaderTitlePosition) => ({
|
||||||
left: insets.left + 60,
|
left: insets.left + 60,
|
||||||
right: insets.right + Math.max(45 * numIconsRight, 15)
|
right: insets.right + Math.max(45 * numIconsRight, 15),
|
||||||
});
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -38,8 +38,8 @@ const styles = StyleSheet.create({
|
||||||
height: headerHeight,
|
height: headerHeight,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
elevation: 4
|
elevation: 4,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IHeader {
|
interface IHeader {
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const Drawer = React.memo(({ navigation, testID, ...props }: Partial<IHea
|
||||||
</Container>
|
</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>
|
<Container left>
|
||||||
<Item iconName='close' onPress={onPress} testID={testID} {...props} />
|
<Item iconName='close' onPress={onPress} testID={testID} {...props} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
interface IHeaderButtonContainer {
|
interface IHeaderButtonContainer {
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
|
@ -10,14 +10,14 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
marginLeft: 5
|
marginLeft: 5,
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
marginRight: 5
|
marginRight: 5,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const Container = ({ children, left = false }: IHeaderButtonContainer) => (
|
const Container = ({ children, left = false }: IHeaderButtonContainer) => (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
@ -17,27 +17,27 @@ interface IHeaderButtonItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BUTTON_HIT_SLOP = {
|
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({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
marginHorizontal: 6
|
marginHorizontal: 6,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
...Platform.select({
|
...Platform.select({
|
||||||
android: {
|
android: {
|
||||||
fontSize: 14
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
default: {
|
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}>
|
<Touchable onPress={onPress} testID={testID} hitSlop={BUTTON_HIT_SLOP} style={styles.container}>
|
||||||
<>
|
<>
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,8 +11,8 @@ const styles = StyleSheet.create({
|
||||||
top: -3,
|
top: -3,
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Badge = ({ ...props }) => (
|
export const Badge = ({ ...props }) => (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 Touchable from 'react-native-platform-touchable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Notifier } from 'react-native-notifier';
|
import { Notifier } from 'react-native-notifier';
|
||||||
|
@ -32,36 +32,36 @@ const styles = StyleSheet.create({
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginHorizontal: 10,
|
marginHorizontal: 10,
|
||||||
borderWidth: StyleSheet.hairlineWidth,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
inner: {
|
inner: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
marginRight: 10
|
marginRight: 10,
|
||||||
},
|
},
|
||||||
roomName: {
|
roomName: {
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
lineHeight: 20,
|
lineHeight: 20,
|
||||||
...sharedStyles.textMedium
|
...sharedStyles.textMedium,
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
lineHeight: 17,
|
lineHeight: 17,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
close: {
|
close: {
|
||||||
marginLeft: 10
|
marginLeft: 10,
|
||||||
},
|
},
|
||||||
small: {
|
small: {
|
||||||
width: '50%',
|
width: '50%',
|
||||||
alignSelf: 'center'
|
alignSelf: 'center',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const hideNotification = () => Notifier.hideNotification();
|
const hideNotification = () => Notifier.hideNotification();
|
||||||
|
@ -83,7 +83,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const item = {
|
const item = {
|
||||||
rid, name: title, t: type, prid
|
rid, name: title, t: type, prid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
|
@ -102,8 +102,8 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
|
||||||
{
|
{
|
||||||
backgroundColor: themes[theme].focusedBackground,
|
backgroundColor: themes[theme].focusedBackground,
|
||||||
borderColor: themes[theme].separatorColor,
|
borderColor: themes[theme].separatorColor,
|
||||||
marginTop: insets.top
|
marginTop: insets.top,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Touchable
|
<Touchable
|
||||||
|
@ -132,7 +132,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(NotifierComponent);
|
export default connect(mapStateToProps)(NotifierComponent);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { memo, useEffect } from 'react';
|
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 { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ const InAppNotification = memo(({ rooms, appState }: {rooms: any, appState: stri
|
||||||
showEasing: Easing.inOut(Easing.quad),
|
showEasing: Easing.inOut(Easing.quad),
|
||||||
Component: NotifierComponent,
|
Component: NotifierComponent,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
notification
|
notification,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -45,7 +45,7 @@ const InAppNotification = memo(({ rooms, appState }: {rooms: any, appState: stri
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
rooms: state.room.rooms,
|
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);
|
export default connect(mapStateToProps)(InAppNotification);
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ScrollView, StyleSheet } from 'react-native';
|
import { ScrollView, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingVertical: 16
|
paddingVertical: 16,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListContainer {
|
interface IListContainer {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, StyleSheet } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
@ -10,12 +10,12 @@ import { PADDING_HORIZONTAL } from './constants';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingBottom: 12,
|
paddingBottom: 12,
|
||||||
paddingHorizontal: PADDING_HORIZONTAL
|
paddingHorizontal: PADDING_HORIZONTAL,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListHeader {
|
interface IListHeader {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
@ -17,8 +17,8 @@ interface IListIcon {
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
icon: {
|
icon: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ListIcon = React.memo(({ theme, name, color, style, testID }: IListIcon) => (
|
const ListIcon = React.memo(({ theme, name, color, style, testID }: IListIcon) => (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, StyleSheet } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
@ -10,12 +10,12 @@ import I18n from '../../i18n';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingTop: 8,
|
paddingTop: 8,
|
||||||
paddingHorizontal: PADDING_HORIZONTAL
|
paddingHorizontal: PADDING_HORIZONTAL,
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListHeader {
|
interface IListHeader {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 Touch from '../../utils/touch';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
@ -17,42 +17,42 @@ const styles = StyleSheet.create({
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
paddingHorizontal: PADDING_HORIZONTAL
|
paddingHorizontal: PADDING_HORIZONTAL,
|
||||||
},
|
},
|
||||||
leftContainer: {
|
leftContainer: {
|
||||||
paddingRight: PADDING_HORIZONTAL
|
paddingRight: PADDING_HORIZONTAL,
|
||||||
},
|
},
|
||||||
rightContainer: {
|
rightContainer: {
|
||||||
paddingLeft: PADDING_HORIZONTAL
|
paddingLeft: PADDING_HORIZONTAL,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
opacity: 0.3
|
opacity: 0.3,
|
||||||
},
|
},
|
||||||
textContainer: {
|
textContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
textAlertContainer: {
|
textAlertContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
alertIcon: {
|
alertIcon: {
|
||||||
paddingLeft: 4
|
paddingLeft: 4,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
actionIndicator: {
|
actionIndicator: {
|
||||||
...I18nManager.isRTL
|
...I18nManager.isRTL
|
||||||
? { transform: [{ rotate: '180deg' }] }
|
? { transform: [{ rotate: '180deg' }] }
|
||||||
: {}
|
: {},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListItemContent {
|
interface IListItemContent {
|
||||||
|
@ -72,7 +72,7 @@ interface IListItemContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Content = React.memo(({
|
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) => (
|
}: IListItemContent) => (
|
||||||
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale! }]} testID={testID}>
|
<View style={[styles.container, disabled && styles.disabled, { height: BASE_HEIGHT * fontScale! }]} testID={testID}>
|
||||||
{left
|
{left
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import { Header } from '.';
|
import { Header } from '.';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
marginVertical: 16
|
marginVertical: 16,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListSection {
|
interface IListSection {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
separator: {
|
separator: {
|
||||||
height: StyleSheet.hairlineWidth
|
height: StyleSheet.hairlineWidth,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IListSeparator {
|
interface IListSeparator {
|
||||||
|
@ -20,7 +20,7 @@ const ListSeparator = React.memo(({ style, theme }: IListSeparator) => (
|
||||||
style={[
|
style={[
|
||||||
styles.separator,
|
styles.separator,
|
||||||
style,
|
style,
|
||||||
{ backgroundColor: themes[theme].separatorColor }
|
{ backgroundColor: themes[theme].separatorColor },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -2,6 +2,6 @@ import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
export const styles = StyleSheet.create({
|
export const styles = StyleSheet.create({
|
||||||
contentContainerStyleFlatList: {
|
contentContainerStyleFlatList: {
|
||||||
paddingVertical: 32
|
paddingVertical: 32,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
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 { withTheme } from '../theme';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
|
|
||||||
|
@ -7,13 +8,13 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
image: {
|
image: {
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
resizeMode: 'contain'
|
resizeMode: 'contain',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ILoadingProps {
|
interface ILoadingProps {
|
||||||
|
@ -22,12 +23,13 @@ interface ILoadingProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Loading extends React.PureComponent<ILoadingProps, any> {
|
class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
scale: new Animated.Value(1),
|
scale: new Animated.Value(1),
|
||||||
opacity: new Animated.Value(0)
|
opacity: new Animated.Value(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
private opacityAnimation: any;
|
private opacityAnimation: any;
|
||||||
|
|
||||||
private scaleAnimation: any;
|
private scaleAnimation: any;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -39,8 +41,8 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||||
{
|
{
|
||||||
toValue: 1,
|
toValue: 1,
|
||||||
duration: 200,
|
duration: 200,
|
||||||
useNativeDriver: true
|
useNativeDriver: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
this.scaleAnimation = Animated.loop(Animated.sequence([
|
this.scaleAnimation = Animated.loop(Animated.sequence([
|
||||||
Animated.timing(
|
Animated.timing(
|
||||||
|
@ -48,17 +50,17 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||||
{
|
{
|
||||||
toValue: 0,
|
toValue: 0,
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
useNativeDriver: true
|
useNativeDriver: true,
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
Animated.timing(
|
Animated.timing(
|
||||||
scale,
|
scale,
|
||||||
{
|
{
|
||||||
toValue: 1,
|
toValue: 1,
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
useNativeDriver: true
|
useNativeDriver: true,
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
@ -97,13 +99,13 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||||
|
|
||||||
const scaleAnimation = scale.interpolate({
|
const scaleAnimation = scale.interpolate({
|
||||||
inputRange: [0, 0.5, 1],
|
inputRange: [0, 0.5, 1],
|
||||||
outputRange: [1, 1.1, 1]
|
outputRange: [1, 1.1, 1],
|
||||||
});
|
});
|
||||||
|
|
||||||
const opacityAnimation = opacity.interpolate({
|
const opacityAnimation = opacity.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: [0, themes[theme].backdropOpacity],
|
outputRange: [0, themes[theme].backdropOpacity],
|
||||||
extrapolate: 'clamp'
|
extrapolate: 'clamp',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -121,15 +123,15 @@ class Loading extends React.PureComponent<ILoadingProps, any> {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
...StyleSheet.absoluteFill,
|
...StyleSheet.absoluteFill,
|
||||||
backgroundColor: themes[theme].backdropColor,
|
backgroundColor: themes[theme].backdropColor,
|
||||||
opacity: opacityAnimation
|
opacity: opacityAnimation,
|
||||||
}]}
|
}]}
|
||||||
/>
|
/>
|
||||||
<Animated.Image
|
<Animated.Image
|
||||||
source={require('../static/images/logo.png')}
|
source={require('../static/images/logo.png')}
|
||||||
style={[styles.image, {
|
style={[styles.image, {
|
||||||
transform: [{
|
transform: [{
|
||||||
scale: scaleAnimation
|
scale: scaleAnimation,
|
||||||
}]
|
}],
|
||||||
}]}
|
}]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</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 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 { connect } from 'react-redux';
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import * as AppleAuthentication from 'expo-apple-authentication';
|
import * as AppleAuthentication from 'expo-apple-authentication';
|
||||||
|
@ -12,7 +12,7 @@ import OrSeparator from './OrSeparator';
|
||||||
import Touch from '../utils/touch';
|
import Touch from '../utils/touch';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import random from '../utils/random';
|
import random from '../utils/random';
|
||||||
import { logEvent, events } from '../utils/log';
|
import { events, logEvent } from '../utils/log';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ const LOGIN_STYPE_REDIRECT = 'redirect';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
serviceButton: {
|
serviceButton: {
|
||||||
borderRadius: BORDER_RADIUS,
|
borderRadius: BORDER_RADIUS,
|
||||||
marginBottom: 10
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
serviceButtonContainer: {
|
serviceButtonContainer: {
|
||||||
borderRadius: BORDER_RADIUS,
|
borderRadius: BORDER_RADIUS,
|
||||||
|
@ -36,25 +36,25 @@ const styles = StyleSheet.create({
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
paddingHorizontal: 15
|
paddingHorizontal: 15,
|
||||||
},
|
},
|
||||||
serviceIcon: {
|
serviceIcon: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 15,
|
left: 15,
|
||||||
top: 12,
|
top: 12,
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24
|
height: 24,
|
||||||
},
|
},
|
||||||
serviceText: {
|
serviceText: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
fontSize: 16
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
serviceName: {
|
serviceName: {
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
marginBottom: 0
|
marginBottom: 0,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IOpenOAuth {
|
interface IOpenOAuth {
|
||||||
|
@ -94,12 +94,12 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
private _animation: any;
|
private _animation: any;
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
separator: true
|
separator: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
|
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT),
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressFacebook = () => {
|
onPressFacebook = () => {
|
||||||
|
@ -198,7 +198,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
logEvent(events.ENTER_WITH_CUSTOM_OAUTH);
|
logEvent(events.ENTER_WITH_CUSTOM_OAUTH);
|
||||||
const { server } = this.props;
|
const { server } = this.props;
|
||||||
const {
|
const {
|
||||||
serverURL, authorizePath, clientId, scope, service
|
serverURL, authorizePath, clientId, scope, service,
|
||||||
} = loginService;
|
} = loginService;
|
||||||
const redirectUri = `${ server }/_oauth/${ service }`;
|
const redirectUri = `${ server }/_oauth/${ service }`;
|
||||||
const state = this.getOAuthState();
|
const state = this.getOAuthState();
|
||||||
|
@ -227,14 +227,14 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
this.openOAuth({ url, ssoToken, authType: 'cas' });
|
this.openOAuth({ url, ssoToken, authType: 'cas' });
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressAppleLogin = async() => {
|
onPressAppleLogin = async () => {
|
||||||
logEvent(events.ENTER_WITH_APPLE);
|
logEvent(events.ENTER_WITH_APPLE);
|
||||||
try {
|
try {
|
||||||
const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({
|
const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({
|
||||||
requestedScopes: [
|
requestedScopes: [
|
||||||
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
||||||
AppleAuthentication.AppleAuthenticationScope.EMAIL
|
AppleAuthentication.AppleAuthenticationScope.EMAIL,
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
await RocketChat.loginOAuthOrSso({ fullName, email, identityToken });
|
await RocketChat.loginOAuthOrSso({ fullName, email, identityToken });
|
||||||
|
@ -249,7 +249,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
if (loginStyle === LOGIN_STYPE_REDIRECT) {
|
if (loginStyle === LOGIN_STYPE_REDIRECT) {
|
||||||
obj = {
|
obj = {
|
||||||
...obj,
|
...obj,
|
||||||
redirectUrl: 'rocketchat://auth'
|
redirectUrl: 'rocketchat://auth',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return Base64.encodeURI(JSON.stringify(obj));
|
return Base64.encodeURI(JSON.stringify(obj));
|
||||||
|
@ -270,7 +270,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
toValue: height,
|
toValue: height,
|
||||||
duration: 300,
|
duration: 300,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
easing: Easing.easeOutCubic
|
easing: Easing.easeOutCubic,
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
linkedin: this.onPressLinkedin,
|
linkedin: this.onPressLinkedin,
|
||||||
'meteor-developer': this.onPressMeteor,
|
'meteor-developer': this.onPressMeteor,
|
||||||
twitter: this.onPressTwitter,
|
twitter: this.onPressTwitter,
|
||||||
wordpress: this.onPressWordpress
|
wordpress: this.onPressWordpress,
|
||||||
};
|
};
|
||||||
return oauthProviders[name];
|
return oauthProviders[name];
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ class LoginServices extends React.PureComponent<ILoginServicesProps, any> {
|
||||||
const { length } = Object.values(services);
|
const { length } = Object.values(services);
|
||||||
const style = {
|
const style = {
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
height: servicesHeight
|
height: servicesHeight,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (length > 3 && separator) {
|
if (length > 3 && separator) {
|
||||||
|
@ -423,7 +423,7 @@ const mapStateToProps = (state: any) => ({
|
||||||
Gitlab_URL: state.settings.API_Gitlab_URL,
|
Gitlab_URL: state.settings.API_Gitlab_URL,
|
||||||
CAS_enabled: state.settings.CAS_enabled,
|
CAS_enabled: state.settings.CAS_enabled,
|
||||||
CAS_login_url: state.settings.CAS_login_url,
|
CAS_login_url: state.settings.CAS_login_url,
|
||||||
services: state.login.services
|
services: state.login.services,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(LoginServices));
|
export default connect(mapStateToProps)(withTheme(LoginServices));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { View, Text, FlatList, StyleSheet } from 'react-native';
|
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
@ -10,7 +10,7 @@ import database from '../../lib/database';
|
||||||
import { Button } from '../ActionSheet';
|
import { Button } from '../ActionSheet';
|
||||||
import { useDimensions } from '../../dimensions';
|
import { useDimensions } from '../../dimensions';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import {IEmoji} from "../EmojiPicker/interfaces";
|
import { IEmoji } from '../EmojiPicker/interfaces';
|
||||||
|
|
||||||
interface IHeader {
|
interface IHeader {
|
||||||
handleReaction: Function;
|
handleReaction: Function;
|
||||||
|
@ -40,7 +40,7 @@ const ITEM_MARGIN = 8;
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginHorizontal: CONTAINER_MARGIN
|
marginHorizontal: CONTAINER_MARGIN,
|
||||||
},
|
},
|
||||||
headerItem: {
|
headerItem: {
|
||||||
height: ITEM_SIZE,
|
height: ITEM_SIZE,
|
||||||
|
@ -48,17 +48,17 @@ const styles = StyleSheet.create({
|
||||||
borderRadius: ITEM_SIZE / 2,
|
borderRadius: ITEM_SIZE / 2,
|
||||||
marginHorizontal: ITEM_MARGIN,
|
marginHorizontal: ITEM_MARGIN,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
headerIcon: {
|
headerIcon: {
|
||||||
...sharedStyles.textAlignCenter,
|
...sharedStyles.textAlignCenter,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
color: '#fff'
|
color: '#fff',
|
||||||
},
|
},
|
||||||
customEmoji: {
|
customEmoji: {
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20
|
width: 20,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const keyExtractor = (item: any) => item?.id || item;
|
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 [items, setItems] = useState([]);
|
||||||
const { width, height }: any = useDimensions();
|
const { width, height }: any = useDimensions();
|
||||||
|
|
||||||
const setEmojis = async() => {
|
const setEmojis = async () => {
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const freqEmojiCollection = db.get('frequently_used_emojis');
|
const freqEmojiCollection = db.get('frequently_used_emojis');
|
||||||
|
|
|
@ -68,12 +68,12 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
editMessagePermission,
|
editMessagePermission,
|
||||||
deleteMessagePermission,
|
deleteMessagePermission,
|
||||||
forceDeleteMessagePermission,
|
forceDeleteMessagePermission,
|
||||||
pinMessagePermission
|
pinMessagePermission,
|
||||||
}: IMessageActions, ref): any => {
|
}: IMessageActions, ref): any => {
|
||||||
let permissions: any = {};
|
let permissions: any = {};
|
||||||
const { showActionSheet, hideActionSheet }: any = useActionSheet();
|
const { showActionSheet, hideActionSheet }: any = useActionSheet();
|
||||||
|
|
||||||
const getPermissions = async() => {
|
const getPermissions = async () => {
|
||||||
try {
|
try {
|
||||||
const permission = [editMessagePermission, deleteMessagePermission, forceDeleteMessagePermission, pinMessagePermission];
|
const permission = [editMessagePermission, deleteMessagePermission, forceDeleteMessagePermission, pinMessagePermission];
|
||||||
const result = await RocketChat.hasPermission(permission, room.rid);
|
const result = await RocketChat.hasPermission(permission, room.rid);
|
||||||
|
@ -81,7 +81,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
hasEditPermission: result[0],
|
hasEditPermission: result[0],
|
||||||
hasDeletePermission: result[1],
|
hasDeletePermission: result[1],
|
||||||
hasForceDeletePermission: result[2],
|
hasForceDeletePermission: result[2],
|
||||||
hasPinPermission: result[3]
|
hasPinPermission: result[3],
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
// Do nothing
|
// 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);
|
logEvent(events.ROOM_MSG_ACTION_UNREAD);
|
||||||
const { id: messageId, ts } = message;
|
const { id: messageId, ts } = message;
|
||||||
const { rid } = room;
|
const { rid } = room;
|
||||||
|
@ -177,7 +177,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
const subRecord = await subCollection.find(rid);
|
const subRecord = await subCollection.find(rid);
|
||||||
await db.action(async() => {
|
await db.action(async () => {
|
||||||
try {
|
try {
|
||||||
await subRecord.update((sub: any) => sub.lastOpen = ts);
|
await subRecord.update((sub: any) => sub.lastOpen = ts);
|
||||||
} catch {
|
} 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);
|
logEvent(events.ROOM_MSG_ACTION_PERMALINK);
|
||||||
try {
|
try {
|
||||||
const permalink: any = await getPermalink(message);
|
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);
|
logEvent(events.ROOM_MSG_ACTION_COPY);
|
||||||
await Clipboard.setString(message?.attachments?.[0]?.description || message.msg);
|
await Clipboard.setString(message?.attachments?.[0]?.description || message.msg);
|
||||||
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
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);
|
logEvent(events.ROOM_MSG_ACTION_SHARE);
|
||||||
try {
|
try {
|
||||||
const permalink: any = await getPermalink(message);
|
const permalink: any = await getPermalink(message);
|
||||||
|
@ -224,7 +224,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
replyInit(message, false);
|
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);
|
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
|
||||||
try {
|
try {
|
||||||
await RocketChat.toggleStarMessage(message.id, message.starred);
|
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);
|
logEvent(events.ROOM_MSG_ACTION_PIN);
|
||||||
try {
|
try {
|
||||||
await RocketChat.togglePinMessage(message.id, message.pinned);
|
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 {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
await db.action(async() => {
|
await db.action(async () => {
|
||||||
await message.update((m: any) => {
|
await message.update((m: any) => {
|
||||||
m.autoTranslate = !m.autoTranslate;
|
m.autoTranslate = !m.autoTranslate;
|
||||||
m._updatedAt = new Date();
|
m._updatedAt = new Date();
|
||||||
|
@ -279,7 +279,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
_id: message.id,
|
_id: message.id,
|
||||||
rid: message.subscription.id,
|
rid: message.subscription.id,
|
||||||
u: message.u,
|
u: message.u,
|
||||||
msg: message.msg
|
msg: message.msg,
|
||||||
};
|
};
|
||||||
await RocketChat.translateMessage(m, room.autoTranslateLanguage);
|
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);
|
logEvent(events.ROOM_MSG_ACTION_REPORT);
|
||||||
try {
|
try {
|
||||||
await RocketChat.reportMessage(message.id);
|
await RocketChat.reportMessage(message.id);
|
||||||
|
@ -305,7 +305,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
showConfirmationAlert({
|
showConfirmationAlert({
|
||||||
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
|
message: I18n.t('You_will_not_be_able_to_recover_this_message'),
|
||||||
confirmationText: I18n.t('Delete'),
|
confirmationText: I18n.t('Delete'),
|
||||||
onPress: async() => {
|
onPress: async () => {
|
||||||
try {
|
try {
|
||||||
logEvent(events.ROOM_MSG_ACTION_DELETE);
|
logEvent(events.ROOM_MSG_ACTION_DELETE);
|
||||||
await RocketChat.deleteMessage(message.id, message.subscription.id);
|
await RocketChat.deleteMessage(message.id, message.subscription.id);
|
||||||
|
@ -313,7 +313,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
|
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options = [{
|
options = [{
|
||||||
title: I18n.t('Reply_in_Thread'),
|
title: I18n.t('Reply_in_Thread'),
|
||||||
icon: 'threads',
|
icon: 'threads',
|
||||||
onPress: () => handleReply(message)
|
onPress: () => handleReply(message),
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Quote'),
|
title: I18n.t('Quote'),
|
||||||
icon: 'quote',
|
icon: 'quote',
|
||||||
onPress: () => handleQuote(message)
|
onPress: () => handleQuote(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Edit'),
|
title: I18n.t('Edit'),
|
||||||
icon: 'edit',
|
icon: 'edit',
|
||||||
onPress: () => handleEdit(message)
|
onPress: () => handleEdit(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,14 +351,14 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Permalink'),
|
title: I18n.t('Permalink'),
|
||||||
icon: 'link',
|
icon: 'link',
|
||||||
onPress: () => handlePermalink(message)
|
onPress: () => handlePermalink(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create Discussion
|
// Create Discussion
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Start_a_Discussion'),
|
title: I18n.t('Start_a_Discussion'),
|
||||||
icon: 'discussions',
|
icon: 'discussions',
|
||||||
onPress: () => handleCreateDiscussion(message)
|
onPress: () => handleCreateDiscussion(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark as unread
|
// Mark as unread
|
||||||
|
@ -366,7 +366,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Mark_unread'),
|
title: I18n.t('Mark_unread'),
|
||||||
icon: 'flag',
|
icon: 'flag',
|
||||||
onPress: () => handleUnread(message)
|
onPress: () => handleUnread(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,14 +374,14 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Copy'),
|
title: I18n.t('Copy'),
|
||||||
icon: 'copy',
|
icon: 'copy',
|
||||||
onPress: () => handleCopy(message)
|
onPress: () => handleCopy(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Share
|
// Share
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Share'),
|
title: I18n.t('Share'),
|
||||||
icon: 'share',
|
icon: 'share',
|
||||||
onPress: () => handleShare(message)
|
onPress: () => handleShare(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Star
|
// Star
|
||||||
|
@ -389,7 +389,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t(message.starred ? 'Unstar' : 'Star'),
|
title: I18n.t(message.starred ? 'Unstar' : 'Star'),
|
||||||
icon: message.starred ? 'star-filled' : 'star',
|
icon: message.starred ? 'star-filled' : 'star',
|
||||||
onPress: () => handleStar(message)
|
onPress: () => handleStar(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t(message.pinned ? 'Unpin' : 'Pin'),
|
title: I18n.t(message.pinned ? 'Unpin' : 'Pin'),
|
||||||
icon: 'pin',
|
icon: 'pin',
|
||||||
onPress: () => handlePin(message)
|
onPress: () => handlePin(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,7 +407,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t('Read_Receipt'),
|
title: I18n.t('Read_Receipt'),
|
||||||
icon: 'info',
|
icon: 'info',
|
||||||
onPress: () => handleReadReceipt(message)
|
onPress: () => handleReadReceipt(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +416,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
options.push({
|
options.push({
|
||||||
title: I18n.t(message.autoTranslate ? 'View_Original' : 'Translate'),
|
title: I18n.t(message.autoTranslate ? 'View_Original' : 'Translate'),
|
||||||
icon: 'language',
|
icon: 'language',
|
||||||
onPress: () => handleToggleTranslation(message)
|
onPress: () => handleToggleTranslation(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
title: I18n.t('Report'),
|
title: I18n.t('Report'),
|
||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
danger: true,
|
danger: true,
|
||||||
onPress: () => handleReport(message)
|
onPress: () => handleReport(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
|
@ -434,27 +434,27 @@ const MessageActions = React.memo(forwardRef(({
|
||||||
title: I18n.t('Delete'),
|
title: I18n.t('Delete'),
|
||||||
icon: 'delete',
|
icon: 'delete',
|
||||||
danger: true,
|
danger: true,
|
||||||
onPress: () => handleDelete(message)
|
onPress: () => handleDelete(message),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
const showMessageActions = async(message: any) => {
|
const showMessageActions = async (message: any) => {
|
||||||
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
logEvent(events.ROOM_SHOW_MSG_ACTIONS);
|
||||||
await getPermissions();
|
await getPermissions();
|
||||||
showActionSheet({
|
showActionSheet({
|
||||||
options: getOptions(message),
|
options: getOptions(message),
|
||||||
headerHeight: HEADER_HEIGHT,
|
headerHeight: HEADER_HEIGHT,
|
||||||
customHeader: (!isReadOnly || room.reactWhenReadOnly ? (
|
customHeader: !isReadOnly || room.reactWhenReadOnly ? (
|
||||||
<Header
|
<Header
|
||||||
server={server}
|
server={server}
|
||||||
handleReaction={handleReaction}
|
handleReaction={handleReaction}
|
||||||
isMasterDetail={isMasterDetail}
|
isMasterDetail={isMasterDetail}
|
||||||
message={message}
|
message={message}
|
||||||
/>
|
/>
|
||||||
) : null)
|
) : null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ const mapStateToProps = (state: any) => ({
|
||||||
editMessagePermission: state.permissions['edit-message'],
|
editMessagePermission: state.permissions['edit-message'],
|
||||||
deleteMessagePermission: state.permissions['delete-message'],
|
deleteMessagePermission: state.permissions['delete-message'],
|
||||||
forceDeleteMessagePermission: state.permissions['force-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);
|
export default connect(mapStateToProps, null, null, { forwardRef: true })(MessageActions);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { CancelEditingButton, ToggleEmojiButton } from './buttons';
|
import { CancelEditingButton, ToggleEmojiButton } from './buttons';
|
||||||
|
|
||||||
interface IMessageBoxLeftButtons {
|
interface IMessageBoxLeftButtons {
|
||||||
|
@ -11,7 +12,7 @@ interface IMessageBoxLeftButtons {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LeftButtons = React.memo(({
|
const LeftButtons = React.memo(({
|
||||||
theme, showEmojiKeyboard, editing, editCancel, openEmoji, closeEmoji
|
theme, showEmojiKeyboard, editing, editCancel, openEmoji, closeEmoji,
|
||||||
}: IMessageBoxLeftButtons) => {
|
}: IMessageBoxLeftButtons) => {
|
||||||
if (editing) {
|
if (editing) {
|
||||||
return <CancelEditingButton onPress={editCancel} theme={theme} />;
|
return <CancelEditingButton onPress={editCancel} theme={theme} />;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
import { CancelEditingButton, ActionsButton } from './buttons';
|
import { ActionsButton, CancelEditingButton } from './buttons';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IMessageBoxLeftButtons {
|
interface IMessageBoxLeftButtons {
|
||||||
|
@ -13,7 +13,7 @@ interface IMessageBoxLeftButtons {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LeftButtons = React.memo(({
|
const LeftButtons = React.memo(({
|
||||||
theme, showMessageBoxActions, editing, editCancel, isActionsEnabled
|
theme, showMessageBoxActions, editing, editCancel, isActionsEnabled,
|
||||||
}: IMessageBoxLeftButtons) => {
|
}: IMessageBoxLeftButtons) => {
|
||||||
if (editing) {
|
if (editing) {
|
||||||
return <CancelEditingButton onPress={editCancel} theme={theme} />;
|
return <CancelEditingButton onPress={editCancel} theme={theme} />;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TouchableOpacity, Text } from 'react-native';
|
import { Text, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../../i18n';
|
||||||
|
@ -9,7 +9,7 @@ interface IMessageBoxFixedMentionItem {
|
||||||
item: {
|
item: {
|
||||||
username: string;
|
username: string;
|
||||||
};
|
};
|
||||||
onPress({}): void;
|
onPress: Function;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ const FixedMentionItem = ({ item, onPress, theme }: IMessageBoxFixedMentionItem)
|
||||||
styles.mentionItem,
|
styles.mentionItem,
|
||||||
{
|
{
|
||||||
backgroundColor: themes[theme].auxiliaryBackground,
|
backgroundColor: themes[theme].auxiliaryBackground,
|
||||||
borderTopColor: themes[theme].separatorColor
|
borderTopColor: themes[theme].separatorColor,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
onPress={() => onPress(item)}
|
onPress={() => onPress(item)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import shortnameToUnicode from '../../../utils/shortnameToUnicode';
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
import MessageboxContext from '../Context';
|
import MessageboxContext from '../Context';
|
||||||
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
|
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
|
||||||
import {IEmoji} from "../../EmojiPicker/interfaces";
|
import { IEmoji } from '../../EmojiPicker/interfaces';
|
||||||
|
|
||||||
interface IMessageBoxMentionEmoji {
|
interface IMessageBoxMentionEmoji {
|
||||||
item: IEmoji;
|
item: IEmoji;
|
||||||
|
@ -33,7 +33,7 @@ const MentionEmoji = ({ item }: IMessageBoxMentionEmoji) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
MentionEmoji.propTypes = {
|
MentionEmoji.propTypes = {
|
||||||
item: PropTypes.object
|
item: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MentionEmoji;
|
export default MentionEmoji;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { TouchableOpacity, Text } from 'react-native';
|
import { Text, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
import Avatar from '../../Avatar';
|
import Avatar from '../../Avatar';
|
||||||
import MessageboxContext from '../Context';
|
import MessageboxContext from '../Context';
|
||||||
import FixedMentionItem from './FixedMentionItem';
|
import FixedMentionItem from './FixedMentionItem';
|
||||||
import MentionEmoji from './MentionEmoji';
|
import MentionEmoji from './MentionEmoji';
|
||||||
import { MENTIONS_TRACKING_TYPE_EMOJIS, MENTIONS_TRACKING_TYPE_COMMANDS } from '../constants';
|
import { MENTIONS_TRACKING_TYPE_COMMANDS, MENTIONS_TRACKING_TYPE_EMOJIS } from '../constants';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import {IEmoji} from "../../EmojiPicker/interfaces";
|
import { IEmoji } from '../../EmojiPicker/interfaces';
|
||||||
|
|
||||||
interface IMessageBoxMentionItem {
|
interface IMessageBoxMentionItem {
|
||||||
item: {
|
item: {
|
||||||
|
@ -79,8 +79,8 @@ const MentionItem = ({ item, trackingType, theme }: IMessageBoxMentionItem) => {
|
||||||
styles.mentionItem,
|
styles.mentionItem,
|
||||||
{
|
{
|
||||||
backgroundColor: themes[theme].auxiliaryBackground,
|
backgroundColor: themes[theme].auxiliaryBackground,
|
||||||
borderTopColor: themes[theme].separatorColor
|
borderTopColor: themes[theme].separatorColor,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
onPress={() => onPressMention(item)}
|
onPress={() => onPressMention(item)}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { Audio } from 'expo-av';
|
import { Audio } from 'expo-av';
|
||||||
import { BorderlessButton } from 'react-native-gesture-handler';
|
import { BorderlessButton } from 'react-native-gesture-handler';
|
||||||
import { getInfoAsync } from 'expo-file-system';
|
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 styles from './styles';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import { logEvent, events } from '../../utils/log';
|
import { events, logEvent } from '../../utils/log';
|
||||||
|
|
||||||
interface IMessageBoxRecordAudioProps {
|
interface IMessageBoxRecordAudioProps {
|
||||||
theme: string;
|
theme: string;
|
||||||
recordingCallback({}): void;
|
recordingCallback: Function;
|
||||||
onFinish({}): void;
|
onFinish: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RECORDING_EXTENSION = '.aac';
|
const RECORDING_EXTENSION = '.aac';
|
||||||
|
@ -25,7 +25,7 @@ const RECORDING_SETTINGS = {
|
||||||
audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
|
audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC,
|
||||||
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.sampleRate,
|
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.sampleRate,
|
||||||
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.android.numberOfChannels,
|
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: {
|
ios: {
|
||||||
extension: RECORDING_EXTENSION,
|
extension: RECORDING_EXTENSION,
|
||||||
|
@ -33,8 +33,8 @@ const RECORDING_SETTINGS = {
|
||||||
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.sampleRate,
|
sampleRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.sampleRate,
|
||||||
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.numberOfChannels,
|
numberOfChannels: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.numberOfChannels,
|
||||||
bitRate: Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY.ios.bitRate,
|
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 = {
|
const RECORDING_MODE = {
|
||||||
allowsRecordingIOS: true,
|
allowsRecordingIOS: true,
|
||||||
|
@ -43,7 +43,7 @@ const RECORDING_MODE = {
|
||||||
shouldDuckAndroid: true,
|
shouldDuckAndroid: true,
|
||||||
playThroughEarpieceAndroid: false,
|
playThroughEarpieceAndroid: false,
|
||||||
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
|
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) {
|
const formatTime = function(seconds: any) {
|
||||||
|
@ -56,6 +56,7 @@ const formatTime = function(seconds: any) {
|
||||||
|
|
||||||
export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAudioProps, any> {
|
export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAudioProps, any> {
|
||||||
private isRecorderBusy: boolean;
|
private isRecorderBusy: boolean;
|
||||||
|
|
||||||
private recording: any;
|
private recording: any;
|
||||||
|
|
||||||
constructor(props: IMessageBoxRecordAudioProps) {
|
constructor(props: IMessageBoxRecordAudioProps) {
|
||||||
|
@ -63,7 +64,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
this.isRecorderBusy = false;
|
this.isRecorderBusy = false;
|
||||||
this.state = {
|
this.state = {
|
||||||
isRecording: false,
|
isRecording: false,
|
||||||
recordingDurationMillis: 0
|
recordingDurationMillis: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
return formatTime(Math.floor(recordingDurationMillis / 1000));
|
return formatTime(Math.floor(recordingDurationMillis / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
isRecordingPermissionGranted = async() => {
|
isRecordingPermissionGranted = async () => {
|
||||||
try {
|
try {
|
||||||
const permission = await Audio.getPermissionsAsync();
|
const permission = await Audio.getPermissionsAsync();
|
||||||
if (permission.status === 'granted') {
|
if (permission.status === 'granted') {
|
||||||
|
@ -101,11 +102,11 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
onRecordingStatusUpdate = (status: any) => {
|
onRecordingStatusUpdate = (status: any) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isRecording: status.isRecording,
|
isRecording: status.isRecording,
|
||||||
recordingDurationMillis: status.durationMillis
|
recordingDurationMillis: status.durationMillis,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
startRecordingAudio = async() => {
|
startRecordingAudio = async () => {
|
||||||
logEvent(events.ROOM_AUDIO_RECORD);
|
logEvent(events.ROOM_AUDIO_RECORD);
|
||||||
if (!this.isRecorderBusy) {
|
if (!this.isRecorderBusy) {
|
||||||
this.isRecorderBusy = true;
|
this.isRecorderBusy = true;
|
||||||
|
@ -130,7 +131,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
finishRecordingAudio = async() => {
|
finishRecordingAudio = async () => {
|
||||||
logEvent(events.ROOM_AUDIO_FINISH);
|
logEvent(events.ROOM_AUDIO_FINISH);
|
||||||
if (!this.isRecorderBusy) {
|
if (!this.isRecorderBusy) {
|
||||||
const { onFinish } = this.props;
|
const { onFinish } = this.props;
|
||||||
|
@ -147,7 +148,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
type: 'audio/aac',
|
type: 'audio/aac',
|
||||||
store: 'Uploads',
|
store: 'Uploads',
|
||||||
path: fileURI,
|
path: fileURI,
|
||||||
size: fileData.size
|
size: fileData.size,
|
||||||
};
|
};
|
||||||
|
|
||||||
onFinish(fileInfo);
|
onFinish(fileInfo);
|
||||||
|
@ -160,7 +161,7 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cancelRecordingAudio = async() => {
|
cancelRecordingAudio = async () => {
|
||||||
logEvent(events.ROOM_AUDIO_CANCEL);
|
logEvent(events.ROOM_AUDIO_CANCEL);
|
||||||
if (!this.isRecorderBusy) {
|
if (!this.isRecorderBusy) {
|
||||||
this.isRecorderBusy = true;
|
this.isRecorderBusy = true;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, StyleSheet } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
@ -11,33 +11,33 @@ import { themes } from '../../constants/colors';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
paddingTop: 10
|
paddingTop: 10,
|
||||||
},
|
},
|
||||||
messageContainer: {
|
messageContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
marginHorizontal: 10,
|
marginHorizontal: 10,
|
||||||
paddingHorizontal: 15,
|
paddingHorizontal: 15,
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textMedium
|
...sharedStyles.textMedium,
|
||||||
},
|
},
|
||||||
time: {
|
time: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
lineHeight: 16,
|
lineHeight: 16,
|
||||||
marginLeft: 6,
|
marginLeft: 6,
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
fontWeight: '300'
|
fontWeight: '300',
|
||||||
},
|
},
|
||||||
close: {
|
close: {
|
||||||
marginRight: 10
|
marginRight: 10,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IMessageBoxReplyPreview {
|
interface IMessageBoxReplyPreview {
|
||||||
|
@ -51,13 +51,13 @@ interface IMessageBoxReplyPreview {
|
||||||
close(): void;
|
close(): void;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
username: string;
|
username: string;
|
||||||
getCustomEmoji(): void;
|
getCustomEmoji: Function;
|
||||||
theme: string;
|
theme: string;
|
||||||
useRealName: boolean;
|
useRealName: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReplyPreview = React.memo(({
|
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) => {
|
}: IMessageBoxReplyPreview) => {
|
||||||
if (!replying) {
|
if (!replying) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -68,7 +68,7 @@ const ReplyPreview = React.memo(({
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
styles.container,
|
||||||
{ backgroundColor: themes[theme].messageboxBackground }
|
{ backgroundColor: themes[theme].messageboxBackground },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={[styles.messageContainer, { backgroundColor: themes[theme].chatComponentBackground }]}>
|
<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.username, { color: themes[theme].tintColor }]}>{useRealName ? message.u?.name : message.u?.username}</Text>
|
||||||
<Text style={[styles.time, { color: themes[theme].auxiliaryText }]}>{time}</Text>
|
<Text style={[styles.time, { color: themes[theme].auxiliaryText }]}>{time}</Text>
|
||||||
</View>
|
</View>
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<Markdown
|
<Markdown
|
||||||
msg={message.msg}
|
msg={message.msg}
|
||||||
baseUrl={baseUrl}
|
baseUrl={baseUrl}
|
||||||
|
@ -95,7 +95,7 @@ const ReplyPreview = React.memo(({
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||||
baseUrl: state.server.server,
|
baseUrl: state.server.server,
|
||||||
useRealName: state.settings.UI_Use_Real_Name
|
useRealName: state.settings.UI_Use_Real_Name,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(ReplyPreview);
|
export default connect(mapStateToProps)(ReplyPreview);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
import { SendButton, ActionsButton } from './buttons';
|
import { ActionsButton, SendButton } from './buttons';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IMessageBoxRightButtons {
|
interface IMessageBoxRightButtons {
|
||||||
|
@ -13,7 +13,7 @@ interface IMessageBoxRightButtons {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RightButtons = React.memo(({
|
const RightButtons = React.memo(({
|
||||||
theme, showSend, submit, showMessageBoxActions, isActionsEnabled
|
theme, showSend, submit, showMessageBoxActions, isActionsEnabled,
|
||||||
}: IMessageBoxRightButtons) => {
|
}: IMessageBoxRightButtons) => {
|
||||||
if (showSend) {
|
if (showSend) {
|
||||||
return <SendButton onPress={submit} theme={theme} />;
|
return <SendButton onPress={submit} theme={theme} />;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { SendButton } from './buttons';
|
import { SendButton } from './buttons';
|
||||||
|
|
||||||
interface IMessageBoxRightButtons {
|
interface IMessageBoxRightButtons {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BaseButton from './BaseButton';
|
import BaseButton from './BaseButton';
|
||||||
|
|
||||||
interface IActionsButton {
|
interface IActionsButton {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BaseButton from './BaseButton';
|
import BaseButton from './BaseButton';
|
||||||
|
|
||||||
interface ICancelEditingButton {
|
interface ICancelEditingButton {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BaseButton from './BaseButton';
|
import BaseButton from './BaseButton';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import BaseButton from './BaseButton';
|
import BaseButton from './BaseButton';
|
||||||
|
|
||||||
interface IToggleEmojiButton {
|
interface IToggleEmojiButton {
|
||||||
|
|
|
@ -7,5 +7,5 @@ export {
|
||||||
CancelEditingButton,
|
CancelEditingButton,
|
||||||
ToggleEmojiButton,
|
ToggleEmojiButton,
|
||||||
SendButton,
|
SendButton,
|
||||||
ActionsButton
|
ActionsButton,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { Component } from 'react';
|
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 { connect } from 'react-redux';
|
||||||
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
import { KeyboardAccessoryView } from 'react-native-ui-lib/keyboard';
|
||||||
import ImagePicker from 'react-native-image-crop-picker';
|
import ImagePicker from 'react-native-image-crop-picker';
|
||||||
|
@ -15,33 +15,35 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import database from '../../lib/database';
|
import database from '../../lib/database';
|
||||||
import { emojis } from '../../emojis';
|
import { emojis } from '../../emojis';
|
||||||
import log, { logEvent, events } from '../../utils/log';
|
import log, { events, logEvent } from '../../utils/log';
|
||||||
import RecordAudio from './RecordAudio';
|
import RecordAudio from './RecordAudio';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import ReplyPreview from './ReplyPreview';
|
import ReplyPreview from './ReplyPreview';
|
||||||
import debounce from '../../utils/debounce';
|
import debounce from '../../utils/debounce';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line import/extensions,import/no-unresolved
|
||||||
import LeftButtons from './LeftButtons';
|
import LeftButtons from './LeftButtons';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line import/extensions,import/no-unresolved
|
||||||
import RightButtons from './RightButtons';
|
import RightButtons from './RightButtons';
|
||||||
import { isAndroid, isTablet } from '../../utils/deviceInfo';
|
import { isAndroid, isTablet } from '../../utils/deviceInfo';
|
||||||
import { canUploadFile } from '../../utils/media';
|
import { canUploadFile } from '../../utils/media';
|
||||||
import EventEmiter from '../../utils/events';
|
import EventEmiter from '../../utils/events';
|
||||||
import {
|
import {
|
||||||
KEY_COMMAND,
|
KEY_COMMAND,
|
||||||
handleCommandTyping,
|
handleCommandShowUpload,
|
||||||
handleCommandSubmit,
|
handleCommandSubmit,
|
||||||
handleCommandShowUpload
|
handleCommandTyping,
|
||||||
} from '../../commands';
|
} from '../../commands';
|
||||||
import Mentions from './Mentions';
|
import Mentions from './Mentions';
|
||||||
import MessageboxContext from './Context';
|
import MessageboxContext from './Context';
|
||||||
import {
|
import {
|
||||||
MENTIONS_TRACKING_TYPE_EMOJIS,
|
|
||||||
MENTIONS_TRACKING_TYPE_COMMANDS,
|
|
||||||
MENTIONS_COUNT_TO_DISPLAY,
|
MENTIONS_COUNT_TO_DISPLAY,
|
||||||
|
MENTIONS_TRACKING_TYPE_COMMANDS,
|
||||||
|
MENTIONS_TRACKING_TYPE_EMOJIS,
|
||||||
|
MENTIONS_TRACKING_TYPE_ROOMS,
|
||||||
MENTIONS_TRACKING_TYPE_USERS,
|
MENTIONS_TRACKING_TYPE_USERS,
|
||||||
MENTIONS_TRACKING_TYPE_ROOMS
|
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import CommandsPreview from './CommandsPreview';
|
import CommandsPreview from './CommandsPreview';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
|
@ -58,17 +60,17 @@ const imagePickerConfig = {
|
||||||
cropping: true,
|
cropping: true,
|
||||||
compressImageQuality: 0.8,
|
compressImageQuality: 0.8,
|
||||||
avoidEmptySpaceAroundImage: false,
|
avoidEmptySpaceAroundImage: false,
|
||||||
freeStyleCropEnabled: true
|
freeStyleCropEnabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const libraryPickerConfig = {
|
const libraryPickerConfig = {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
compressVideoPreset: 'Passthrough',
|
compressVideoPreset: 'Passthrough',
|
||||||
mediaType: 'any'
|
mediaType: 'any',
|
||||||
};
|
};
|
||||||
|
|
||||||
const videoPickerConfig = {
|
const videoPickerConfig = {
|
||||||
mediaType: 'video'
|
mediaType: 'video',
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IMessageBoxProps {
|
interface IMessageBoxProps {
|
||||||
|
@ -95,18 +97,18 @@ interface IMessageBoxProps {
|
||||||
FileUpload_MediaTypeWhiteList: string;
|
FileUpload_MediaTypeWhiteList: string;
|
||||||
FileUpload_MaxFileSize: number;
|
FileUpload_MaxFileSize: number;
|
||||||
Message_AudioRecorderEnabled: boolean;
|
Message_AudioRecorderEnabled: boolean;
|
||||||
getCustomEmoji(): void;
|
getCustomEmoji: Function;
|
||||||
editCancel(): void;
|
editCancel: Function;
|
||||||
editRequest({}): void;
|
editRequest: Function;
|
||||||
onSubmit({}, {}?, {}?): void;
|
onSubmit: Function;
|
||||||
typing({}, {}): void;
|
typing: Function;
|
||||||
theme: string;
|
theme: string;
|
||||||
replyCancel(): void;
|
replyCancel(): void;
|
||||||
showSend: boolean;
|
showSend: boolean;
|
||||||
navigation: any;
|
navigation: any;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
showActionSheet({}): void;
|
showActionSheet: Function;
|
||||||
iOSScrollBehavior: number;
|
iOSScrollBehavior: number;
|
||||||
sharing: boolean;
|
sharing: boolean;
|
||||||
isActionsEnabled: boolean;
|
isActionsEnabled: boolean;
|
||||||
|
@ -127,31 +129,44 @@ interface IMessageBoxState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
|
||||||
private text: string;
|
private text: string;
|
||||||
|
|
||||||
private selection: { start: number; end: number };
|
private selection: { start: number; end: number };
|
||||||
|
|
||||||
private focused: boolean;
|
private focused: boolean;
|
||||||
|
|
||||||
private options: any;
|
private options: any;
|
||||||
|
|
||||||
private imagePickerConfig: any;
|
private imagePickerConfig: any;
|
||||||
|
|
||||||
private libraryPickerConfig: any;
|
private libraryPickerConfig: any;
|
||||||
|
|
||||||
private videoPickerConfig: any;
|
private videoPickerConfig: any;
|
||||||
|
|
||||||
private room: any;
|
private room: any;
|
||||||
|
|
||||||
private thread: any;
|
private thread: any;
|
||||||
|
|
||||||
private unsubscribeFocus: any;
|
private unsubscribeFocus: any;
|
||||||
|
|
||||||
private trackingTimeout: any;
|
private trackingTimeout: any;
|
||||||
|
|
||||||
private tracking: any;
|
private tracking: any;
|
||||||
|
|
||||||
private unsubscribeBlur: any;
|
private unsubscribeBlur: any;
|
||||||
|
|
||||||
private component: any;
|
private component: any;
|
||||||
|
|
||||||
private typingTimeout: any;
|
private typingTimeout: any;
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
message: {
|
message: {
|
||||||
id: ''
|
id: '',
|
||||||
},
|
},
|
||||||
sharing: false,
|
sharing: false,
|
||||||
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
|
iOSScrollBehavior: NativeModules.KeyboardTrackingViewTempManager?.KeyboardTrackingScrollBehaviorFixedOffset,
|
||||||
isActionsEnabled: true,
|
isActionsEnabled: true,
|
||||||
getCustomEmoji: () => {}
|
getCustomEmoji: () => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: IMessageBoxProps) {
|
constructor(props: IMessageBoxProps) {
|
||||||
|
@ -165,7 +180,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
commandPreview: [],
|
commandPreview: [],
|
||||||
showCommandPreview: false,
|
showCommandPreview: false,
|
||||||
command: {},
|
command: {},
|
||||||
tshow: false
|
tshow: false,
|
||||||
};
|
};
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.selection = { start: 0, end: 0 };
|
this.selection = { start: 0, end: 0 };
|
||||||
|
@ -176,49 +191,49 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
{
|
{
|
||||||
title: I18n.t('Take_a_photo'),
|
title: I18n.t('Take_a_photo'),
|
||||||
icon: 'camera-photo',
|
icon: 'camera-photo',
|
||||||
onPress: this.takePhoto
|
onPress: this.takePhoto,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: I18n.t('Take_a_video'),
|
title: I18n.t('Take_a_video'),
|
||||||
icon: 'camera',
|
icon: 'camera',
|
||||||
onPress: this.takeVideo
|
onPress: this.takeVideo,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: I18n.t('Choose_from_library'),
|
title: I18n.t('Choose_from_library'),
|
||||||
icon: 'image',
|
icon: 'image',
|
||||||
onPress: this.chooseFromLibrary
|
onPress: this.chooseFromLibrary,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: I18n.t('Choose_file'),
|
title: I18n.t('Choose_file'),
|
||||||
icon: 'attach',
|
icon: 'attach',
|
||||||
onPress: this.chooseFile
|
onPress: this.chooseFile,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: I18n.t('Create_Discussion'),
|
title: I18n.t('Create_Discussion'),
|
||||||
icon: 'discussions',
|
icon: 'discussions',
|
||||||
onPress: this.createDiscussion
|
onPress: this.createDiscussion,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const libPickerLabels = {
|
const libPickerLabels = {
|
||||||
cropperChooseText: I18n.t('Choose'),
|
cropperChooseText: I18n.t('Choose'),
|
||||||
cropperCancelText: I18n.t('Cancel'),
|
cropperCancelText: I18n.t('Cancel'),
|
||||||
loadingLabelText: I18n.t('Processing')
|
loadingLabelText: I18n.t('Processing'),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.imagePickerConfig = {
|
this.imagePickerConfig = {
|
||||||
...imagePickerConfig,
|
...imagePickerConfig,
|
||||||
...libPickerLabels
|
...libPickerLabels,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.libraryPickerConfig = {
|
this.libraryPickerConfig = {
|
||||||
...libraryPickerConfig,
|
...libraryPickerConfig,
|
||||||
...libPickerLabels
|
...libPickerLabels,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.videoPickerConfig = {
|
this.videoPickerConfig = {
|
||||||
...videoPickerConfig,
|
...videoPickerConfig,
|
||||||
...libPickerLabels
|
...libPickerLabels,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,11 +317,11 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: any, nextState: any) {
|
shouldComponentUpdate(nextProps: any, nextState: any) {
|
||||||
const {
|
const {
|
||||||
showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow
|
showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
roomType, replying, editing, isFocused, message, theme
|
roomType, replying, editing, isFocused, message, theme,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (nextProps.theme !== theme) {
|
if (nextProps.theme !== theme) {
|
||||||
|
@ -388,7 +403,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
debouncedOnChangeText = debounce(async(text: any) => {
|
debouncedOnChangeText = debounce(async (text: any) => {
|
||||||
const { sharing } = this.props;
|
const { sharing } = this.props;
|
||||||
const isTextEmpty = text.length === 0;
|
const isTextEmpty = text.length === 0;
|
||||||
if (isTextEmpty) {
|
if (isTextEmpty) {
|
||||||
|
@ -424,15 +439,14 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.identifyMentionKeyword(command, MENTIONS_TRACKING_TYPE_COMMANDS);
|
return this.identifyMentionKeyword(command, MENTIONS_TRACKING_TYPE_COMMANDS);
|
||||||
} else if (channelMention) {
|
} if (channelMention) {
|
||||||
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_ROOMS);
|
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_ROOMS);
|
||||||
} else if (userMention) {
|
} if (userMention) {
|
||||||
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_USERS);
|
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_USERS);
|
||||||
} else if (emojiMention) {
|
} if (emojiMention) {
|
||||||
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_EMOJIS);
|
return this.identifyMentionKeyword(result, MENTIONS_TRACKING_TYPE_EMOJIS);
|
||||||
} else {
|
|
||||||
return this.stopTrackingMention();
|
|
||||||
}
|
}
|
||||||
|
return this.stopTrackingMention();
|
||||||
}, 100)
|
}, 100)
|
||||||
|
|
||||||
onKeyboardResigned = () => {
|
onKeyboardResigned = () => {
|
||||||
|
@ -451,7 +465,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
const result = msg.substr(0, cursor).replace(regexp, '');
|
const result = msg.substr(0, cursor).replace(regexp, '');
|
||||||
const mentionName = trackingType === MENTIONS_TRACKING_TYPE_EMOJIS
|
const mentionName = trackingType === MENTIONS_TRACKING_TYPE_EMOJIS
|
||||||
? `${ item.name || item }:`
|
? `${ item.name || item }:`
|
||||||
: (item.username || item.name || item.command);
|
: item.username || item.name || item.command;
|
||||||
const text = `${ result }${ mentionName } ${ msg.slice(cursor) }`;
|
const text = `${ result }${ mentionName } ${ msg.slice(cursor) }`;
|
||||||
|
|
||||||
if ((trackingType === MENTIONS_TRACKING_TYPE_COMMANDS) && item.providesPreview) {
|
if ((trackingType === MENTIONS_TRACKING_TYPE_COMMANDS) && item.providesPreview) {
|
||||||
|
@ -467,7 +481,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
onPressCommandPreview = (item: any) => {
|
onPressCommandPreview = (item: any) => {
|
||||||
const { command } = this.state;
|
const { command } = this.state;
|
||||||
const {
|
const {
|
||||||
rid, tmid, message: { id: messageTmid }, replyCancel
|
rid, tmid, message: { id: messageTmid }, replyCancel,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { text } = this;
|
const { text } = this;
|
||||||
const name = text.substr(0, text.indexOf(' ')).slice(1);
|
const name = text.substr(0, text.indexOf(' ')).slice(1);
|
||||||
|
@ -500,7 +514,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
this.setShowSend(true);
|
this.setShowSend(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPermalink = async(message: any) => {
|
getPermalink = async (message: any) => {
|
||||||
try {
|
try {
|
||||||
return await RocketChat.getPermalinkMessage(message);
|
return await RocketChat.getPermalinkMessage(message);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -519,18 +533,18 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUsers = debounce(async(keyword: any) => {
|
getUsers = debounce(async (keyword: any) => {
|
||||||
let res = await RocketChat.search({ text: keyword, filterRooms: false, filterUsers: true });
|
let res = await RocketChat.search({ text: keyword, filterRooms: false, filterUsers: true });
|
||||||
res = [...this.getFixedMentions(keyword), ...res];
|
res = [...this.getFixedMentions(keyword), ...res];
|
||||||
this.setState({ mentions: res });
|
this.setState({ mentions: res });
|
||||||
}, 300)
|
}, 300)
|
||||||
|
|
||||||
getRooms = debounce(async(keyword = '') => {
|
getRooms = debounce(async (keyword = '') => {
|
||||||
const res = await RocketChat.search({ text: keyword, filterRooms: true, filterUsers: false });
|
const res = await RocketChat.search({ text: keyword, filterRooms: true, filterUsers: false });
|
||||||
this.setState({ mentions: res });
|
this.setState({ mentions: res });
|
||||||
}, 300)
|
}, 300)
|
||||||
|
|
||||||
getEmojis = debounce(async(keyword: any) => {
|
getEmojis = debounce(async (keyword: any) => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const customEmojisCollection = db.get('custom_emojis');
|
const customEmojisCollection = db.get('custom_emojis');
|
||||||
const likeString = sanitizeLikeString(keyword);
|
const likeString = sanitizeLikeString(keyword);
|
||||||
|
@ -540,17 +554,17 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
let customEmojis = await customEmojisCollection.query(...whereClause).fetch();
|
let customEmojis = await customEmojisCollection.query(...whereClause).fetch();
|
||||||
customEmojis = customEmojis.slice(0, MENTIONS_COUNT_TO_DISPLAY);
|
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);
|
const mergedEmojis = [...customEmojis, ...filteredEmojis].slice(0, MENTIONS_COUNT_TO_DISPLAY);
|
||||||
this.setState({ mentions: mergedEmojis || [] });
|
this.setState({ mentions: mergedEmojis || [] });
|
||||||
}, 300)
|
}, 300)
|
||||||
|
|
||||||
getSlashCommands = debounce(async(keyword: any) => {
|
getSlashCommands = debounce(async (keyword: any) => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const commandsCollection = db.get('slash_commands');
|
const commandsCollection = db.get('slash_commands');
|
||||||
const likeString = sanitizeLikeString(keyword);
|
const likeString = sanitizeLikeString(keyword);
|
||||||
const commands = await commandsCollection.query(
|
const commands = await commandsCollection.query(
|
||||||
Q.where('id', Q.like(`${ likeString }%`))
|
Q.where('id', Q.like(`${ likeString }%`)),
|
||||||
).fetch();
|
).fetch();
|
||||||
this.setState({ mentions: commands || [] });
|
this.setState({ mentions: commands || [] });
|
||||||
}, 300)
|
}, 300)
|
||||||
|
@ -585,7 +599,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
setCommandPreview = async(command: any, name: string, params: any) => {
|
setCommandPreview = async (command: any, name: string, params: any) => {
|
||||||
const { rid } = this.props;
|
const { rid } = this.props;
|
||||||
try {
|
try {
|
||||||
const { success, preview } = await RocketChat.getCommandPreview(name, rid, params);
|
const { success, preview } = await RocketChat.getCommandPreview(name, rid, params);
|
||||||
|
@ -630,7 +644,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
takePhoto = async() => {
|
takePhoto = async () => {
|
||||||
logEvent(events.ROOM_BOX_ACTION_PHOTO);
|
logEvent(events.ROOM_BOX_ACTION_PHOTO);
|
||||||
try {
|
try {
|
||||||
const image = await ImagePicker.openCamera(this.imagePickerConfig);
|
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);
|
logEvent(events.ROOM_BOX_ACTION_VIDEO);
|
||||||
try {
|
try {
|
||||||
const video = await ImagePicker.openCamera(this.videoPickerConfig);
|
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);
|
logEvent(events.ROOM_BOX_ACTION_LIBRARY);
|
||||||
try {
|
try {
|
||||||
const attachments = await ImagePicker.openPicker(this.libraryPickerConfig);
|
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);
|
logEvent(events.ROOM_BOX_ACTION_FILE);
|
||||||
try {
|
try {
|
||||||
const res = await DocumentPicker.pick({
|
const res = await DocumentPicker.pick({
|
||||||
type: [DocumentPicker.types.allFiles]
|
type: [DocumentPicker.types.allFiles],
|
||||||
});
|
});
|
||||||
const file = {
|
const file = {
|
||||||
filename: res.name,
|
filename: res.name,
|
||||||
size: res.size,
|
size: res.size,
|
||||||
mime: res.type,
|
mime: res.type,
|
||||||
path: res.uri
|
path: res.uri,
|
||||||
};
|
};
|
||||||
if (this.canUploadFile(file)) {
|
if (this.canUploadFile(file)) {
|
||||||
this.openShareView([file]);
|
this.openShareView([file]);
|
||||||
|
@ -730,9 +744,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
this.setState({ recording });
|
this.setState({ recording });
|
||||||
}
|
}
|
||||||
|
|
||||||
finishAudioMessage = async(fileInfo: any) => {
|
finishAudioMessage = async (fileInfo: any) => {
|
||||||
const {
|
const {
|
||||||
rid, tmid, baseUrl: server, user
|
rid, tmid, baseUrl: server, user,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (fileInfo) {
|
if (fileInfo) {
|
||||||
|
@ -750,10 +764,10 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
this.setState({ showEmojiKeyboard: false });
|
this.setState({ showEmojiKeyboard: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = async() => {
|
submit = async () => {
|
||||||
const { tshow } = this.state;
|
const { tshow } = this.state;
|
||||||
const {
|
const {
|
||||||
onSubmit, rid: roomId, tmid, showSend, sharing
|
onSubmit, rid: roomId, tmid, showSend, sharing,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const message = this.text;
|
const message = this.text;
|
||||||
|
|
||||||
|
@ -773,7 +787,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
editing, replying, message: { id: messageTmid }, replyCancel
|
editing, replying, message: { id: messageTmid }, replyCancel,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// Slash command
|
// Slash command
|
||||||
|
@ -783,7 +797,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
const command = message.replace(/ .*/, '').slice(1);
|
const command = message.replace(/ .*/, '').slice(1);
|
||||||
const likeString = sanitizeLikeString(command);
|
const likeString = sanitizeLikeString(command);
|
||||||
const slashCommand = await commandsCollection.query(
|
const slashCommand = await commandsCollection.query(
|
||||||
Q.where('id', Q.like(`${ likeString }%`))
|
Q.where('id', Q.like(`${ likeString }%`)),
|
||||||
).fetch();
|
).fetch();
|
||||||
if (slashCommand.length > 0) {
|
if (slashCommand.length > 0) {
|
||||||
logEvent(events.COMMAND_RUN);
|
logEvent(events.COMMAND_RUN);
|
||||||
|
@ -811,7 +825,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
// Reply
|
// Reply
|
||||||
} else if (replying) {
|
} else if (replying) {
|
||||||
const {
|
const {
|
||||||
message: replyingMessage, threadsEnabled, replyWithMention
|
message: replyingMessage, threadsEnabled, replyWithMention,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
@ -856,7 +870,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
identifyMentionKeyword = (keyword: any, type: string) => {
|
identifyMentionKeyword = (keyword: any, type: string) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
showEmojiKeyboard: false,
|
showEmojiKeyboard: false,
|
||||||
trackingType: type
|
trackingType: type,
|
||||||
});
|
});
|
||||||
this.updateMentions(keyword, type);
|
this.updateMentions(keyword, type);
|
||||||
}
|
}
|
||||||
|
@ -870,7 +884,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
mentions: [],
|
mentions: [],
|
||||||
trackingType: '',
|
trackingType: '',
|
||||||
commandPreview: [],
|
commandPreview: [],
|
||||||
showCommandPreview: false
|
showCommandPreview: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,16 +926,16 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
|
||||||
renderContent = () => {
|
renderContent = () => {
|
||||||
const {
|
const {
|
||||||
recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview
|
recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const {
|
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;
|
} = this.props;
|
||||||
|
|
||||||
const isAndroidTablet = isTablet && isAndroid ? {
|
const isAndroidTablet = isTablet && isAndroid ? {
|
||||||
multiline: false,
|
multiline: false,
|
||||||
onSubmitEditing: this.submit,
|
onSubmitEditing: this.submit,
|
||||||
returnKeyType: 'send'
|
returnKeyType: 'send',
|
||||||
} : {};
|
} : {};
|
||||||
|
|
||||||
const recordAudio = showSend || !Message_AudioRecorderEnabled ? null : (
|
const recordAudio = showSend || !Message_AudioRecorderEnabled ? null : (
|
||||||
|
@ -935,7 +949,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
const commandsPreviewAndMentions = !recording ? (
|
const commandsPreviewAndMentions = !recording ? (
|
||||||
<>
|
<>
|
||||||
<CommandsPreview commandPreview={commandPreview} showCommandPreview={showCommandPreview} />
|
<CommandsPreview commandPreview={commandPreview} showCommandPreview={showCommandPreview} />
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<Mentions mentions={mentions} trackingType={trackingType} theme={theme} />
|
<Mentions mentions={mentions} trackingType={trackingType} theme={theme} />
|
||||||
</>
|
</>
|
||||||
) : null;
|
) : null;
|
||||||
|
@ -965,11 +979,11 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
isActionsEnabled={isActionsEnabled}
|
isActionsEnabled={isActionsEnabled}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={component => this.component = component}
|
ref={(component) => this.component = component}
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
style={[styles.textBoxInput, { color: themes[theme].bodyText }]}
|
style={[styles.textBoxInput, { color: themes[theme].bodyText }]}
|
||||||
returnKeyType='default'
|
returnKeyType='default'
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
keyboardType='twitter'
|
keyboardType='twitter'
|
||||||
blurOnSubmit={false}
|
blurOnSubmit={false}
|
||||||
placeholder={I18n.t('New_Message')}
|
placeholder={I18n.t('New_Message')}
|
||||||
|
@ -1002,7 +1016,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
style={[
|
style={[
|
||||||
styles.textArea,
|
styles.textArea,
|
||||||
{ backgroundColor: themes[theme].messageboxBackground },
|
{ backgroundColor: themes[theme].messageboxBackground },
|
||||||
!recording && editing && { backgroundColor: themes[theme].chatComponentBackground }
|
!recording && editing && { backgroundColor: themes[theme].chatComponentBackground },
|
||||||
]}
|
]}
|
||||||
testID='messagebox'
|
testID='messagebox'
|
||||||
>
|
>
|
||||||
|
@ -1020,7 +1034,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
console.count(`${ this.constructor.name }.render calls`);
|
console.count(`${ this.constructor.name }.render calls`);
|
||||||
const { showEmojiKeyboard } = this.state;
|
const { showEmojiKeyboard } = this.state;
|
||||||
const {
|
const {
|
||||||
user, baseUrl, theme, iOSScrollBehavior
|
user, baseUrl, theme, iOSScrollBehavior,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<MessageboxContext.Provider
|
<MessageboxContext.Provider
|
||||||
|
@ -1028,7 +1042,7 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
user,
|
user,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
onPressMention: this.onPressMention,
|
onPressMention: this.onPressMention,
|
||||||
onPressCommandPreview: this.onPressCommandPreview
|
onPressCommandPreview: this.onPressCommandPreview,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<KeyboardAccessoryView
|
<KeyboardAccessoryView
|
||||||
|
@ -1056,11 +1070,11 @@ const mapStateToProps = (state: any) => ({
|
||||||
user: getUserSelector(state),
|
user: getUserSelector(state),
|
||||||
FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList,
|
FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList,
|
||||||
FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize,
|
FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize,
|
||||||
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled
|
Message_AudioRecorderEnabled: state.settings.Message_AudioRecorderEnabled,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dispatchToProps = ({
|
const dispatchToProps = {
|
||||||
typing: (rid: any, status: any) => userTypingAction(rid, status)
|
typing: (rid: any, status: any) => userTypingAction(rid, status),
|
||||||
});
|
};
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox));
|
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({
|
export default StyleSheet.create({
|
||||||
composer: {
|
composer: {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
borderTopWidth: 1
|
borderTopWidth: 1,
|
||||||
},
|
},
|
||||||
textArea: {
|
textArea: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexGrow: 0
|
flexGrow: 0,
|
||||||
},
|
},
|
||||||
textBoxInput: {
|
textBoxInput: {
|
||||||
textAlignVertical: 'center',
|
textAlignVertical: 'center',
|
||||||
|
@ -28,48 +28,48 @@ export default StyleSheet.create({
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
letterSpacing: 0,
|
letterSpacing: 0,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
actionButton: {
|
actionButton: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 48
|
height: 48,
|
||||||
},
|
},
|
||||||
mentionList: {
|
mentionList: {
|
||||||
maxHeight: MENTION_HEIGHT * 4
|
maxHeight: MENTION_HEIGHT * 4,
|
||||||
},
|
},
|
||||||
mentionItem: {
|
mentionItem: {
|
||||||
height: MENTION_HEIGHT,
|
height: MENTION_HEIGHT,
|
||||||
borderTopWidth: StyleSheet.hairlineWidth,
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingHorizontal: 5
|
paddingHorizontal: 5,
|
||||||
},
|
},
|
||||||
mentionItemCustomEmoji: {
|
mentionItemCustomEmoji: {
|
||||||
margin: 8,
|
margin: 8,
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30
|
height: 30,
|
||||||
},
|
},
|
||||||
mentionItemEmoji: {
|
mentionItemEmoji: {
|
||||||
width: 46,
|
width: 46,
|
||||||
height: 36,
|
height: 36,
|
||||||
fontSize: isIOS ? 30 : 25,
|
fontSize: isIOS ? 30 : 25,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
fixedMentionAvatar: {
|
fixedMentionAvatar: {
|
||||||
width: 46,
|
width: 46,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textBold,
|
...sharedStyles.textBold,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
mentionText: {
|
mentionText: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
emojiKeyboardContainer: {
|
emojiKeyboardContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
borderTopWidth: StyleSheet.hairlineWidth
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
},
|
},
|
||||||
slash: {
|
slash: {
|
||||||
height: 30,
|
height: 30,
|
||||||
|
@ -77,48 +77,48 @@ export default StyleSheet.create({
|
||||||
padding: 5,
|
padding: 5,
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
marginHorizontal: 10,
|
marginHorizontal: 10,
|
||||||
borderRadius: 2
|
borderRadius: 2,
|
||||||
},
|
},
|
||||||
commandPreviewImage: {
|
commandPreviewImage: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
margin: 3,
|
margin: 3,
|
||||||
width: 120,
|
width: 120,
|
||||||
height: 80,
|
height: 80,
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
commandPreview: {
|
commandPreview: {
|
||||||
height: 100,
|
height: 100,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
margin: 8
|
margin: 8,
|
||||||
},
|
},
|
||||||
scrollViewMention: {
|
scrollViewMention: {
|
||||||
maxHeight: SCROLLVIEW_MENTION_HEIGHT
|
maxHeight: SCROLLVIEW_MENTION_HEIGHT,
|
||||||
},
|
},
|
||||||
recordingContent: {
|
recordingContent: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between',
|
||||||
},
|
},
|
||||||
recordingCancelText: {
|
recordingCancelText: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
buttonsWhitespace: {
|
buttonsWhitespace: {
|
||||||
width: 15
|
width: 15,
|
||||||
},
|
},
|
||||||
sendToChannelButton: {
|
sendToChannelButton: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingVertical: 8,
|
paddingVertical: 8,
|
||||||
paddingHorizontal: 18
|
paddingHorizontal: 18,
|
||||||
},
|
},
|
||||||
sendToChannelText: {
|
sendToChannelText: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
marginLeft: 4,
|
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 RocketChat from '../lib/rocketchat';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
|
@ -10,11 +10,11 @@ import log from '../utils/log';
|
||||||
const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
||||||
const { showActionSheet }: any = useActionSheet();
|
const { showActionSheet }: any = useActionSheet();
|
||||||
|
|
||||||
const handleResend = protectedFunction(async(message: any) => {
|
const handleResend = protectedFunction(async (message: any) => {
|
||||||
await RocketChat.resendMessage(message, tmid);
|
await RocketChat.resendMessage(message, tmid);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDelete = async(message: any) => {
|
const handleDelete = async (message: any) => {
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const deleteBatch: any = [];
|
const deleteBatch: any = [];
|
||||||
|
@ -41,7 +41,7 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
||||||
msg.prepareUpdate((m: any) => {
|
msg.prepareUpdate((m: any) => {
|
||||||
m.tcount = null;
|
m.tcount = null;
|
||||||
m.tlm = null;
|
m.tlm = null;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -55,14 +55,14 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
||||||
deleteBatch.push(
|
deleteBatch.push(
|
||||||
msg.prepareUpdate((m: any) => {
|
msg.prepareUpdate((m: any) => {
|
||||||
m.tcount -= 1;
|
m.tcount -= 1;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Do nothing: message not found
|
// Do nothing: message not found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await db.action(async() => {
|
await db.action(async () => {
|
||||||
await db.batch(...deleteBatch);
|
await db.batch(...deleteBatch);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -76,21 +76,21 @@ const MessageErrorActions = forwardRef(({ tmid }: any, ref): any => {
|
||||||
{
|
{
|
||||||
title: I18n.t('Resend'),
|
title: I18n.t('Resend'),
|
||||||
icon: 'send',
|
icon: 'send',
|
||||||
onPress: () => handleResend(message)
|
onPress: () => handleResend(message),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: I18n.t('Delete'),
|
title: I18n.t('Delete'),
|
||||||
icon: 'delete',
|
icon: 'delete',
|
||||||
danger: true,
|
danger: true,
|
||||||
onPress: () => handleDelete(message)
|
onPress: () => handleDelete(message),
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
hasCancel: true
|
hasCancel: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
showMessageErrorActions
|
showMessageErrorActions,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet, Text } from 'react-native';
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import sharedStyles from '../views/Styles';
|
import sharedStyles from '../views/Styles';
|
||||||
|
@ -9,18 +9,18 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginVertical: 24
|
marginVertical: 24,
|
||||||
},
|
},
|
||||||
line: {
|
line: {
|
||||||
height: 1,
|
height: 1,
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginLeft: 14,
|
marginLeft: 14,
|
||||||
marginRight: 14,
|
marginRight: 14,
|
||||||
...sharedStyles.textMedium
|
...sharedStyles.textMedium,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IOrSeparator {
|
interface IOrSeparator {
|
||||||
|
|
|
@ -11,7 +11,7 @@ interface IPasscodeButton {
|
||||||
icon: string;
|
icon: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onPress({}?): void;
|
onPress: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button = React.memo(({ text, disabled, theme, onPress, icon }: Partial<IPasscodeButton>) => {
|
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) => (
|
const Dots = React.memo(({ passcode, theme, length }: IPasscodeDots) => (
|
||||||
<View style={styles.dotsContainer}>
|
<View style={styles.dotsContainer}>
|
||||||
{range(length).map((val) => {
|
{range(length).map((val) => {
|
||||||
const lengthSup = (passcode.length >= val + 1);
|
const lengthSup = passcode.length >= val + 1;
|
||||||
const height = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
const height = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
||||||
const width = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
const width = lengthSup ? SIZE_FULL : SIZE_EMPTY;
|
||||||
let backgroundColor = '';
|
let backgroundColor = '';
|
||||||
|
@ -38,7 +38,7 @@ const Dots = React.memo(({ passcode, theme, length }: IPasscodeDots) => (
|
||||||
borderRadius,
|
borderRadius,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
marginRight,
|
marginRight,
|
||||||
marginLeft
|
marginLeft,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Grid } from 'react-native-easy-grid';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import { resetAttempts } from '../../../utils/localAuthentication';
|
import { resetAttempts } from '../../../utils/localAuthentication';
|
||||||
import { TYPE } from '../constants';
|
import { TYPE } from '../constants';
|
||||||
import { getLockedUntil, getDiff } from '../utils';
|
import { getDiff, getLockedUntil } from '../utils';
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../../i18n';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import Title from './Title';
|
import Title from './Title';
|
||||||
|
@ -52,7 +52,7 @@ const Timer = React.memo(({ time, theme, setStatus }: IPasscodeTimer) => {
|
||||||
const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
|
const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
|
||||||
const [lockedUntil, setLockedUntil] = useState<any>(null);
|
const [lockedUntil, setLockedUntil] = useState<any>(null);
|
||||||
|
|
||||||
const readItemFromStorage = async() => {
|
const readItemFromStorage = async () => {
|
||||||
const l = await getLockedUntil();
|
const l = await getLockedUntil();
|
||||||
setLockedUntil(l);
|
setLockedUntil(l);
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,7 @@ const Locked = React.memo(({ theme, setStatus }: IPasscodeLocked) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
//TODO - verify if this 'r' it's correct
|
// TODO - verify if this 'r' it's correct
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
<Grid style={[styles.grid, { backgroundColor: themes[theme].passcodeBackground }]} r>
|
<Grid style={[styles.grid, { backgroundColor: themes[theme].passcodeBackground }]} r>
|
||||||
<LockIcon theme={theme} />
|
<LockIcon theme={theme} />
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { Row } from 'react-native-easy-grid';
|
import { Row } from 'react-native-easy-grid';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { Row } from 'react-native-easy-grid';
|
import { Row } from 'react-native-easy-grid';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState, forwardRef, useImperativeHandle, useRef } from 'react';
|
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
||||||
import { Col, Row, Grid } from 'react-native-easy-grid';
|
import { Col, Grid, Row } from 'react-native-easy-grid';
|
||||||
import range from 'lodash/range';
|
import range from 'lodash/range';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
import * as Haptics from 'expo-haptics';
|
import * as Haptics from 'expo-haptics';
|
||||||
|
@ -27,7 +27,7 @@ interface IPasscodeBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Base = forwardRef(({
|
const Base = forwardRef(({
|
||||||
theme, type, onEndProcess, previousPasscode, title, subtitle, onError, showBiometry, onBiometryPress
|
theme, type, onEndProcess, previousPasscode, title, subtitle, onError, showBiometry, onBiometryPress,
|
||||||
}: IPasscodeBase, ref) => {
|
}: IPasscodeBase, ref) => {
|
||||||
const rootRef = useRef<any>();
|
const rootRef = useRef<any>();
|
||||||
const dotsRef = useRef<any>();
|
const dotsRef = useRef<any>();
|
||||||
|
@ -78,7 +78,7 @@ const Base = forwardRef(({
|
||||||
});
|
});
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
wrongPasscode, animate, clearPasscode
|
wrongPasscode, animate, clearPasscode,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,22 +4,22 @@ import sharedStyles from '../../../views/Styles';
|
||||||
|
|
||||||
export default StyleSheet.create({
|
export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
titleView: {
|
titleView: {
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
subtitleView: {
|
subtitleView: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
height: 32
|
height: 32,
|
||||||
},
|
},
|
||||||
row: {
|
row: {
|
||||||
flex: 0,
|
flex: 0,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
buttonRow: {
|
buttonRow: {
|
||||||
height: 102
|
height: 102,
|
||||||
},
|
},
|
||||||
colButton: {
|
colButton: {
|
||||||
flex: 0,
|
flex: 0,
|
||||||
|
@ -27,44 +27,44 @@ export default StyleSheet.create({
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
width: 78,
|
width: 78,
|
||||||
height: 78
|
height: 78,
|
||||||
},
|
},
|
||||||
buttonText: {
|
buttonText: {
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
buttonView: {
|
buttonView: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
width: 78,
|
width: 78,
|
||||||
height: 78,
|
height: 78,
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
textTitle: {
|
textTitle: {
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
textSubtitle: {
|
textSubtitle: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textMedium
|
...sharedStyles.textMedium,
|
||||||
},
|
},
|
||||||
dotsContainer: {
|
dotsContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginTop: 24,
|
marginTop: 24,
|
||||||
marginBottom: 40
|
marginBottom: 40,
|
||||||
},
|
},
|
||||||
dotsView: {
|
dotsView: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
height: 16
|
height: 16,
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
flexDirection: 'column'
|
flexDirection: 'column',
|
||||||
},
|
},
|
||||||
iconView: {
|
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 * as Haptics from 'expo-haptics';
|
||||||
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ import Base from './Base';
|
||||||
import Locked from './Base/Locked';
|
import Locked from './Base/Locked';
|
||||||
import { TYPE } from './constants';
|
import { TYPE } from './constants';
|
||||||
import {
|
import {
|
||||||
ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, PASSCODE_KEY, MAX_ATTEMPTS
|
ATTEMPTS_KEY, LOCKED_OUT_TIMER_KEY, MAX_ATTEMPTS, PASSCODE_KEY,
|
||||||
} from '../../constants/localAuthentication';
|
} from '../../constants/localAuthentication';
|
||||||
import { resetAttempts, biometryAuth } from '../../utils/localAuthentication';
|
import { biometryAuth, resetAttempts } from '../../utils/localAuthentication';
|
||||||
import { getLockedUntil, getDiff } from './utils';
|
import { getDiff, getLockedUntil } from './utils';
|
||||||
import UserPreferences from '../../lib/userPreferences';
|
import UserPreferences from '../../lib/userPreferences';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
|
||||||
const { getItem: getAttempts, setItem: setAttempts } = useAsyncStorage(ATTEMPTS_KEY);
|
const { getItem: getAttempts, setItem: setAttempts } = useAsyncStorage(ATTEMPTS_KEY);
|
||||||
const { setItem: setLockedUntil } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
const { setItem: setLockedUntil } = useAsyncStorage(LOCKED_OUT_TIMER_KEY);
|
||||||
|
|
||||||
const fetchPasscode = async() => {
|
const fetchPasscode = async () => {
|
||||||
const p: any = await UserPreferences.getStringAsync(PASSCODE_KEY);
|
const p: any = await UserPreferences.getStringAsync(PASSCODE_KEY);
|
||||||
setPasscode(p);
|
setPasscode(p);
|
||||||
};
|
};
|
||||||
|
|
||||||
const biometry = async() => {
|
const biometry = async () => {
|
||||||
if (hasBiometry && status === TYPE.ENTER) {
|
if (hasBiometry && status === TYPE.ENTER) {
|
||||||
const result = await biometryAuth();
|
const result = await biometryAuth();
|
||||||
if (result?.success) {
|
if (result?.success) {
|
||||||
|
@ -45,7 +45,7 @@ const PasscodeEnter = ({ theme, hasBiometry, finishProcess }: IPasscodePasscodeE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const readStorage = async() => {
|
const readStorage = async () => {
|
||||||
lockedUntil = await getLockedUntil();
|
lockedUntil = await getLockedUntil();
|
||||||
if (lockedUntil) {
|
if (lockedUntil) {
|
||||||
const diff = getDiff(lockedUntil);
|
const diff = getDiff(lockedUntil);
|
||||||
|
|
|
@ -2,5 +2,5 @@ export const TYPE: any = {
|
||||||
CHOOSE: 'choose',
|
CHOOSE: 'choose',
|
||||||
CONFIRM: 'confirm',
|
CONFIRM: 'confirm',
|
||||||
ENTER: 'enter',
|
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';
|
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);
|
const t: any = await AsyncStorage.getItem(LOCKED_OUT_TIMER_KEY);
|
||||||
if (t) {
|
if (t) {
|
||||||
return moment(t).add(TIME_TO_LOCK);
|
return moment(t).add(TIME_TO_LOCK);
|
||||||
|
@ -11,4 +11,4 @@ export const getLockedUntil = async() => {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
// @ts-ignore
|
// @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 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 Modal from 'react-native-modal';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
|
@ -13,48 +13,48 @@ import SafeAreaView from './SafeAreaView';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
safeArea: {
|
safeArea: {
|
||||||
backgroundColor: 'transparent'
|
backgroundColor: 'transparent',
|
||||||
},
|
},
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingVertical: 10
|
paddingVertical: 10,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
...sharedStyles.textSemibold,
|
...sharedStyles.textSemibold,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
reactCount: {
|
reactCount: {
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
peopleReacted: {
|
peopleReacted: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textMedium
|
...sharedStyles.textMedium,
|
||||||
},
|
},
|
||||||
peopleItemContainer: {
|
peopleItemContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
emojiContainer: {
|
emojiContainer: {
|
||||||
width: 50,
|
width: 50,
|
||||||
height: 50,
|
height: 50,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
itemContainer: {
|
itemContainer: {
|
||||||
height: 50,
|
height: 50,
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
listContainer: {
|
listContainer: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
closeButton: {
|
closeButton: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 10
|
top: 10,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const standardEmojiStyle = { fontSize: 20 };
|
const standardEmojiStyle = { fontSize: 20 };
|
||||||
const customEmojiStyle = { width: 20, height: 20 };
|
const customEmojiStyle = { width: 20, height: 20 };
|
||||||
|
@ -132,7 +132,7 @@ const ModalContent = React.memo(({ message, onClose, ...props }: IModalContent)
|
||||||
style={styles.listContainer}
|
style={styles.listContainer}
|
||||||
data={message.reactions}
|
data={message.reactions}
|
||||||
renderItem={({ item }) => <Item item={item} {...props} />}
|
renderItem={({ item }) => <Item item={item} {...props} />}
|
||||||
keyExtractor={item => item.emoji}
|
keyExtractor={(item) => item.emoji}
|
||||||
/>
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
@ -149,7 +149,7 @@ const ReactionsModal = React.memo(({ isVisible, onClose, theme, ...props }: IRea
|
||||||
onSwipeComplete={onClose}
|
onSwipeComplete={onClose}
|
||||||
swipeDirection={['up', 'left', 'right', 'down']}
|
swipeDirection={['up', 'left', 'right', 'down']}
|
||||||
>
|
>
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<ModalContent onClose={onClose} theme={theme} {...props} />
|
<ModalContent onClose={onClose} theme={theme} {...props} />
|
||||||
</Modal>
|
</Modal>
|
||||||
), (prevProps, nextProps) => prevProps.isVisible === nextProps.isVisible && prevProps.theme === nextProps.theme);
|
), (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 */
|
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions, react/prop-types, react/destructuring-assignment */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Dimensions } from 'react-native';
|
import { Dimensions, View } from 'react-native';
|
||||||
import { storiesOf } from '@storybook/react-native';
|
import { storiesOf } from '@storybook/react-native';
|
||||||
|
|
||||||
import RoomHeaderComponent from './RoomHeader';
|
|
||||||
import Header from '../Header';
|
import Header from '../Header';
|
||||||
import { longText } from '../../../storybook/utils';
|
import { longText } from '../../../storybook/utils';
|
||||||
import { ThemeContext } from '../../theme';
|
import { ThemeContext } from '../../theme';
|
||||||
|
import RoomHeaderComponent from './RoomHeader';
|
||||||
|
|
||||||
const stories = storiesOf('RoomHeader', module);
|
const stories = storiesOf('RoomHeader', module);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useCallback } from 'react';
|
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 I18n from '../../i18n';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
|
@ -9,7 +9,7 @@ import RoomTypeIcon from '../RoomTypeIcon';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
|
|
||||||
const HIT_SLOP = {
|
const HIT_SLOP = {
|
||||||
top: 5, right: 5, bottom: 5, left: 5
|
top: 5, right: 5, bottom: 5, left: 5,
|
||||||
};
|
};
|
||||||
const TITLE_SIZE = 16;
|
const TITLE_SIZE = 16;
|
||||||
const SUBTITLE_SIZE = 12;
|
const SUBTITLE_SIZE = 12;
|
||||||
|
@ -19,23 +19,23 @@ const getSubTitleSize = (scale: number) => SUBTITLE_SIZE * scale;
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
typingUsers: {
|
typingUsers: {
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
type TRoomHeaderSubTitle = {
|
type TRoomHeaderSubTitle = {
|
||||||
|
@ -141,7 +141,7 @@ const HeaderTitle = React.memo(({ title, tmid, prid, scale, theme, testID }: TRo
|
||||||
});
|
});
|
||||||
|
|
||||||
const Header = React.memo(({
|
const Header = React.memo(({
|
||||||
title, subtitle, parentTitle, type, status, 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) => {
|
}: IRoomHeader) => {
|
||||||
const portrait = height > width;
|
const portrait = height > width;
|
||||||
let scale = 1;
|
let scale = 1;
|
||||||
|
|
|
@ -29,10 +29,9 @@ interface IRoomHeaderContainerProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: IRoomHeaderContainerProps) {
|
shouldComponentUpdate(nextProps: IRoomHeaderContainerProps) {
|
||||||
const {
|
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;
|
} = this.props;
|
||||||
if (nextProps.type !== type) {
|
if (nextProps.type !== type) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -93,7 +92,7 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
|
||||||
height,
|
height,
|
||||||
parentTitle,
|
parentTitle,
|
||||||
isGroupChat,
|
isGroupChat,
|
||||||
testID
|
testID,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let subtitle;
|
let subtitle;
|
||||||
|
@ -147,7 +146,7 @@ const mapStateToProps = (state: any, ownProps: any) => {
|
||||||
connected: state.meteor.connected,
|
connected: state.meteor.connected,
|
||||||
usersTyping: state.usersTyping,
|
usersTyping: state.usersTyping,
|
||||||
status,
|
status,
|
||||||
statusText
|
statusText,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
import { STATUS_COLORS, themes } from '../constants/colors';
|
import { STATUS_COLORS, themes } from '../constants/colors';
|
||||||
import Status from './Status/Status';
|
import Status from './Status/Status';
|
||||||
|
@ -7,8 +8,8 @@ import { withTheme } from '../theme';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
icon: {
|
icon: {
|
||||||
marginRight: 4
|
marginRight: 4,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IRoomTypeIcon {
|
interface IRoomTypeIcon {
|
||||||
|
@ -22,7 +23,7 @@ interface IRoomTypeIcon {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RoomTypeIcon = React.memo(({
|
const RoomTypeIcon = React.memo(({
|
||||||
type, isGroupChat, status, style, theme, teamMain, size = 16
|
type, isGroupChat, status, style, theme, teamMain, size = 16,
|
||||||
}: IRoomTypeIcon) => {
|
}: IRoomTypeIcon) => {
|
||||||
if (!type) {
|
if (!type) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -32,7 +33,7 @@ const RoomTypeIcon = React.memo(({
|
||||||
const iconStyle = [
|
const iconStyle = [
|
||||||
styles.icon,
|
styles.icon,
|
||||||
{ color },
|
{ color },
|
||||||
style
|
style,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (type === 'd' && !isGroupChat) {
|
if (type === 'd' && !isGroupChat) {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
import { SafeAreaView as SafeAreaContext } from 'react-native-safe-area-context';
|
import { SafeAreaView as SafeAreaContext } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
view: {
|
view: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ISafeAreaView {
|
interface ISafeAreaView {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import TextInput from '../presentation/TextInput';
|
import TextInput from '../presentation/TextInput';
|
||||||
|
@ -14,7 +14,7 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
searchBox: {
|
searchBox: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -25,7 +25,7 @@ const styles = StyleSheet.create({
|
||||||
margin: 16,
|
margin: 16,
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
paddingHorizontal: 10,
|
paddingHorizontal: 10,
|
||||||
flex: 1
|
flex: 1,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -33,15 +33,15 @@ const styles = StyleSheet.create({
|
||||||
marginLeft: 8,
|
marginLeft: 8,
|
||||||
paddingTop: 0,
|
paddingTop: 0,
|
||||||
paddingBottom: 0,
|
paddingBottom: 0,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
marginRight: 15
|
marginRight: 15,
|
||||||
},
|
},
|
||||||
cancelText: {
|
cancelText: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
fontSize: 17
|
fontSize: 17,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ISearchBox {
|
interface ISearchBox {
|
||||||
|
@ -66,14 +66,14 @@ const SearchBox = ({
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.container,
|
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 }]}>
|
<View style={[styles.searchBox, { backgroundColor: themes[theme].searchboxBackground }]}>
|
||||||
<CustomIcon name='search' size={14} color={themes[theme].auxiliaryText} />
|
<CustomIcon name='search' size={14} color={themes[theme].auxiliaryText} />
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
autoCapitalize='none'
|
autoCapitalize='none'
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
blurOnSubmit
|
blurOnSubmit
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import { STATUS_COLORS } from '../../constants/colors';
|
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 isNameValid = CustomIcon.hasIcon(name);
|
||||||
const iconName = isNameValid ? name : 'status-offline';
|
const iconName = isNameValid ? name : 'status-offline';
|
||||||
const calculatedStyle = [{
|
const calculatedStyle = [{
|
||||||
width: size, height: size, textAlignVertical: 'center'
|
width: size, height: size, textAlignVertical: 'center',
|
||||||
}, style];
|
}, style];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,7 +12,7 @@ interface IStatusContainer {
|
||||||
const StatusContainer = memo(({ style, size = 32, status }: IStatusContainer) => <Status size={size} style={style} status={status} />);
|
const StatusContainer = memo(({ style, size = 32, status }: IStatusContainer) => <Status size={size} style={style} status={status} />);
|
||||||
|
|
||||||
const mapStateToProps = (state: any, ownProps: any) => ({
|
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);
|
export default connect(mapStateToProps)(StatusContainer);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 { BorderlessButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
import sharedStyles from '../views/Styles';
|
import sharedStyles from '../views/Styles';
|
||||||
|
@ -11,15 +11,15 @@ import ActivityIndicator from './ActivityIndicator';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
error: {
|
error: {
|
||||||
...sharedStyles.textAlignCenter,
|
...sharedStyles.textAlignCenter,
|
||||||
paddingTop: 5
|
paddingTop: 5,
|
||||||
},
|
},
|
||||||
inputContainer: {
|
inputContainer: {
|
||||||
marginBottom: 10
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
|
@ -27,27 +27,27 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
borderWidth: StyleSheet.hairlineWidth,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderRadius: 2
|
borderRadius: 2,
|
||||||
},
|
},
|
||||||
inputIconLeft: {
|
inputIconLeft: {
|
||||||
paddingLeft: 45
|
paddingLeft: 45,
|
||||||
},
|
},
|
||||||
inputIconRight: {
|
inputIconRight: {
|
||||||
paddingRight: 45
|
paddingRight: 45,
|
||||||
},
|
},
|
||||||
wrap: {
|
wrap: {
|
||||||
position: 'relative'
|
position: 'relative',
|
||||||
},
|
},
|
||||||
iconContainer: {
|
iconContainer: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 14
|
top: 14,
|
||||||
},
|
},
|
||||||
iconLeft: {
|
iconLeft: {
|
||||||
left: 15
|
left: 15,
|
||||||
},
|
},
|
||||||
iconRight: {
|
iconRight: {
|
||||||
right: 15
|
right: 15,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IRCTextInputProps {
|
interface IRCTextInputProps {
|
||||||
|
@ -71,14 +71,13 @@ interface IRCTextInputProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, any> {
|
export default class RCTextInput extends React.PureComponent<IRCTextInputProps, any> {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
error: {},
|
error: {},
|
||||||
theme: 'light'
|
theme: 'light',
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
showPassword: false
|
showPassword: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
get iconLeft() {
|
get iconLeft() {
|
||||||
|
@ -147,7 +146,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
|
||||||
style={[
|
style={[
|
||||||
styles.label,
|
styles.label,
|
||||||
{ color: themes[theme].titleText },
|
{ color: themes[theme].titleText },
|
||||||
error.error && { color: dangerColor }
|
error.error && { color: dangerColor },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
@ -155,7 +154,7 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
|
||||||
) : null}
|
) : null}
|
||||||
<View style={styles.wrap}>
|
<View style={styles.wrap}>
|
||||||
<TextInput
|
<TextInput
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
style={[
|
style={[
|
||||||
styles.input,
|
styles.input,
|
||||||
iconLeft && styles.inputIconLeft,
|
iconLeft && styles.inputIconLeft,
|
||||||
|
@ -163,16 +162,16 @@ export default class RCTextInput extends React.PureComponent<IRCTextInputProps,
|
||||||
{
|
{
|
||||||
backgroundColor: themes[theme].backgroundColor,
|
backgroundColor: themes[theme].backgroundColor,
|
||||||
borderColor: themes[theme].separatorColor,
|
borderColor: themes[theme].separatorColor,
|
||||||
color: themes[theme].titleText
|
color: themes[theme].titleText,
|
||||||
},
|
},
|
||||||
error.error && {
|
error.error && {
|
||||||
color: dangerColor,
|
color: dangerColor,
|
||||||
borderColor: dangerColor
|
borderColor: dangerColor,
|
||||||
},
|
},
|
||||||
inputStyle
|
inputStyle,
|
||||||
]}
|
]}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
autoCapitalize='none'
|
autoCapitalize='none'
|
||||||
underlineColorAndroid='transparent'
|
underlineColorAndroid='transparent'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
@ -11,32 +11,32 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
detailsContainer: {
|
detailsContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
detailContainer: {
|
detailContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginRight: 8
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
detailText: {
|
detailText: {
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
marginLeft: 2,
|
marginLeft: 2,
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
},
|
},
|
||||||
badgeContainer: {
|
badgeContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
badge: {
|
badge: {
|
||||||
width: 8,
|
width: 8,
|
||||||
height: 8,
|
height: 8,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
marginRight: 8
|
marginRight: 8,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IThreadDetails {
|
interface IThreadDetails {
|
||||||
|
@ -60,7 +60,7 @@ const ThreadDetails = ({
|
||||||
badgeColor,
|
badgeColor,
|
||||||
toggleFollowThread,
|
toggleFollowThread,
|
||||||
style,
|
style,
|
||||||
theme
|
theme,
|
||||||
}: IThreadDetails) => {
|
}: IThreadDetails) => {
|
||||||
let { tcount } = item;
|
let { tcount } = item;
|
||||||
if (tcount >= 1000) {
|
if (tcount >= 1000) {
|
||||||
|
|
|
@ -10,13 +10,13 @@ import { withTheme } from '../theme';
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
toast: {
|
toast: {
|
||||||
maxWidth: 300,
|
maxWidth: 300,
|
||||||
padding: 10
|
padding: 10,
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const LISTENER = 'Toast';
|
export const LISTENER = 'Toast';
|
||||||
|
@ -27,6 +27,7 @@ interface IToastProps {
|
||||||
|
|
||||||
class Toast extends React.Component<IToastProps, any> {
|
class Toast extends React.Component<IToastProps, any> {
|
||||||
private listener: any;
|
private listener: any;
|
||||||
|
|
||||||
private toast: any;
|
private toast: any;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
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 isEmpty from 'lodash/isEmpty';
|
||||||
import { sha256 } from 'js-sha256';
|
import { sha256 } from 'js-sha256';
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
|
@ -26,18 +26,18 @@ interface ITwoFactor {
|
||||||
const methods: any = {
|
const methods: any = {
|
||||||
totp: {
|
totp: {
|
||||||
text: 'Open_your_authentication_app_and_enter_the_code',
|
text: 'Open_your_authentication_app_and_enter_the_code',
|
||||||
keyboardType: 'numeric'
|
keyboardType: 'numeric',
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
text: 'Verify_your_email_for_the_code_we_sent',
|
text: 'Verify_your_email_for_the_code_we_sent',
|
||||||
keyboardType: 'numeric'
|
keyboardType: 'numeric',
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
title: 'Please_enter_your_password',
|
title: 'Please_enter_your_password',
|
||||||
text: 'For_your_security_you_must_enter_your_current_password_to_continue',
|
text: 'For_your_security_you_must_enter_your_current_password_to_continue',
|
||||||
secureTextEntry: true,
|
secureTextEntry: true,
|
||||||
keyboardType: 'default'
|
keyboardType: 'default',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
||||||
|
@ -90,7 +90,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
||||||
const color = themes[theme].titleText;
|
const color = themes[theme].titleText;
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
transparent
|
transparent
|
||||||
avoidKeyboard
|
avoidKeyboard
|
||||||
useNativeDriver
|
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>
|
<Text style={[styles.title, { color }]}>{I18n.t(method?.title || 'Two_Factor_Authentication')}</Text>
|
||||||
{method?.text ? <Text style={[styles.subtitle, { color }]}>{I18n.t(method.text)}</Text> : null}
|
{method?.text ? <Text style={[styles.subtitle, { color }]}>{I18n.t(method.text)}</Text> : null}
|
||||||
<TextInput
|
<TextInput
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
value={code}
|
value={code}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
inputRef={(e: any) => InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}
|
inputRef={(e: any) => InteractionManager.runAfterInteractions(() => e?.getNativeRef()?.focus())}
|
||||||
|
@ -141,7 +141,7 @@ const TwoFactor = React.memo(({ theme, isMasterDetail }: ITwoFactor) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(TwoFactor));
|
export default connect(mapStateToProps)(withTheme(TwoFactor));
|
||||||
|
|
|
@ -6,40 +6,40 @@ export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center'
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
padding: 16,
|
padding: 16,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
paddingBottom: 8,
|
paddingBottom: 8,
|
||||||
...sharedStyles.textBold,
|
...sharedStyles.textBold,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
paddingBottom: 8,
|
paddingBottom: 8,
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
sendEmail: {
|
sendEmail: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
paddingBottom: 24,
|
paddingBottom: 24,
|
||||||
paddingTop: 8,
|
paddingTop: 8,
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
marginBottom: 0
|
marginBottom: 0,
|
||||||
},
|
},
|
||||||
buttonContainer: {
|
buttonContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between',
|
||||||
},
|
},
|
||||||
tablet: {
|
tablet: {
|
||||||
height: undefined
|
height: undefined,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const Actions = ({ blockId, appId, elements, parser, theme }: IActions) =
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<Elements />
|
<Elements />
|
||||||
{showMoreVisible && (<Button theme={theme} title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />)}
|
{showMoreVisible && (<Button theme={theme} title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
minHeight: 36,
|
minHeight: 36,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Context = ({ elements, parser }: any) => (
|
export const Context = ({ elements, parser }: any) => (
|
||||||
|
@ -19,5 +19,5 @@ export const Context = ({ elements, parser }: any) => (
|
||||||
|
|
||||||
Context.propTypes = {
|
Context.propTypes = {
|
||||||
elements: PropTypes.array,
|
elements: PropTypes.array,
|
||||||
parser: PropTypes.object
|
parser: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from 'react';
|
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 DateTimePicker from '@react-native-community/datetimepicker';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||||
|
@ -8,7 +8,6 @@ import moment from 'moment';
|
||||||
import Button from '../Button';
|
import Button from '../Button';
|
||||||
import { textParser } from './utils';
|
import { textParser } from './utils';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import { isAndroid } from '../../utils/deviceInfo';
|
import { isAndroid } from '../../utils/deviceInfo';
|
||||||
|
@ -21,19 +20,19 @@ const styles = StyleSheet.create({
|
||||||
borderWidth: StyleSheet.hairlineWidth,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
inputText: {
|
inputText: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
fontSize: 14
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
right: 16,
|
right: 16,
|
||||||
position: 'absolute'
|
position: 'absolute',
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
padding: 0
|
padding: 0,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IDatePicker {
|
interface IDatePicker {
|
||||||
|
@ -51,7 +50,7 @@ interface IDatePicker {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DatePicker = ({
|
export const DatePicker = ({
|
||||||
element, language, action, context, theme, loading, value, error
|
element, language, action, context, theme, loading, value, error,
|
||||||
}: IDatePicker) => {
|
}: IDatePicker) => {
|
||||||
const [show, onShow] = useState(false);
|
const [show, onShow] = useState(false);
|
||||||
const { initial_date, placeholder } = element;
|
const { initial_date, placeholder } = element;
|
||||||
|
@ -86,7 +85,7 @@ export const DatePicker = ({
|
||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
styles.inputText,
|
styles.inputText,
|
||||||
{ color: error ? themes[theme].dangerColor : themes[theme].titleText }
|
{ color: error ? themes[theme].dangerColor : themes[theme].titleText },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{currentDate.toLocaleDateString(language)}
|
{currentDate.toLocaleDateString(language)}
|
||||||
|
|
|
@ -7,8 +7,8 @@ const styles = StyleSheet.create({
|
||||||
separator: {
|
separator: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
marginBottom: 16
|
marginBottom: 16,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Divider = () => <List.Separator style={styles.separator} />;
|
export const Divider = () => <List.Separator style={styles.separator} />;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
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 FastImage from '@rocket.chat/react-native-fast-image';
|
||||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ import Navigation from '../../lib/Navigation';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
image: {
|
image: {
|
||||||
borderRadius: 2
|
borderRadius: 2,
|
||||||
},
|
},
|
||||||
mediaContext: {
|
mediaContext: {
|
||||||
marginRight: 8
|
marginRight: 8,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IThumb {
|
interface IThumb {
|
||||||
|
|
|
@ -7,28 +7,28 @@ import { themes } from '../../constants/colors';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
marginBottom: 16
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginVertical: 10,
|
marginVertical: 10,
|
||||||
...sharedStyles.textSemibold
|
...sharedStyles.textSemibold,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
...sharedStyles.textAlignCenter
|
...sharedStyles.textAlignCenter,
|
||||||
},
|
},
|
||||||
hint: {
|
hint: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
...sharedStyles.textRegular
|
...sharedStyles.textRegular,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IInput {
|
interface IInput {
|
||||||
|
@ -42,7 +42,7 @@ interface IInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Input = ({
|
export const Input = ({
|
||||||
element, parser, label, description, error, hint, theme
|
element, parser, label, description, error, hint, theme,
|
||||||
}: IInput) => (
|
}: IInput) => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{label ? <Text style={[styles.label, { color: error ? themes[theme].dangerColor : themes[theme].titleText }]}>{label}</Text> : null}
|
{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 { themes } from '../../../constants/colors';
|
||||||
import { textParser } from '../utils';
|
import { textParser } from '../utils';
|
||||||
import { CustomIcon } from '../../../lib/Icons';
|
import { CustomIcon } from '../../../lib/Icons';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IChip {
|
interface IChip {
|
||||||
|
@ -50,7 +49,7 @@ Chip.propTypes = {
|
||||||
|
|
||||||
const Chips = ({ items, onSelect, style, theme }: IChips) => (
|
const Chips = ({ items, onSelect, style, theme }: IChips) => (
|
||||||
<View style={styles.chips}>
|
<View style={styles.chips}>
|
||||||
{items.map(item => <Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} theme={theme} />)}
|
{items.map((item) => <Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} theme={theme} />)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
import { CustomIcon } from '../../../lib/Icons';
|
import { CustomIcon } from '../../../lib/Icons';
|
||||||
|
@ -18,7 +18,7 @@ interface IInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Input = ({
|
const Input = ({
|
||||||
children, onPress, theme, loading, inputStyle, placeholder, disabled
|
children, onPress, theme, loading, inputStyle, placeholder, disabled,
|
||||||
}: IInput) => (
|
}: IInput) => (
|
||||||
<Touchable
|
<Touchable
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, FlatList } from 'react-native';
|
import { FlatList, Text } from 'react-native';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import Check from '../../Check';
|
||||||
import * as List from '../../List';
|
import * as List from '../../List';
|
||||||
import { textParser } from '../utils';
|
import { textParser } from '../utils';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IItem {
|
interface IItem {
|
||||||
|
@ -40,7 +39,7 @@ const Item = ({ item, selected, onSelect, theme }: IItem) => {
|
||||||
onPress={() => onSelect(item)}
|
onPress={() => onSelect(item)}
|
||||||
style={[
|
style={[
|
||||||
styles.item,
|
styles.item,
|
||||||
{ backgroundColor: themes[theme].backgroundColor }
|
{ backgroundColor: themes[theme].backgroundColor },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
|
@ -60,7 +59,7 @@ const Items = ({ items, selected, onSelect, theme }: IItems) => (
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
keyExtractor={keyExtractor}
|
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 {
|
import {
|
||||||
View, Text, TouchableWithoutFeedback, Modal, KeyboardAvoidingView, Animated, Easing, StyleSheet
|
Animated, Easing, KeyboardAvoidingView, Modal, StyleSheet, Text, TouchableWithoutFeedback, View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||||
|
|
||||||
import Button from '../../Button';
|
import Button from '../../Button';
|
||||||
import TextInput from '../../TextInput';
|
import TextInput from '../../TextInput';
|
||||||
|
|
||||||
import { textParser } from '../utils';
|
import { textParser } from '../utils';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import I18n from '../../../i18n';
|
import I18n from '../../../i18n';
|
||||||
import { isIOS } from '../../../utils/deviceInfo';
|
import { isIOS } from '../../../utils/deviceInfo';
|
||||||
|
|
||||||
import Chips from './Chips';
|
import Chips from './Chips';
|
||||||
import Items from './Items';
|
import Items from './Items';
|
||||||
import Input from './Input';
|
import Input from './Input';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IMultiSelect {
|
interface IMultiSelect {
|
||||||
|
@ -39,7 +36,7 @@ const ANIMATION_DURATION = 200;
|
||||||
const ANIMATION_PROPS = {
|
const ANIMATION_PROPS = {
|
||||||
duration: ANIMATION_DURATION,
|
duration: ANIMATION_DURATION,
|
||||||
easing: Easing.inOut(Easing.quad),
|
easing: Easing.inOut(Easing.quad),
|
||||||
useNativeDriver: true
|
useNativeDriver: true,
|
||||||
};
|
};
|
||||||
const animatedValue = new Animated.Value(0);
|
const animatedValue = new Animated.Value(0);
|
||||||
|
|
||||||
|
@ -57,7 +54,7 @@ export const MultiSelect = React.memo(({
|
||||||
onClose = () => {},
|
onClose = () => {},
|
||||||
disabled,
|
disabled,
|
||||||
inputStyle,
|
inputStyle,
|
||||||
theme
|
theme,
|
||||||
}: IMultiSelect) => {
|
}: IMultiSelect) => {
|
||||||
const [selected, select] = useState<any>(Array.isArray(values) ? values : []);
|
const [selected, select] = useState<any>(Array.isArray(values) ? values : []);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
@ -86,8 +83,8 @@ export const MultiSelect = React.memo(({
|
||||||
animatedValue,
|
animatedValue,
|
||||||
{
|
{
|
||||||
toValue: 1,
|
toValue: 1,
|
||||||
...ANIMATION_PROPS
|
...ANIMATION_PROPS,
|
||||||
}
|
},
|
||||||
).start();
|
).start();
|
||||||
setShowContent(true);
|
setShowContent(true);
|
||||||
};
|
};
|
||||||
|
@ -98,8 +95,8 @@ export const MultiSelect = React.memo(({
|
||||||
animatedValue,
|
animatedValue,
|
||||||
{
|
{
|
||||||
toValue: 0,
|
toValue: 0,
|
||||||
...ANIMATION_PROPS
|
...ANIMATION_PROPS,
|
||||||
}
|
},
|
||||||
).start(() => setShowContent(false));
|
).start(() => setShowContent(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,7 +126,7 @@ export const MultiSelect = React.memo(({
|
||||||
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
|
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
|
||||||
<TextInput
|
<TextInput
|
||||||
testID='multi-select-search'
|
testID='multi-select-search'
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
onChangeText={onSearch || onSearchChange}
|
onChangeText={onSearch || onSearchChange}
|
||||||
placeholder={I18n.t('Search')}
|
placeholder={I18n.t('Search')}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
@ -142,7 +139,7 @@ export const MultiSelect = React.memo(({
|
||||||
|
|
||||||
const translateY = animatedValue.interpolate({
|
const translateY = animatedValue.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: [600, 0]
|
outputRange: [600, 0],
|
||||||
});
|
});
|
||||||
|
|
||||||
let button = multiselect ? (
|
let button = multiselect ? (
|
||||||
|
@ -176,7 +173,7 @@ export const MultiSelect = React.memo(({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
inputStyle={inputStyle}
|
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>}
|
{items.length ? <Chips items={items} onSelect={onSelect} theme={theme} /> : <Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder.text}</Text>}
|
||||||
</Input>
|
</Input>
|
||||||
);
|
);
|
||||||
|
@ -193,9 +190,9 @@ export const MultiSelect = React.memo(({
|
||||||
>
|
>
|
||||||
<TouchableWithoutFeedback onPress={onHide}>
|
<TouchableWithoutFeedback onPress={onHide}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<View style={{ ...StyleSheet.absoluteFill, opacity: themes[theme].backdropOpacity, backgroundColor: themes[theme].backdropColor }} />
|
<View style={{ ...StyleSheet.absoluteFill, opacity: themes[theme].backdropOpacity, backgroundColor: themes[theme].backdropColor }} />
|
||||||
{/*@ts-ignore*/}
|
{/* @ts-ignore*/}
|
||||||
<KeyboardAvoidingView style={styles.keyboardView} behavior={behavior}>
|
<KeyboardAvoidingView style={styles.keyboardView} behavior={behavior}>
|
||||||
<Animated.View style={[styles.animatedContent, { transform: [{ translateY }] }]}>
|
<Animated.View style={[styles.animatedContent, { transform: [{ translateY }] }]}>
|
||||||
{showContent ? renderContent() : null}
|
{showContent ? renderContent() : null}
|
||||||
|
|
|
@ -6,34 +6,34 @@ export default StyleSheet.create<any>({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'flex-end'
|
justifyContent: 'flex-end',
|
||||||
},
|
},
|
||||||
modal: {
|
modal: {
|
||||||
height: 300,
|
height: 300,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
borderTopRightRadius: 16,
|
borderTopRightRadius: 16,
|
||||||
borderTopLeftRadius: 16,
|
borderTopLeftRadius: 16,
|
||||||
overflow: 'hidden'
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
padding: 16
|
padding: 16,
|
||||||
},
|
},
|
||||||
animatedContent: {
|
animatedContent: {
|
||||||
width: '100%'
|
width: '100%',
|
||||||
},
|
},
|
||||||
keyboardView: {
|
keyboardView: {
|
||||||
width: '100%'
|
width: '100%',
|
||||||
},
|
},
|
||||||
pickerText: {
|
pickerText: {
|
||||||
...sharedStyles.textRegular,
|
...sharedStyles.textRegular,
|
||||||
paddingLeft: 6,
|
paddingLeft: 6,
|
||||||
fontSize: 16
|
fontSize: 16,
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
height: 48,
|
height: 48,
|
||||||
maxWidth: '85%',
|
maxWidth: '85%',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
minHeight: 48,
|
minHeight: 48,
|
||||||
|
@ -42,23 +42,23 @@ export default StyleSheet.create<any>({
|
||||||
borderWidth: StyleSheet.hairlineWidth,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 16
|
right: 16,
|
||||||
},
|
},
|
||||||
itemContent: {
|
itemContent: {
|
||||||
paddingBottom: 36
|
paddingBottom: 36,
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
height: 226
|
height: 226,
|
||||||
},
|
},
|
||||||
chips: {
|
chips: {
|
||||||
paddingTop: 8,
|
paddingTop: 8,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
marginRight: 50
|
marginRight: 50,
|
||||||
},
|
},
|
||||||
chip: {
|
chip: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
@ -67,24 +67,24 @@ export default StyleSheet.create<any>({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingHorizontal: 4,
|
paddingHorizontal: 4,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
marginRight: 8
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
chipText: {
|
chipText: {
|
||||||
paddingHorizontal: 8,
|
paddingHorizontal: 8,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
...sharedStyles.textMedium,
|
...sharedStyles.textMedium,
|
||||||
fontSize: 14
|
fontSize: 14,
|
||||||
},
|
},
|
||||||
chipImage: {
|
chipImage: {
|
||||||
marginLeft: 4,
|
marginLeft: 4,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20,
|
||||||
},
|
},
|
||||||
itemImage: {
|
itemImage: {
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24
|
height: 24,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from 'react';
|
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 Popover from 'react-native-popover-view';
|
||||||
import Touchable from 'react-native-platform-touchable';
|
import Touchable from 'react-native-platform-touchable';
|
||||||
|
|
||||||
|
@ -39,15 +39,15 @@ const keyExtractor = (item: any) => item.value;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
menu: {
|
menu: {
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
option: {
|
option: {
|
||||||
padding: 8,
|
padding: 8,
|
||||||
minHeight: 32
|
minHeight: 32,
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
padding: 0
|
padding: 0,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: IOption) => (
|
const Option = ({ option: { text, value }, onOptionPress, parser, theme }: IOption) => (
|
||||||
|
@ -83,8 +83,8 @@ export const Overflow = ({ element, loading, action, parser, theme }: IOverflow)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Touchable
|
<Touchable
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
ref={ref => touchable[blockId] = ref}
|
ref={(ref) => touchable[blockId] = ref}
|
||||||
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
background={Touchable.Ripple(themes[theme].bannerBackground)}
|
||||||
onPress={() => onShow(!show)}
|
onPress={() => onShow(!show)}
|
||||||
hitSlop={BUTTON_HIT_SLOP}
|
hitSlop={BUTTON_HIT_SLOP}
|
||||||
|
@ -94,7 +94,7 @@ export const Overflow = ({ element, loading, action, parser, theme }: IOverflow)
|
||||||
</Touchable>
|
</Touchable>
|
||||||
<Popover
|
<Popover
|
||||||
isVisible={show}
|
isVisible={show}
|
||||||
/*@ts-ignore*/
|
/* @ts-ignore*/
|
||||||
fromView={touchable[blockId]}
|
fromView={touchable[blockId]}
|
||||||
onRequestClose={() => onShow(false)}
|
onRequestClose={() => onShow(false)}
|
||||||
>
|
>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue