Merge 4.23.0 into single-server (#3575)
This commit is contained in:
parent
b564eddcfd
commit
2b8757571c
|
@ -1419,6 +1419,7 @@ Array [
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Use"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
@ -1581,6 +1582,7 @@ Array [
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Use"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
@ -41244,6 +41246,7 @@ exports[`Storyshots Message Show a button as attachment 1`] = `
|
||||||
Test Button
|
Test Button
|
||||||
</Text>
|
</Text>
|
||||||
<View
|
<View
|
||||||
|
accessibilityLabel="Text button"
|
||||||
accessible={true}
|
accessible={true}
|
||||||
focusable={true}
|
focusable={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
|
|
@ -144,13 +144,15 @@ android {
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode VERSIONCODE as Integer
|
versionCode VERSIONCODE as Integer
|
||||||
versionName "4.22.0"
|
versionName "4.23.0"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
if (!isFoss) {
|
if (!isFoss) {
|
||||||
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
|
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
|
||||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" // See note below!
|
||||||
}
|
}
|
||||||
resValue "string", "rn_config_reader_custom_package", "chat.rocket.reactnative"
|
resValue "string", "rn_config_reader_custom_package", "chat.rocket.reactnative"
|
||||||
|
testBuildType System.getProperty('testBuildType', 'debug')
|
||||||
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -203,6 +205,10 @@ android {
|
||||||
dimension = "app"
|
dimension = "app"
|
||||||
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
||||||
}
|
}
|
||||||
|
e2e {
|
||||||
|
dimension = "app"
|
||||||
|
buildConfigField "boolean", "IS_OFFICIAL", "false"
|
||||||
|
}
|
||||||
foss {
|
foss {
|
||||||
dimension = "type"
|
dimension = "type"
|
||||||
buildConfigField "boolean", "FDROID_BUILD", "true"
|
buildConfigField "boolean", "FDROID_BUILD", "true"
|
||||||
|
@ -230,6 +236,16 @@ android {
|
||||||
java.srcDirs = ['src/main/java', 'src/play/java']
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
manifest.srcFile 'src/play/AndroidManifest.xml'
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
}
|
}
|
||||||
|
e2ePlayDebug {
|
||||||
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
|
res.srcDirs = ['src/experimental/res']
|
||||||
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
|
}
|
||||||
|
e2ePlayRelease {
|
||||||
|
java.srcDirs = ['src/main/java', 'src/play/java']
|
||||||
|
res.srcDirs = ['src/experimental/res']
|
||||||
|
manifest.srcFile 'src/play/AndroidManifest.xml'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
|
@ -294,6 +310,8 @@ dependencies {
|
||||||
implementation "com.tencent:mmkv-static:1.2.1"
|
implementation "com.tencent:mmkv-static:1.2.1"
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
||||||
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.0"
|
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.0"
|
||||||
|
androidTestImplementation('com.wix:detox:+') { transitive = true }
|
||||||
|
androidTestImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run this once to be able to run the application with BUCK
|
// Run this once to be able to run the application with BUCK
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Replace "com.example" here and below with your app's package name from the top of MainActivity.java
|
||||||
|
package chat.rocket.reactnative;
|
||||||
|
|
||||||
|
import com.wix.detox.Detox;
|
||||||
|
import com.wix.detox.config.DetoxConfig;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
import androidx.test.rule.ActivityTestRule;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@LargeTest
|
||||||
|
public class DetoxTest {
|
||||||
|
@Rule
|
||||||
|
// Replace 'MainActivity' with the value of android:name entry in
|
||||||
|
// <activity> in AndroidManifest.xml
|
||||||
|
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runDetoxTests() {
|
||||||
|
DetoxConfig detoxConfig = new DetoxConfig();
|
||||||
|
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
|
||||||
|
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
|
||||||
|
detoxConfig.rnContextLoadTimeoutSec = (chat.rocket.reactnative.BuildConfig.DEBUG ? 180 : 60);
|
||||||
|
|
||||||
|
Detox.runTests(mActivityRule, detoxConfig);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<base-config cleartextTrafficPermitted="true">
|
||||||
|
<trust-anchors>
|
||||||
|
<certificates src="system" />
|
||||||
|
<certificates src="user"
|
||||||
|
tools:ignore="AcceptsUserCertificates" />
|
||||||
|
</trust-anchors>
|
||||||
|
</base-config>
|
||||||
|
</network-security-config>
|
|
@ -53,6 +53,10 @@ allprojects {
|
||||||
url("$rootDir/../node_modules/jsc-android/dist")
|
url("$rootDir/../node_modules/jsc-android/dist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url "$rootDir/../node_modules/detox/Detox-android"
|
||||||
|
}
|
||||||
|
|
||||||
maven {
|
maven {
|
||||||
url jitsi_url
|
url jitsi_url
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { NavigationContainer } from '@react-navigation/native';
|
||||||
import { createStackNavigator } from '@react-navigation/stack';
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { SetUsernameStackParamList, StackParamList } from './navigationTypes';
|
||||||
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 { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME } from './actions/app';
|
import { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME } from './actions/app';
|
||||||
|
@ -17,7 +18,7 @@ import { ThemeContext } from './theme';
|
||||||
import { setCurrentScreen } from './utils/log';
|
import { setCurrentScreen } from './utils/log';
|
||||||
|
|
||||||
// SetUsernameStack
|
// SetUsernameStack
|
||||||
const SetUsername = createStackNavigator();
|
const SetUsername = createStackNavigator<SetUsernameStackParamList>();
|
||||||
const SetUsernameStack = () => (
|
const SetUsernameStack = () => (
|
||||||
<SetUsername.Navigator screenOptions={defaultHeader}>
|
<SetUsername.Navigator screenOptions={defaultHeader}>
|
||||||
<SetUsername.Screen name='SetUsernameView' component={SetUsernameView} />
|
<SetUsername.Screen name='SetUsernameView' component={SetUsernameView} />
|
||||||
|
@ -25,7 +26,7 @@ const SetUsernameStack = () => (
|
||||||
);
|
);
|
||||||
|
|
||||||
// App
|
// App
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator<StackParamList>();
|
||||||
const App = React.memo(({ root, isMasterDetail }: { root: string; isMasterDetail: boolean }) => {
|
const App = React.memo(({ root, isMasterDetail }: { root: string; isMasterDetail: boolean }) => {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -124,7 +124,11 @@ const ActionSheet = React.memo(
|
||||||
|
|
||||||
const renderFooter = () =>
|
const renderFooter = () =>
|
||||||
data?.hasCancel ? (
|
data?.hasCancel ? (
|
||||||
<Button onPress={hide} style={[styles.button, { backgroundColor: themes[theme].auxiliaryBackground }]} theme={theme}>
|
<Button
|
||||||
|
onPress={hide}
|
||||||
|
style={[styles.button, { backgroundColor: themes[theme].auxiliaryBackground }]}
|
||||||
|
theme={theme}
|
||||||
|
accessibilityLabel={I18n.t('Cancel')}>
|
||||||
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{I18n.t('Cancel')}</Text>
|
<Text style={[styles.text, { color: themes[theme].bodyText }]}>{I18n.t('Cancel')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const useActionSheet = () => useContext(context);
|
||||||
|
|
||||||
const { Provider, Consumer } = context;
|
const { Provider, Consumer } = context;
|
||||||
|
|
||||||
export const withActionSheet = <P extends object>(Component: React.ComponentType<P>) =>
|
export const withActionSheet = (Component: any): any =>
|
||||||
forwardRef((props: any, ref: ForwardedRef<any>) => (
|
forwardRef((props: any, ref: ForwardedRef<any>) => (
|
||||||
<Consumer>{(contexts: any) => <Component {...props} {...contexts} ref={ref} />}</Consumer>
|
<Consumer>{(contexts: any) => <Component {...props} {...contexts} ref={ref} />}</Consumer>
|
||||||
));
|
));
|
||||||
|
|
|
@ -70,6 +70,7 @@ export default class Button extends React.PureComponent<Partial<IButtonProps>, a
|
||||||
disabled && styles.disabled,
|
disabled && styles.disabled,
|
||||||
style
|
style
|
||||||
]}
|
]}
|
||||||
|
accessibilityLabel={title}
|
||||||
{...otherProps}>
|
{...otherProps}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ActivityIndicator color={textColor} />
|
<ActivityIndicator color={textColor} />
|
||||||
|
|
|
@ -31,7 +31,7 @@ interface IEmojiPickerProps {
|
||||||
customEmojis?: any;
|
customEmojis?: any;
|
||||||
style: object;
|
style: object;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
onEmojiSelected?: Function;
|
onEmojiSelected?: ((emoji: any) => void) | ((keyboardId: any, params?: any) => void);
|
||||||
tabEmojiStyle?: object;
|
tabEmojiStyle?: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,4 +201,5 @@ const mapStateToProps = (state: any) => ({
|
||||||
customEmojis: state.customEmojis
|
customEmojis: state.customEmojis
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(EmojiPicker));
|
// TODO - remove this as any, at the new PR to fix the HOC erros
|
||||||
|
export default connect(mapStateToProps)(withTheme(EmojiPicker)) as any;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { StyleSheet, View } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
interface IHeaderButtonContainer {
|
interface IHeaderButtonContainer {
|
||||||
children: JSX.Element;
|
children: React.ReactNode;
|
||||||
left?: boolean;
|
left?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -423,4 +423,4 @@ const mapStateToProps = (state: any) => ({
|
||||||
services: state.login.services
|
services: state.login.services
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withTheme(LoginServices));
|
export default connect(mapStateToProps)(withTheme(LoginServices)) as any;
|
||||||
|
|
|
@ -13,7 +13,7 @@ interface IMessageBoxEmojiKeyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
|
export default class EmojiKeyboard extends React.PureComponent<IMessageBoxEmojiKeyboard, any> {
|
||||||
private readonly baseUrl: any;
|
private readonly baseUrl: string;
|
||||||
|
|
||||||
constructor(props: IMessageBoxEmojiKeyboard) {
|
constructor(props: IMessageBoxEmojiKeyboard) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { events, logEvent } from '../../utils/log';
|
||||||
|
|
||||||
interface IMessageBoxRecordAudioProps {
|
interface IMessageBoxRecordAudioProps {
|
||||||
theme: string;
|
theme: string;
|
||||||
|
permissionToUpload: boolean;
|
||||||
recordingCallback: Function;
|
recordingCallback: Function;
|
||||||
onFinish: Function;
|
onFinish: Function;
|
||||||
}
|
}
|
||||||
|
@ -192,9 +193,11 @@ export default class RecordAudio extends React.PureComponent<IMessageBoxRecordAu
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { theme } = this.props;
|
const { theme, permissionToUpload } = this.props;
|
||||||
const { isRecording, isRecorderActive } = this.state;
|
const { isRecording, isRecorderActive } = this.state;
|
||||||
|
if (!permissionToUpload) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!isRecording && !isRecorderActive) {
|
if (!isRecording && !isRecorderActive) {
|
||||||
return (
|
return (
|
||||||
<BorderlessButton
|
<BorderlessButton
|
||||||
|
|
|
@ -109,6 +109,8 @@ interface IMessageBoxProps {
|
||||||
sharing: boolean;
|
sharing: boolean;
|
||||||
isActionsEnabled: boolean;
|
isActionsEnabled: boolean;
|
||||||
usedCannedResponse: string;
|
usedCannedResponse: string;
|
||||||
|
uploadFilePermission: string[];
|
||||||
|
serverVersion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMessageBoxState {
|
interface IMessageBoxState {
|
||||||
|
@ -124,6 +126,7 @@ interface IMessageBoxState {
|
||||||
};
|
};
|
||||||
tshow: boolean;
|
tshow: boolean;
|
||||||
mentionLoading: boolean;
|
mentionLoading: boolean;
|
||||||
|
permissionToUpload: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
@ -179,41 +182,13 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
showCommandPreview: false,
|
showCommandPreview: false,
|
||||||
command: {},
|
command: {},
|
||||||
tshow: false,
|
tshow: false,
|
||||||
mentionLoading: false
|
mentionLoading: false,
|
||||||
|
permissionToUpload: true
|
||||||
};
|
};
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.selection = { start: 0, end: 0 };
|
this.selection = { start: 0, end: 0 };
|
||||||
this.focused = false;
|
this.focused = false;
|
||||||
|
|
||||||
// MessageBox Actions
|
|
||||||
this.options = [
|
|
||||||
{
|
|
||||||
title: I18n.t('Take_a_photo'),
|
|
||||||
icon: 'camera-photo',
|
|
||||||
onPress: this.takePhoto
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: I18n.t('Take_a_video'),
|
|
||||||
icon: 'camera',
|
|
||||||
onPress: this.takeVideo
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: I18n.t('Choose_from_library'),
|
|
||||||
icon: 'image',
|
|
||||||
onPress: this.chooseFromLibrary
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: I18n.t('Choose_file'),
|
|
||||||
icon: 'attach',
|
|
||||||
onPress: this.chooseFile
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: I18n.t('Create_Discussion'),
|
|
||||||
icon: 'discussions',
|
|
||||||
onPress: this.createDiscussion
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const libPickerLabels = {
|
const libPickerLabels = {
|
||||||
cropperChooseText: I18n.t('Choose'),
|
cropperChooseText: I18n.t('Choose'),
|
||||||
cropperCancelText: I18n.t('Cancel'),
|
cropperCancelText: I18n.t('Cancel'),
|
||||||
|
@ -277,6 +252,8 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
this.onChangeText(usedCannedResponse);
|
this.onChangeText(usedCannedResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setOptions();
|
||||||
|
|
||||||
this.unsubscribeFocus = navigation.addListener('focus', () => {
|
this.unsubscribeFocus = navigation.addListener('focus', () => {
|
||||||
// didFocus
|
// didFocus
|
||||||
// We should wait pushed views be dismissed
|
// We should wait pushed views be dismissed
|
||||||
|
@ -321,10 +298,20 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: any, nextState: any) {
|
shouldComponentUpdate(nextProps: IMessageBoxProps, nextState: IMessageBoxState) {
|
||||||
const { showEmojiKeyboard, showSend, recording, mentions, commandPreview, tshow, mentionLoading, trackingType } = this.state;
|
const {
|
||||||
|
showEmojiKeyboard,
|
||||||
|
showSend,
|
||||||
|
recording,
|
||||||
|
mentions,
|
||||||
|
commandPreview,
|
||||||
|
tshow,
|
||||||
|
mentionLoading,
|
||||||
|
trackingType,
|
||||||
|
permissionToUpload
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
const { roomType, replying, editing, isFocused, message, theme, usedCannedResponse } = this.props;
|
const { roomType, replying, editing, isFocused, message, theme, usedCannedResponse, uploadFilePermission } = this.props;
|
||||||
if (nextProps.theme !== theme) {
|
if (nextProps.theme !== theme) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -358,6 +345,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
if (nextState.tshow !== tshow) {
|
if (nextState.tshow !== tshow) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (nextState.permissionToUpload !== permissionToUpload) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!dequal(nextState.mentions, mentions)) {
|
if (!dequal(nextState.mentions, mentions)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -367,12 +357,22 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
if (!dequal(nextProps.message?.id, message?.id)) {
|
if (!dequal(nextProps.message?.id, message?.id)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!dequal(nextProps.uploadFilePermission, uploadFilePermission)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (nextProps.usedCannedResponse !== usedCannedResponse) {
|
if (nextProps.usedCannedResponse !== usedCannedResponse) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: IMessageBoxProps) {
|
||||||
|
const { uploadFilePermission } = this.props;
|
||||||
|
if (!dequal(prevProps.uploadFilePermission, uploadFilePermission)) {
|
||||||
|
this.setOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
console.countReset(`${this.constructor.name}.render calls`);
|
console.countReset(`${this.constructor.name}.render calls`);
|
||||||
if (this.onChangeText && this.onChangeText.stop) {
|
if (this.onChangeText && this.onChangeText.stop) {
|
||||||
|
@ -404,6 +404,19 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOptions = async () => {
|
||||||
|
const { uploadFilePermission, rid } = this.props;
|
||||||
|
|
||||||
|
// Servers older than 4.2
|
||||||
|
if (!uploadFilePermission) {
|
||||||
|
this.setState({ permissionToUpload: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionToUpload = await RocketChat.hasPermission([uploadFilePermission], rid);
|
||||||
|
this.setState({ permissionToUpload: permissionToUpload[0] });
|
||||||
|
};
|
||||||
|
|
||||||
onChangeText: any = (text: string): void => {
|
onChangeText: any = (text: string): void => {
|
||||||
const isTextEmpty = text.length === 0;
|
const isTextEmpty = text.length === 0;
|
||||||
this.setShowSend(!isTextEmpty);
|
this.setShowSend(!isTextEmpty);
|
||||||
|
@ -666,8 +679,9 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
canUploadFile = (file: any) => {
|
canUploadFile = (file: any) => {
|
||||||
|
const { permissionToUpload } = this.state;
|
||||||
const { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize } = this.props;
|
const { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize } = this.props;
|
||||||
const result = canUploadFile(file, FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize);
|
const result = canUploadFile(file, FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize, permissionToUpload);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -766,8 +780,41 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
|
||||||
showMessageBoxActions = () => {
|
showMessageBoxActions = () => {
|
||||||
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
|
logEvent(events.ROOM_SHOW_BOX_ACTIONS);
|
||||||
|
const { permissionToUpload } = this.state;
|
||||||
const { showActionSheet } = this.props;
|
const { showActionSheet } = this.props;
|
||||||
showActionSheet({ options: this.options });
|
|
||||||
|
const options = [];
|
||||||
|
if (permissionToUpload) {
|
||||||
|
options.push(
|
||||||
|
{
|
||||||
|
title: I18n.t('Take_a_photo'),
|
||||||
|
icon: 'camera-photo',
|
||||||
|
onPress: this.takePhoto
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: I18n.t('Take_a_video'),
|
||||||
|
icon: 'camera',
|
||||||
|
onPress: this.takeVideo
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: I18n.t('Choose_from_library'),
|
||||||
|
icon: 'image',
|
||||||
|
onPress: this.chooseFromLibrary
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: I18n.t('Choose_file'),
|
||||||
|
icon: 'attach',
|
||||||
|
onPress: this.chooseFile
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push({
|
||||||
|
title: I18n.t('Create_Discussion'),
|
||||||
|
icon: 'discussions',
|
||||||
|
onPress: this.createDiscussion
|
||||||
|
});
|
||||||
|
showActionSheet({ options });
|
||||||
};
|
};
|
||||||
|
|
||||||
editCancel = () => {
|
editCancel = () => {
|
||||||
|
@ -968,8 +1015,17 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
renderContent = () => {
|
renderContent = () => {
|
||||||
const { recording, showEmojiKeyboard, showSend, mentions, trackingType, commandPreview, showCommandPreview, mentionLoading } =
|
const {
|
||||||
this.state;
|
recording,
|
||||||
|
showEmojiKeyboard,
|
||||||
|
showSend,
|
||||||
|
mentions,
|
||||||
|
trackingType,
|
||||||
|
commandPreview,
|
||||||
|
showCommandPreview,
|
||||||
|
mentionLoading,
|
||||||
|
permissionToUpload
|
||||||
|
} = this.state;
|
||||||
const {
|
const {
|
||||||
editing,
|
editing,
|
||||||
message,
|
message,
|
||||||
|
@ -995,7 +1051,12 @@ class MessageBox extends Component<IMessageBoxProps, IMessageBoxState> {
|
||||||
|
|
||||||
const recordAudio =
|
const recordAudio =
|
||||||
showSend || !Message_AudioRecorderEnabled ? null : (
|
showSend || !Message_AudioRecorderEnabled ? null : (
|
||||||
<RecordAudio theme={theme} recordingCallback={this.recordingCallback} onFinish={this.finishAudioMessage} />
|
<RecordAudio
|
||||||
|
theme={theme}
|
||||||
|
recordingCallback={this.recordingCallback}
|
||||||
|
onFinish={this.finishAudioMessage}
|
||||||
|
permissionToUpload={permissionToUpload}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const commandsPreviewAndMentions = !recording ? (
|
const commandsPreviewAndMentions = !recording ? (
|
||||||
|
@ -1117,11 +1178,12 @@ 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,
|
||||||
|
uploadFilePermission: state.permissions['mobile-upload-file']
|
||||||
});
|
});
|
||||||
|
|
||||||
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)) as any;
|
||||||
|
|
|
@ -20,7 +20,7 @@ interface IPasscodeBase {
|
||||||
previousPasscode?: string;
|
previousPasscode?: string;
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
showBiometry?: string;
|
showBiometry?: boolean;
|
||||||
onEndProcess: Function;
|
onEndProcess: Function;
|
||||||
onError?: Function;
|
onError?: Function;
|
||||||
onBiometryPress?(): void;
|
onBiometryPress?(): void;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import I18n from '../../i18n';
|
||||||
|
|
||||||
interface IPasscodePasscodeEnter {
|
interface IPasscodePasscodeEnter {
|
||||||
theme: string;
|
theme: string;
|
||||||
hasBiometry: string;
|
hasBiometry: boolean;
|
||||||
finishProcess: Function;
|
finishProcess: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, Text, View } from 'react-native';
|
import { StyleSheet, Text, TextInputProps, 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';
|
||||||
|
@ -45,7 +45,7 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ISearchBox {
|
interface ISearchBox {
|
||||||
onChangeText: () => void;
|
onChangeText: TextInputProps['onChangeText'];
|
||||||
onSubmitEditing: () => void;
|
onSubmitEditing: () => void;
|
||||||
hasCancel: boolean;
|
hasCancel: boolean;
|
||||||
onCancelPress: Function;
|
onCancelPress: Function;
|
||||||
|
|
|
@ -8,6 +8,7 @@ interface IStatus {
|
||||||
status: string;
|
status: string;
|
||||||
size: number;
|
size: number;
|
||||||
style?: StyleProp<TextStyle>;
|
style?: StyleProp<TextStyle>;
|
||||||
|
testID?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
|
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: IStatus) => {
|
||||||
|
|
|
@ -43,7 +43,11 @@ const Content = React.memo(
|
||||||
content = <Text style={[styles.text, { color: themes[props.theme].bodyText }]}>{I18n.t('Sent_an_attachment')}</Text>;
|
content = <Text style={[styles.text, { color: themes[props.theme].bodyText }]}>{I18n.t('Sent_an_attachment')}</Text>;
|
||||||
} else if (props.isEncrypted) {
|
} else if (props.isEncrypted) {
|
||||||
content = (
|
content = (
|
||||||
<Text style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}>{I18n.t('Encrypted_message')}</Text>
|
<Text
|
||||||
|
style={[styles.textInfo, { color: themes[props.theme].auxiliaryText }]}
|
||||||
|
accessibilityLabel={I18n.t('Encrypted_message')}>
|
||||||
|
{I18n.t('Encrypted_message')}
|
||||||
|
</Text>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const { baseUrl, user, onLinkPress } = useContext(MessageContext);
|
const { baseUrl, user, onLinkPress } = useContext(MessageContext);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export interface IAttachment {
|
||||||
|
title: string;
|
||||||
|
type: string;
|
||||||
|
description: string;
|
||||||
|
title_link?: string;
|
||||||
|
image_url?: string;
|
||||||
|
image_type?: string;
|
||||||
|
video_url?: string;
|
||||||
|
video_type?: string;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface IMessage {
|
||||||
|
msg: string;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface IRocketChatRecord {
|
||||||
|
id: string;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { IRocketChatRecord } from './IRocketChatRecord';
|
||||||
|
|
||||||
|
export enum RoomType {
|
||||||
|
GROUP = 'p',
|
||||||
|
DIRECT = 'd',
|
||||||
|
CHANNEL = 'c',
|
||||||
|
OMNICHANNEL = 'l',
|
||||||
|
THREAD = 'thread'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoom extends IRocketChatRecord {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
name: string;
|
||||||
|
fname: string;
|
||||||
|
prid?: string;
|
||||||
|
tmid?: string;
|
||||||
|
topic?: string;
|
||||||
|
teamMain?: boolean;
|
||||||
|
teamId?: string;
|
||||||
|
encrypted?: boolean;
|
||||||
|
visitor?: boolean;
|
||||||
|
autoTranslateLanguage?: boolean;
|
||||||
|
autoTranslate?: boolean;
|
||||||
|
observe?: Function;
|
||||||
|
usedCannedResponse: string;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
export interface IServer {
|
||||||
|
name: string;
|
||||||
|
iconURL: string;
|
||||||
|
useRealName: boolean;
|
||||||
|
FileUpload_MediaTypeWhiteList: string;
|
||||||
|
FileUpload_MaxFileSize: number;
|
||||||
|
roomsUpdatedAt: Date;
|
||||||
|
version: string;
|
||||||
|
lastLocalAuthenticatedSession: Date;
|
||||||
|
autoLock: boolean;
|
||||||
|
autoLockTime: number | null;
|
||||||
|
biometry: boolean | null;
|
||||||
|
uniqueID: string;
|
||||||
|
enterpriseModules: string;
|
||||||
|
E2E_Enable: boolean;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// https://github.com/RocketChat/Rocket.Chat/blob/develop/definition/ITeam.ts
|
// https://github.com/RocketChat/Rocket.Chat/blob/develop/definition/ITeam.ts
|
||||||
export const TEAM_TYPE = {
|
exports.TEAM_TYPE = {
|
||||||
PUBLIC: 0,
|
PUBLIC: 0,
|
||||||
PRIVATE: 1
|
PRIVATE: 1
|
||||||
};
|
};
|
|
@ -22,7 +22,7 @@ export interface IDimensionsContextProps {
|
||||||
|
|
||||||
export const DimensionsContext = React.createContext<Partial<IDimensionsContextProps>>(Dimensions.get('window'));
|
export const DimensionsContext = React.createContext<Partial<IDimensionsContextProps>>(Dimensions.get('window'));
|
||||||
|
|
||||||
export function withDimensions(Component: any) {
|
export function withDimensions(Component: any): any {
|
||||||
const DimensionsComponent = (props: any) => (
|
const DimensionsComponent = (props: any) => (
|
||||||
<DimensionsContext.Consumer>{contexts => <Component {...props} {...contexts} />}</DimensionsContext.Consumer>
|
<DimensionsContext.Consumer>{contexts => <Component {...props} {...contexts} />}</DimensionsContext.Consumer>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { inquiryQueueAdd, inquiryQueueRemove, inquiryQueueUpdate, inquiryRequest
|
||||||
const removeListener = listener => listener.stop();
|
const removeListener = listener => listener.stop();
|
||||||
|
|
||||||
let connectedListener;
|
let connectedListener;
|
||||||
let disconnectedListener;
|
|
||||||
let queueListener;
|
let queueListener;
|
||||||
|
|
||||||
const streamTopic = 'stream-livechat-inquiry-queue-observer';
|
const streamTopic = 'stream-livechat-inquiry-queue-observer';
|
||||||
|
@ -48,10 +47,6 @@ export default function subscribeInquiry() {
|
||||||
connectedListener.then(removeListener);
|
connectedListener.then(removeListener);
|
||||||
connectedListener = false;
|
connectedListener = false;
|
||||||
}
|
}
|
||||||
if (disconnectedListener) {
|
|
||||||
disconnectedListener.then(removeListener);
|
|
||||||
disconnectedListener = false;
|
|
||||||
}
|
|
||||||
if (queueListener) {
|
if (queueListener) {
|
||||||
queueListener.then(removeListener);
|
queueListener.then(removeListener);
|
||||||
queueListener = false;
|
queueListener = false;
|
||||||
|
@ -59,7 +54,6 @@ export default function subscribeInquiry() {
|
||||||
};
|
};
|
||||||
|
|
||||||
connectedListener = RocketChat.onStreamData('connected', handleConnection);
|
connectedListener = RocketChat.onStreamData('connected', handleConnection);
|
||||||
disconnectedListener = RocketChat.onStreamData('close', handleConnection);
|
|
||||||
queueListener = RocketChat.onStreamData(streamTopic, handleQueueMessageReceived);
|
queueListener = RocketChat.onStreamData(streamTopic, handleQueueMessageReceived);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -161,4 +161,5 @@ const mapStateToProps = state => ({
|
||||||
showAvatar: state.sortPreferences.showAvatar,
|
showAvatar: state.sortPreferences.showAvatar,
|
||||||
displayMode: state.sortPreferences.displayMode
|
displayMode: state.sortPreferences.displayMode
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView)));
|
export default connect(mapStateToProps)(withDimensions(withTheme(QueueListView)));
|
||||||
|
|
|
@ -328,7 +328,6 @@
|
||||||
"N_users": "{{n}} مستخدمين",
|
"N_users": "{{n}} مستخدمين",
|
||||||
"N_channels": "{{n}} القنوات",
|
"N_channels": "{{n}} القنوات",
|
||||||
"Name": "اسم",
|
"Name": "اسم",
|
||||||
"Navigation_history": "تاريخ التصفح",
|
|
||||||
"Never": "أبداً",
|
"Never": "أبداً",
|
||||||
"New_Message": "رسالة جديدة",
|
"New_Message": "رسالة جديدة",
|
||||||
"New_Password": "كلمة مرور جديدة",
|
"New_Password": "كلمة مرور جديدة",
|
||||||
|
|
|
@ -330,7 +330,6 @@
|
||||||
"N_users": "{{n}} Benutzer",
|
"N_users": "{{n}} Benutzer",
|
||||||
"N_channels": "{{n}} Kanäle",
|
"N_channels": "{{n}} Kanäle",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Navigation_history": "Navigations-Verlauf",
|
|
||||||
"Never": "Niemals",
|
"Never": "Niemals",
|
||||||
"New_Message": "Neue Nachricht",
|
"New_Message": "Neue Nachricht",
|
||||||
"New_Password": "Neues Kennwort",
|
"New_Password": "Neues Kennwort",
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"error-save-video": "Error while saving video",
|
"error-save-video": "Error while saving video",
|
||||||
"error-field-unavailable": "{{field}} is already in use :(",
|
"error-field-unavailable": "{{field}} is already in use :(",
|
||||||
"error-file-too-large": "File is too large",
|
"error-file-too-large": "File is too large",
|
||||||
|
"error-not-permission-to-upload-file": "You don't have permission to upload files",
|
||||||
"error-importer-not-defined": "The importer was not defined correctly, it is missing the Import class.",
|
"error-importer-not-defined": "The importer was not defined correctly, it is missing the Import class.",
|
||||||
"error-input-is-not-a-valid-field": "{{input}} is not a valid {{field}}",
|
"error-input-is-not-a-valid-field": "{{input}} is not a valid {{field}}",
|
||||||
"error-invalid-actionlink": "Invalid action link",
|
"error-invalid-actionlink": "Invalid action link",
|
||||||
|
@ -330,7 +331,6 @@
|
||||||
"N_users": "{{n}} users",
|
"N_users": "{{n}} users",
|
||||||
"N_channels": "{{n}} channels",
|
"N_channels": "{{n}} channels",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Navigation_history": "Navigation history",
|
|
||||||
"Never": "Never",
|
"Never": "Never",
|
||||||
"New_Message": "New Message",
|
"New_Message": "New Message",
|
||||||
"New_Password": "New Password",
|
"New_Password": "New Password",
|
||||||
|
|
|
@ -330,7 +330,6 @@
|
||||||
"N_users": "{{n}} utilisateurs",
|
"N_users": "{{n}} utilisateurs",
|
||||||
"N_channels": "{{n}} canaux",
|
"N_channels": "{{n}} canaux",
|
||||||
"Name": "Nom",
|
"Name": "Nom",
|
||||||
"Navigation_history": "Historique de navigation",
|
|
||||||
"Never": "Jamais",
|
"Never": "Jamais",
|
||||||
"New_Message": "Nouveau message",
|
"New_Message": "Nouveau message",
|
||||||
"New_Password": "Nouveau mot de passe",
|
"New_Password": "Nouveau mot de passe",
|
||||||
|
@ -782,5 +781,8 @@
|
||||||
"No_canned_responses": "Pas de réponses standardisées",
|
"No_canned_responses": "Pas de réponses standardisées",
|
||||||
"Send_email_confirmation": "Envoyer un e-mail de confirmation",
|
"Send_email_confirmation": "Envoyer un e-mail de confirmation",
|
||||||
"sending_email_confirmation": "envoi d'e-mail de confirmation",
|
"sending_email_confirmation": "envoi d'e-mail de confirmation",
|
||||||
"Enable_Message_Parser": "Activer le parseur de messages"
|
"Enable_Message_Parser": "Activer le parseur de messages",
|
||||||
|
"Unsupported_format": "Format non supporté",
|
||||||
|
"Downloaded_file": "Fichier téléchargé",
|
||||||
|
"Error_Download_file": "Erreur lors du téléchargement du fichier"
|
||||||
}
|
}
|
|
@ -322,7 +322,6 @@
|
||||||
"N_people_reacted": "{{n}} persone hanno reagito",
|
"N_people_reacted": "{{n}} persone hanno reagito",
|
||||||
"N_users": "{{n}} utenti",
|
"N_users": "{{n}} utenti",
|
||||||
"Name": "Nome",
|
"Name": "Nome",
|
||||||
"Navigation_history": "Cronologia di navigazione",
|
|
||||||
"Never": "Mai",
|
"Never": "Mai",
|
||||||
"New_Message": "Nuovo messaggio",
|
"New_Message": "Nuovo messaggio",
|
||||||
"New_Password": "Nuova password",
|
"New_Password": "Nuova password",
|
||||||
|
|
|
@ -330,7 +330,6 @@
|
||||||
"N_users": "{{n}} gebruikers",
|
"N_users": "{{n}} gebruikers",
|
||||||
"N_channels": "{{n}} kanalen",
|
"N_channels": "{{n}} kanalen",
|
||||||
"Name": "Naam",
|
"Name": "Naam",
|
||||||
"Navigation_history": "Navigatie geschiedenis",
|
|
||||||
"Never": "Nooit",
|
"Never": "Nooit",
|
||||||
"New_Message": "Nieuw bericht",
|
"New_Message": "Nieuw bericht",
|
||||||
"New_Password": "Nieuw wachtwoord",
|
"New_Password": "Nieuw wachtwoord",
|
||||||
|
@ -782,5 +781,8 @@
|
||||||
"No_canned_responses": "Geen standaardantwoorden",
|
"No_canned_responses": "Geen standaardantwoorden",
|
||||||
"Send_email_confirmation": "Stuur e-mailbevestiging",
|
"Send_email_confirmation": "Stuur e-mailbevestiging",
|
||||||
"sending_email_confirmation": "e-mailbevestiging aan het verzenden",
|
"sending_email_confirmation": "e-mailbevestiging aan het verzenden",
|
||||||
"Enable_Message_Parser": "Berichtparser inschakelen"
|
"Enable_Message_Parser": "Berichtparser inschakelen",
|
||||||
|
"Unsupported_format": "Niet ondersteund formaat",
|
||||||
|
"Downloaded_file": "Gedownload bestand",
|
||||||
|
"Error_Download_file": "Fout tijdens het downloaden van bestand"
|
||||||
}
|
}
|
|
@ -309,7 +309,6 @@
|
||||||
"N_users": "{{n}} usuários",
|
"N_users": "{{n}} usuários",
|
||||||
"N_channels": "{{n}} canais",
|
"N_channels": "{{n}} canais",
|
||||||
"Name": "Nome",
|
"Name": "Nome",
|
||||||
"Navigation_history": "Histórico de navegação",
|
|
||||||
"Never": "Nunca",
|
"Never": "Nunca",
|
||||||
"New_Message": "Nova Mensagem",
|
"New_Message": "Nova Mensagem",
|
||||||
"New_Password": "Nova Senha",
|
"New_Password": "Nova Senha",
|
||||||
|
|
|
@ -329,7 +329,6 @@
|
||||||
"N_users": "{{n}} utilizadores",
|
"N_users": "{{n}} utilizadores",
|
||||||
"N_channels": "{{n}} canais",
|
"N_channels": "{{n}} canais",
|
||||||
"Name": "Nome",
|
"Name": "Nome",
|
||||||
"Navigation_history": "Histórico de navegação",
|
|
||||||
"Never": "Nunca",
|
"Never": "Nunca",
|
||||||
"New_Message": "Nova Mensagem",
|
"New_Message": "Nova Mensagem",
|
||||||
"New_Password": "Nova Palavra-passe",
|
"New_Password": "Nova Palavra-passe",
|
||||||
|
|
|
@ -330,7 +330,6 @@
|
||||||
"N_users": "{{n}} пользователи",
|
"N_users": "{{n}} пользователи",
|
||||||
"N_channels": "{{n}} каналов",
|
"N_channels": "{{n}} каналов",
|
||||||
"Name": "Имя",
|
"Name": "Имя",
|
||||||
"Navigation_history": "История навигации",
|
|
||||||
"Never": "Никогда",
|
"Never": "Никогда",
|
||||||
"New_Message": "Новое сообщение",
|
"New_Message": "Новое сообщение",
|
||||||
"New_Password": "Новый пароль",
|
"New_Password": "Новый пароль",
|
||||||
|
@ -782,5 +781,8 @@
|
||||||
"No_canned_responses": "Нет заготовленных ответов",
|
"No_canned_responses": "Нет заготовленных ответов",
|
||||||
"Send_email_confirmation": "Отправить электронное письмо с подтверждением",
|
"Send_email_confirmation": "Отправить электронное письмо с подтверждением",
|
||||||
"sending_email_confirmation": "отправка подтверждения по электронной почте",
|
"sending_email_confirmation": "отправка подтверждения по электронной почте",
|
||||||
"Enable_Message_Parser": "Включить парсер сообщений"
|
"Enable_Message_Parser": "Включить парсер сообщений",
|
||||||
|
"Unsupported_format": "Неподдерживаемый формат",
|
||||||
|
"Downloaded_file": "Скачанный файл",
|
||||||
|
"Error_Download_file": "Ошибка при скачивании файла"
|
||||||
}
|
}
|
|
@ -323,7 +323,6 @@
|
||||||
"N_people_reacted": "{{n}} kişi tepki verdi",
|
"N_people_reacted": "{{n}} kişi tepki verdi",
|
||||||
"N_users": "{{n}} kullanıcı",
|
"N_users": "{{n}} kullanıcı",
|
||||||
"Name": "İsim",
|
"Name": "İsim",
|
||||||
"Navigation_history": "Gezinti geçmişi",
|
|
||||||
"Never": "Asla",
|
"Never": "Asla",
|
||||||
"New_Message": "Yeni İleti",
|
"New_Message": "Yeni İleti",
|
||||||
"New_Password": "Yeni Şifre",
|
"New_Password": "Yeni Şifre",
|
||||||
|
|
|
@ -320,7 +320,6 @@
|
||||||
"N_people_reacted": "{{n}} 人回复",
|
"N_people_reacted": "{{n}} 人回复",
|
||||||
"N_users": "{{n}} 位用户",
|
"N_users": "{{n}} 位用户",
|
||||||
"Name": "名称",
|
"Name": "名称",
|
||||||
"Navigation_history": "浏览历史记录",
|
|
||||||
"Never": "从不",
|
"Never": "从不",
|
||||||
"New_Message": "新信息",
|
"New_Message": "新信息",
|
||||||
"New_Password": "新密码",
|
"New_Password": "新密码",
|
||||||
|
|
|
@ -321,7 +321,6 @@
|
||||||
"N_people_reacted": "{{n}} 人回复",
|
"N_people_reacted": "{{n}} 人回复",
|
||||||
"N_users": "{{n}} 位使用者",
|
"N_users": "{{n}} 位使用者",
|
||||||
"Name": "名稱",
|
"Name": "名稱",
|
||||||
"Navigation_history": "瀏覽歷史記錄",
|
|
||||||
"Never": "從不",
|
"Never": "從不",
|
||||||
"New_Message": "新訊息",
|
"New_Message": "新訊息",
|
||||||
"New_Password": "新密碼",
|
"New_Password": "新密碼",
|
||||||
|
|
|
@ -55,7 +55,8 @@ const PERMISSIONS = [
|
||||||
'convert-team',
|
'convert-team',
|
||||||
'edit-omnichannel-contact',
|
'edit-omnichannel-contact',
|
||||||
'edit-livechat-room-customfields',
|
'edit-livechat-room-customfields',
|
||||||
'view-canned-responses'
|
'view-canned-responses',
|
||||||
|
'mobile-upload-file'
|
||||||
];
|
];
|
||||||
|
|
||||||
export async function setPermissions() {
|
export async function setPermissions() {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import messagesStatus from '../../../constants/messagesStatus';
|
||||||
import log from '../../../utils/log';
|
import log from '../../../utils/log';
|
||||||
import random from '../../../utils/random';
|
import random from '../../../utils/random';
|
||||||
import store from '../../createStore';
|
import store from '../../createStore';
|
||||||
import { roomsRequest } from '../../../actions/rooms';
|
|
||||||
import { handlePayloadUserInteraction } from '../actions';
|
import { handlePayloadUserInteraction } from '../actions';
|
||||||
import buildMessage from '../helpers/buildMessage';
|
import buildMessage from '../helpers/buildMessage';
|
||||||
import RocketChat from '../../rocketchat';
|
import RocketChat from '../../rocketchat';
|
||||||
|
@ -21,8 +20,6 @@ import { E2E_MESSAGE_TYPE } from '../../encryption/constants';
|
||||||
|
|
||||||
const removeListener = listener => listener.stop();
|
const removeListener = listener => listener.stop();
|
||||||
|
|
||||||
let connectedListener;
|
|
||||||
let disconnectedListener;
|
|
||||||
let streamListener;
|
let streamListener;
|
||||||
let subServer;
|
let subServer;
|
||||||
let queue = {};
|
let queue = {};
|
||||||
|
@ -255,10 +252,6 @@ const debouncedUpdate = subscription => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function subscribeRooms() {
|
export default function subscribeRooms() {
|
||||||
const handleConnection = () => {
|
|
||||||
store.dispatch(roomsRequest());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStreamMessageReceived = protectedFunction(async ddpMessage => {
|
const handleStreamMessageReceived = protectedFunction(async ddpMessage => {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
|
||||||
|
@ -388,14 +381,6 @@ export default function subscribeRooms() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
if (connectedListener) {
|
|
||||||
connectedListener.then(removeListener);
|
|
||||||
connectedListener = false;
|
|
||||||
}
|
|
||||||
if (disconnectedListener) {
|
|
||||||
disconnectedListener.then(removeListener);
|
|
||||||
disconnectedListener = false;
|
|
||||||
}
|
|
||||||
if (streamListener) {
|
if (streamListener) {
|
||||||
streamListener.then(removeListener);
|
streamListener.then(removeListener);
|
||||||
streamListener = false;
|
streamListener = false;
|
||||||
|
@ -407,8 +392,6 @@ export default function subscribeRooms() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
connectedListener = this.sdk.onStreamData('connected', handleConnection);
|
|
||||||
// disconnectedListener = this.sdk.onStreamData('close', handleConnection);
|
|
||||||
streamListener = this.sdk.onStreamData('stream-notify-user', handleStreamMessageReceived);
|
streamListener = this.sdk.onStreamData('stream-notify-user', handleStreamMessageReceived);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { selectServerFailure } from '../actions/server';
|
||||||
import { useSsl } from '../utils/url';
|
import { useSsl } from '../utils/url';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { updatePermission } from '../actions/permissions';
|
import { updatePermission } from '../actions/permissions';
|
||||||
import { TEAM_TYPE } from '../definition/ITeam';
|
import { TEAM_TYPE } from '../definitions/ITeam';
|
||||||
import { updateSettings } from '../actions/settings';
|
import { updateSettings } from '../actions/settings';
|
||||||
import { compareServerVersion, methods } from './utils';
|
import { compareServerVersion, methods } from './utils';
|
||||||
import reduxStore from './createStore';
|
import reduxStore from './createStore';
|
||||||
|
@ -239,37 +239,34 @@ const RocketChat = {
|
||||||
this.code = null;
|
this.code = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) });
|
// The app can't reconnect if reopen interval is 5s while in development
|
||||||
|
this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server), reopen: __DEV__ ? 20000 : 5000 });
|
||||||
this.getSettings();
|
this.getSettings();
|
||||||
|
|
||||||
const sdkConnect = () =>
|
this.sdk
|
||||||
this.sdk
|
.connect()
|
||||||
.connect()
|
.then(() => {
|
||||||
.then(() => {
|
console.log('connected');
|
||||||
const { server: currentServer } = reduxStore.getState().server;
|
})
|
||||||
if (user && user.token && server === currentServer) {
|
.catch(err => {
|
||||||
reduxStore.dispatch(loginRequest({ resume: user.token }, logoutOnError));
|
console.log('connect error', err);
|
||||||
}
|
});
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log('connect error', err);
|
|
||||||
|
|
||||||
// when `connect` raises an error, we try again in 10 seconds
|
|
||||||
this.connectTimeout = setTimeout(() => {
|
|
||||||
if (this.sdk?.client?.host === server) {
|
|
||||||
sdkConnect();
|
|
||||||
}
|
|
||||||
}, 10000);
|
|
||||||
});
|
|
||||||
|
|
||||||
sdkConnect();
|
|
||||||
|
|
||||||
this.connectingListener = this.sdk.onStreamData('connecting', () => {
|
this.connectingListener = this.sdk.onStreamData('connecting', () => {
|
||||||
reduxStore.dispatch(connectRequest());
|
reduxStore.dispatch(connectRequest());
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connectedListener = this.sdk.onStreamData('connected', () => {
|
this.connectedListener = this.sdk.onStreamData('connected', () => {
|
||||||
|
const { connected } = reduxStore.getState().meteor;
|
||||||
|
if (connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
reduxStore.dispatch(connectSuccess());
|
reduxStore.dispatch(connectSuccess());
|
||||||
|
const { server: currentServer } = reduxStore.getState().server;
|
||||||
|
const { user } = reduxStore.getState().login;
|
||||||
|
if (user?.token && server === currentServer) {
|
||||||
|
reduxStore.dispatch(loginRequest({ resume: user.token }, logoutOnError));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.closeListener = this.sdk.onStreamData('close', () => {
|
this.closeListener = this.sdk.onStreamData('close', () => {
|
||||||
|
@ -1141,10 +1138,6 @@ const RocketChat = {
|
||||||
// RC 0.36.0
|
// RC 0.36.0
|
||||||
return this.methodCallWrapper('livechat:transfer', transferData);
|
return this.methodCallWrapper('livechat:transfer', transferData);
|
||||||
},
|
},
|
||||||
getPagesLivechat(rid, offset) {
|
|
||||||
// RC 2.3.0
|
|
||||||
return this.sdk.get(`livechat/visitors.pagesVisited/${rid}?count=50&offset=${offset}`);
|
|
||||||
},
|
|
||||||
getDepartmentInfo(departmentId) {
|
getDepartmentInfo(departmentId) {
|
||||||
// RC 2.2.0
|
// RC 2.2.0
|
||||||
return this.sdk.get(`livechat/department/${departmentId}?includeAgents=false`);
|
return this.sdk.get(`livechat/department/${departmentId}?includeAgents=false`);
|
||||||
|
@ -1523,16 +1516,7 @@ const RocketChat = {
|
||||||
return this.sdk.get(`${this.roomTypeToApiType(type)}.files`, {
|
return this.sdk.get(`${this.roomTypeToApiType(type)}.files`, {
|
||||||
roomId,
|
roomId,
|
||||||
offset,
|
offset,
|
||||||
sort: { uploadedAt: -1 },
|
sort: { uploadedAt: -1 }
|
||||||
fields: {
|
|
||||||
name: 1,
|
|
||||||
description: 1,
|
|
||||||
size: 1,
|
|
||||||
type: 1,
|
|
||||||
uploadedAt: 1,
|
|
||||||
url: 1,
|
|
||||||
userId: 1
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getMessages(roomId, type, query, offset) {
|
getMessages(roomId, type, query, offset) {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { NavigatorScreenParams } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { IRoom } from './definitions/IRoom';
|
||||||
|
import { IServer } from './definitions/IServer';
|
||||||
|
import { IAttachment } from './definitions/IAttachment';
|
||||||
|
import { MasterDetailInsideStackParamList } from './stacks/MasterDetailStack/types';
|
||||||
|
import { OutsideParamList, InsideStackParamList } from './stacks/types';
|
||||||
|
|
||||||
|
export type SetUsernameStackParamList = {
|
||||||
|
SetUsernameView: {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StackParamList = {
|
||||||
|
AuthLoading: undefined;
|
||||||
|
OutsideStack: NavigatorScreenParams<OutsideParamList>;
|
||||||
|
InsideStack: NavigatorScreenParams<InsideStackParamList>;
|
||||||
|
MasterDetailStack: NavigatorScreenParams<MasterDetailInsideStackParamList>;
|
||||||
|
SetUsernameStack: NavigatorScreenParams<SetUsernameStackParamList>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShareInsideStackParamList = {
|
||||||
|
ShareListView: undefined;
|
||||||
|
ShareView: {
|
||||||
|
attachments: IAttachment[];
|
||||||
|
isShareView?: boolean;
|
||||||
|
isShareExtension: boolean;
|
||||||
|
serverInfo: IServer;
|
||||||
|
text: string;
|
||||||
|
room: IRoom;
|
||||||
|
thread: any; // TODO: Change
|
||||||
|
};
|
||||||
|
SelectServerView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShareOutsideStackParamList = {
|
||||||
|
WithoutServersView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ShareAppStackParamList = {
|
||||||
|
AuthLoading?: undefined;
|
||||||
|
OutsideStack?: NavigatorScreenParams<ShareOutsideStackParamList>;
|
||||||
|
InsideStack?: NavigatorScreenParams<ShareInsideStackParamList>;
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, View } from 'react-native';
|
import { Text, View, ViewStyle } from 'react-native';
|
||||||
|
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
|
@ -10,7 +10,7 @@ import { themes } from '../../constants/colors';
|
||||||
export { ROW_HEIGHT };
|
export { ROW_HEIGHT };
|
||||||
|
|
||||||
interface IDirectoryItemLabel {
|
interface IDirectoryItemLabel {
|
||||||
text: string;
|
text?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ interface IDirectoryItem {
|
||||||
type: string;
|
type: string;
|
||||||
onPress(): void;
|
onPress(): void;
|
||||||
testID: string;
|
testID: string;
|
||||||
style: any;
|
style?: ViewStyle;
|
||||||
rightLabel: string;
|
rightLabel?: string;
|
||||||
rid: string;
|
rid?: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
teamMain?: boolean;
|
teamMain?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ const DirectoryItemLabel = React.memo(({ text, theme }: IDirectoryItemLabel) =>
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Text style={[styles.directoryItemLabel, { color: themes[theme!].auxiliaryText }]}>{text}</Text>;
|
return <Text style={[styles.directoryItemLabel, { color: themes[theme].auxiliaryText }]}>{text}</Text>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const DirectoryItem = ({
|
const DirectoryItem = ({
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { KeyboardAwareScrollView, KeyboardAwareScrollViewProps } from '@codler/r
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
|
|
||||||
interface IKeyboardViewProps extends KeyboardAwareScrollViewProps {
|
interface IKeyboardViewProps extends KeyboardAwareScrollViewProps {
|
||||||
keyboardVerticalOffset: number;
|
keyboardVerticalOffset?: number;
|
||||||
scrollEnabled?: boolean;
|
scrollEnabled?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ interface IUserItem {
|
||||||
testID: string;
|
testID: string;
|
||||||
onLongPress?: () => void;
|
onLongPress?: () => void;
|
||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
icon: string;
|
icon?: string | null;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { setCurrentScreen } from './utils/log';
|
||||||
import AuthLoadingView from './views/AuthLoadingView';
|
import AuthLoadingView from './views/AuthLoadingView';
|
||||||
import { DimensionsContext } from './dimensions';
|
import { DimensionsContext } from './dimensions';
|
||||||
import debounce from './utils/debounce';
|
import debounce from './utils/debounce';
|
||||||
|
import { ShareInsideStackParamList, ShareOutsideStackParamList, ShareAppStackParamList } from './navigationTypes';
|
||||||
|
|
||||||
interface IDimensions {
|
interface IDimensions {
|
||||||
width: number;
|
width: number;
|
||||||
|
@ -46,7 +47,7 @@ interface IState {
|
||||||
fontScale: number;
|
fontScale: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Inside = createStackNavigator();
|
const Inside = createStackNavigator<ShareInsideStackParamList>();
|
||||||
const InsideStack = () => {
|
const InsideStack = () => {
|
||||||
const { theme } = useContext(ThemeContext);
|
const { theme } = useContext(ThemeContext);
|
||||||
|
|
||||||
|
@ -65,24 +66,19 @@ const InsideStack = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Outside = createStackNavigator();
|
const Outside = createStackNavigator<ShareOutsideStackParamList>();
|
||||||
const OutsideStack = () => {
|
const OutsideStack = () => {
|
||||||
const { theme } = useContext(ThemeContext);
|
const { theme } = useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Outside.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme) }}>
|
<Outside.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme) }}>
|
||||||
<Outside.Screen
|
<Outside.Screen name='WithoutServersView' component={WithoutServersView} options={WithoutServersView.navigationOptions} />
|
||||||
name='WithoutServersView'
|
|
||||||
component={WithoutServersView}
|
|
||||||
/* @ts-ignore*/
|
|
||||||
options={WithoutServersView.navigationOptions}
|
|
||||||
/>
|
|
||||||
</Outside.Navigator>
|
</Outside.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// App
|
// App
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator<ShareAppStackParamList>();
|
||||||
export const App = ({ root }: any) => (
|
export const App = ({ root }: any) => (
|
||||||
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
||||||
<>
|
<>
|
||||||
|
@ -112,7 +108,7 @@ class Root extends React.Component<{}, IState> {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount(): void {
|
||||||
RocketChat.closeShareExtension();
|
RocketChat.closeShareExtension();
|
||||||
unsubscribeTheme();
|
unsubscribeTheme();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { I18nManager } from 'react-native';
|
import { I18nManager } from 'react-native';
|
||||||
import { createStackNavigator } from '@react-navigation/stack';
|
import { createStackNavigator, StackNavigationOptions } from '@react-navigation/stack';
|
||||||
import { createDrawerNavigator } from '@react-navigation/drawer';
|
import { createDrawerNavigator } from '@react-navigation/drawer';
|
||||||
|
|
||||||
import { ThemeContext } from '../theme';
|
import { ThemeContext } from '../theme';
|
||||||
import { ModalAnimation, StackAnimation, defaultHeader, themedHeader } from '../utils/navigation';
|
import { ModalAnimation, StackAnimation, defaultHeader, themedHeader } from '../utils/navigation';
|
||||||
import Sidebar from '../views/SidebarView';
|
import Sidebar from '../views/SidebarView';
|
||||||
|
|
||||||
// Chats Stack
|
// Chats Stack
|
||||||
import RoomView from '../views/RoomView';
|
import RoomView from '../views/RoomView';
|
||||||
import RoomsListView from '../views/RoomsListView';
|
import RoomsListView from '../views/RoomsListView';
|
||||||
|
@ -22,7 +21,6 @@ import MessagesView from '../views/MessagesView';
|
||||||
import AutoTranslateView from '../views/AutoTranslateView';
|
import AutoTranslateView from '../views/AutoTranslateView';
|
||||||
import DirectoryView from '../views/DirectoryView';
|
import DirectoryView from '../views/DirectoryView';
|
||||||
import NotificationPrefView from '../views/NotificationPreferencesView';
|
import NotificationPrefView from '../views/NotificationPreferencesView';
|
||||||
import VisitorNavigationView from '../views/VisitorNavigationView';
|
|
||||||
import ForwardLivechatView from '../views/ForwardLivechatView';
|
import ForwardLivechatView from '../views/ForwardLivechatView';
|
||||||
import LivechatEditView from '../views/LivechatEditView';
|
import LivechatEditView from '../views/LivechatEditView';
|
||||||
import PickerView from '../views/PickerView';
|
import PickerView from '../views/PickerView';
|
||||||
|
@ -37,10 +35,8 @@ import { themes } from '../constants/colors';
|
||||||
import ProfileView from '../views/ProfileView';
|
import ProfileView from '../views/ProfileView';
|
||||||
import UserPreferencesView from '../views/UserPreferencesView';
|
import UserPreferencesView from '../views/UserPreferencesView';
|
||||||
import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
|
import UserNotificationPrefView from '../views/UserNotificationPreferencesView';
|
||||||
|
|
||||||
// Display Preferences View
|
// Display Preferences View
|
||||||
import DisplayPrefsView from '../views/DisplayPrefsView';
|
import DisplayPrefsView from '../views/DisplayPrefsView';
|
||||||
|
|
||||||
// Settings Stack
|
// Settings Stack
|
||||||
import SettingsView from '../views/SettingsView';
|
import SettingsView from '../views/SettingsView';
|
||||||
import SecurityPrivacyView from '../views/SecurityPrivacyView';
|
import SecurityPrivacyView from '../views/SecurityPrivacyView';
|
||||||
|
@ -49,21 +45,16 @@ import LanguageView from '../views/LanguageView';
|
||||||
import ThemeView from '../views/ThemeView';
|
import ThemeView from '../views/ThemeView';
|
||||||
import DefaultBrowserView from '../views/DefaultBrowserView';
|
import DefaultBrowserView from '../views/DefaultBrowserView';
|
||||||
import ScreenLockConfigView from '../views/ScreenLockConfigView';
|
import ScreenLockConfigView from '../views/ScreenLockConfigView';
|
||||||
|
|
||||||
// Admin Stack
|
// Admin Stack
|
||||||
import AdminPanelView from '../views/AdminPanelView';
|
import AdminPanelView from '../views/AdminPanelView';
|
||||||
|
|
||||||
// NewMessage Stack
|
// NewMessage Stack
|
||||||
import NewMessageView from '../views/NewMessageView';
|
import NewMessageView from '../views/NewMessageView';
|
||||||
import CreateChannelView from '../views/CreateChannelView';
|
import CreateChannelView from '../views/CreateChannelView';
|
||||||
|
|
||||||
// E2ESaveYourPassword Stack
|
// E2ESaveYourPassword Stack
|
||||||
import E2ESaveYourPasswordView from '../views/E2ESaveYourPasswordView';
|
import E2ESaveYourPasswordView from '../views/E2ESaveYourPasswordView';
|
||||||
import E2EHowItWorksView from '../views/E2EHowItWorksView';
|
import E2EHowItWorksView from '../views/E2EHowItWorksView';
|
||||||
|
|
||||||
// E2EEnterYourPassword Stack
|
// E2EEnterYourPassword Stack
|
||||||
import E2EEnterYourPasswordView from '../views/E2EEnterYourPasswordView';
|
import E2EEnterYourPasswordView from '../views/E2EEnterYourPasswordView';
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
import AttachmentView from '../views/AttachmentView';
|
import AttachmentView from '../views/AttachmentView';
|
||||||
import ModalBlockView from '../views/ModalBlockView';
|
import ModalBlockView from '../views/ModalBlockView';
|
||||||
|
@ -75,20 +66,33 @@ import QueueListView from '../ee/omnichannel/views/QueueListView';
|
||||||
import AddChannelTeamView from '../views/AddChannelTeamView';
|
import AddChannelTeamView from '../views/AddChannelTeamView';
|
||||||
import AddExistingChannelView from '../views/AddExistingChannelView';
|
import AddExistingChannelView from '../views/AddExistingChannelView';
|
||||||
import SelectListView from '../views/SelectListView';
|
import SelectListView from '../views/SelectListView';
|
||||||
|
import {
|
||||||
|
AdminPanelStackParamList,
|
||||||
|
ChatsStackParamList,
|
||||||
|
DisplayPrefStackParamList,
|
||||||
|
DrawerParamList,
|
||||||
|
E2EEnterYourPasswordStackParamList,
|
||||||
|
E2ESaveYourPasswordStackParamList,
|
||||||
|
InsideStackParamList,
|
||||||
|
NewMessageStackParamList,
|
||||||
|
ProfileStackParamList,
|
||||||
|
SettingsStackParamList
|
||||||
|
} from './types';
|
||||||
|
|
||||||
// ChatsStackNavigator
|
// ChatsStackNavigator
|
||||||
const ChatsStack = createStackNavigator();
|
const ChatsStack = createStackNavigator<ChatsStackParamList>();
|
||||||
const ChatsStackNavigator = () => {
|
const ChatsStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<ChatsStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<ChatsStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<ChatsStack.Screen name='RoomsListView' component={RoomsListView} />
|
<ChatsStack.Screen name='RoomsListView' component={RoomsListView} />
|
||||||
<ChatsStack.Screen name='RoomView' component={RoomView} />
|
<ChatsStack.Screen name='RoomView' component={RoomView} />
|
||||||
<ChatsStack.Screen name='RoomActionsView' component={RoomActionsView} options={RoomActionsView.navigationOptions} />
|
<ChatsStack.Screen name='RoomActionsView' component={RoomActionsView} options={RoomActionsView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='SelectListView' component={SelectListView} options={SelectListView.navigationOptions} />
|
<ChatsStack.Screen name='SelectListView' component={SelectListView} options={SelectListView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='RoomInfoView' component={RoomInfoView} options={RoomInfoView.navigationOptions} />
|
<ChatsStack.Screen name='RoomInfoView' component={RoomInfoView} options={RoomInfoView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='RoomInfoEditView' component={RoomInfoEditView} options={RoomInfoEditView.navigationOptions} />
|
<ChatsStack.Screen name='RoomInfoEditView' component={RoomInfoEditView} options={RoomInfoEditView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='RoomMembersView' component={RoomMembersView} options={RoomMembersView.navigationOptions} />
|
<ChatsStack.Screen name='RoomMembersView' component={RoomMembersView} />
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen
|
||||||
name='SearchMessagesView'
|
name='SearchMessagesView'
|
||||||
component={SearchMessagesView}
|
component={SearchMessagesView}
|
||||||
|
@ -109,11 +113,6 @@ const ChatsStackNavigator = () => {
|
||||||
component={NotificationPrefView}
|
component={NotificationPrefView}
|
||||||
options={NotificationPrefView.navigationOptions}
|
options={NotificationPrefView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ChatsStack.Screen
|
|
||||||
name='VisitorNavigationView'
|
|
||||||
component={VisitorNavigationView}
|
|
||||||
options={VisitorNavigationView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen
|
||||||
name='ForwardLivechatView'
|
name='ForwardLivechatView'
|
||||||
component={ForwardLivechatView}
|
component={ForwardLivechatView}
|
||||||
|
@ -126,13 +125,9 @@ const ChatsStackNavigator = () => {
|
||||||
component={ThreadMessagesView}
|
component={ThreadMessagesView}
|
||||||
options={ThreadMessagesView.navigationOptions}
|
options={ThreadMessagesView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ChatsStack.Screen name='TeamChannelsView' component={TeamChannelsView} options={TeamChannelsView.navigationOptions} />
|
<ChatsStack.Screen name='TeamChannelsView' component={TeamChannelsView} />
|
||||||
<ChatsStack.Screen name='CreateChannelView' component={CreateChannelView} options={CreateChannelView.navigationOptions} />
|
<ChatsStack.Screen name='CreateChannelView' component={CreateChannelView} options={CreateChannelView.navigationOptions} />
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen name='AddChannelTeamView' component={AddChannelTeamView} />
|
||||||
name='AddChannelTeamView'
|
|
||||||
component={AddChannelTeamView}
|
|
||||||
options={AddChannelTeamView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen
|
||||||
name='AddExistingChannelView'
|
name='AddExistingChannelView'
|
||||||
component={AddExistingChannelView}
|
component={AddExistingChannelView}
|
||||||
|
@ -141,32 +136,21 @@ const ChatsStackNavigator = () => {
|
||||||
<ChatsStack.Screen name='MarkdownTableView' component={MarkdownTableView} options={MarkdownTableView.navigationOptions} />
|
<ChatsStack.Screen name='MarkdownTableView' component={MarkdownTableView} options={MarkdownTableView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='ReadReceiptsView' component={ReadReceiptsView} options={ReadReceiptsView.navigationOptions} />
|
<ChatsStack.Screen name='ReadReceiptsView' component={ReadReceiptsView} options={ReadReceiptsView.navigationOptions} />
|
||||||
<ChatsStack.Screen name='QueueListView' component={QueueListView} options={QueueListView.navigationOptions} />
|
<ChatsStack.Screen name='QueueListView' component={QueueListView} options={QueueListView.navigationOptions} />
|
||||||
<ChatsStack.Screen
|
<ChatsStack.Screen name='CannedResponsesListView' component={CannedResponsesListView} />
|
||||||
name='CannedResponsesListView'
|
<ChatsStack.Screen name='CannedResponseDetail' component={CannedResponseDetail} />
|
||||||
component={CannedResponsesListView}
|
|
||||||
options={CannedResponsesListView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ChatsStack.Screen
|
|
||||||
name='CannedResponseDetail'
|
|
||||||
component={CannedResponseDetail}
|
|
||||||
options={CannedResponseDetail.navigationOptions}
|
|
||||||
/>
|
|
||||||
</ChatsStack.Navigator>
|
</ChatsStack.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ProfileStackNavigator
|
// ProfileStackNavigator
|
||||||
const ProfileStack = createStackNavigator();
|
const ProfileStack = createStackNavigator<ProfileStackParamList>();
|
||||||
const ProfileStackNavigator = () => {
|
const ProfileStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<ProfileStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<ProfileStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<ProfileStack.Screen name='ProfileView' component={ProfileView} options={ProfileView.navigationOptions} />
|
<ProfileStack.Screen name='ProfileView' component={ProfileView} options={ProfileView.navigationOptions} />
|
||||||
<ProfileStack.Screen
|
<ProfileStack.Screen name='UserPreferencesView' component={UserPreferencesView} />
|
||||||
name='UserPreferencesView'
|
|
||||||
component={UserPreferencesView}
|
|
||||||
options={UserPreferencesView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ProfileStack.Screen
|
<ProfileStack.Screen
|
||||||
name='UserNotificationPrefView'
|
name='UserNotificationPrefView'
|
||||||
component={UserNotificationPrefView}
|
component={UserNotificationPrefView}
|
||||||
|
@ -178,18 +162,15 @@ const ProfileStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// SettingsStackNavigator
|
// SettingsStackNavigator
|
||||||
const SettingsStack = createStackNavigator();
|
const SettingsStack = createStackNavigator<SettingsStackParamList>();
|
||||||
const SettingsStackNavigator = () => {
|
const SettingsStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<SettingsStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<SettingsStack.Screen name='SettingsView' component={SettingsView} options={SettingsView.navigationOptions} />
|
<SettingsStack.Screen name='SettingsView' component={SettingsView} options={SettingsView.navigationOptions} />
|
||||||
<SettingsStack.Screen
|
<SettingsStack.Screen name='SecurityPrivacyView' component={SecurityPrivacyView} />
|
||||||
name='SecurityPrivacyView'
|
|
||||||
component={SecurityPrivacyView}
|
|
||||||
options={SecurityPrivacyView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<SettingsStack.Screen
|
<SettingsStack.Screen
|
||||||
name='E2EEncryptionSecurityView'
|
name='E2EEncryptionSecurityView'
|
||||||
component={E2EEncryptionSecurityView}
|
component={E2EEncryptionSecurityView}
|
||||||
|
@ -212,31 +193,33 @@ const SettingsStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// AdminPanelStackNavigator
|
// AdminPanelStackNavigator
|
||||||
const AdminPanelStack = createStackNavigator();
|
const AdminPanelStack = createStackNavigator<AdminPanelStackParamList>();
|
||||||
const AdminPanelStackNavigator = () => {
|
const AdminPanelStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdminPanelStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<AdminPanelStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<AdminPanelStack.Screen name='AdminPanelView' component={AdminPanelView} options={AdminPanelView.navigationOptions} />
|
<AdminPanelStack.Screen name='AdminPanelView' component={AdminPanelView} options={AdminPanelView.navigationOptions} />
|
||||||
</AdminPanelStack.Navigator>
|
</AdminPanelStack.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// DisplayPreferenceNavigator
|
// DisplayPreferenceNavigator
|
||||||
const DisplayPrefStack = createStackNavigator();
|
const DisplayPrefStack = createStackNavigator<DisplayPrefStackParamList>();
|
||||||
const DisplayPrefStackNavigator = () => {
|
const DisplayPrefStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DisplayPrefStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<DisplayPrefStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<DisplayPrefStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
|
<DisplayPrefStack.Screen name='DisplayPrefsView' component={DisplayPrefsView} />
|
||||||
</DisplayPrefStack.Navigator>
|
</DisplayPrefStack.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// DrawerNavigator
|
// DrawerNavigator
|
||||||
const Drawer = createDrawerNavigator();
|
const Drawer = createDrawerNavigator<DrawerParamList>();
|
||||||
const DrawerNavigator = () => {
|
const DrawerNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
|
@ -257,12 +240,13 @@ const DrawerNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// NewMessageStackNavigator
|
// NewMessageStackNavigator
|
||||||
const NewMessageStack = createStackNavigator();
|
const NewMessageStack = createStackNavigator<NewMessageStackParamList>();
|
||||||
const NewMessageStackNavigator = () => {
|
const NewMessageStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NewMessageStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<NewMessageStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<NewMessageStack.Screen name='NewMessageView' component={NewMessageView} options={NewMessageView.navigationOptions} />
|
<NewMessageStack.Screen name='NewMessageView' component={NewMessageView} options={NewMessageView.navigationOptions} />
|
||||||
<NewMessageStack.Screen name='SelectedUsersViewCreateChannel' component={SelectedUsersView} />
|
<NewMessageStack.Screen name='SelectedUsersViewCreateChannel' component={SelectedUsersView} />
|
||||||
<NewMessageStack.Screen
|
<NewMessageStack.Screen
|
||||||
|
@ -276,12 +260,13 @@ const NewMessageStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// E2ESaveYourPasswordStackNavigator
|
// E2ESaveYourPasswordStackNavigator
|
||||||
const E2ESaveYourPasswordStack = createStackNavigator();
|
const E2ESaveYourPasswordStack = createStackNavigator<E2ESaveYourPasswordStackParamList>();
|
||||||
const E2ESaveYourPasswordStackNavigator = () => {
|
const E2ESaveYourPasswordStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<E2ESaveYourPasswordStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<E2ESaveYourPasswordStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<E2ESaveYourPasswordStack.Screen
|
<E2ESaveYourPasswordStack.Screen
|
||||||
name='E2ESaveYourPasswordView'
|
name='E2ESaveYourPasswordView'
|
||||||
component={E2ESaveYourPasswordView}
|
component={E2ESaveYourPasswordView}
|
||||||
|
@ -297,12 +282,13 @@ const E2ESaveYourPasswordStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// E2EEnterYourPasswordStackNavigator
|
// E2EEnterYourPasswordStackNavigator
|
||||||
const E2EEnterYourPasswordStack = createStackNavigator();
|
const E2EEnterYourPasswordStack = createStackNavigator<E2EEnterYourPasswordStackParamList>();
|
||||||
const E2EEnterYourPasswordStackNavigator = () => {
|
const E2EEnterYourPasswordStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<E2EEnterYourPasswordStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<E2EEnterYourPasswordStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<E2EEnterYourPasswordStack.Screen
|
<E2EEnterYourPasswordStack.Screen
|
||||||
name='E2EEnterYourPasswordView'
|
name='E2EEnterYourPasswordView'
|
||||||
component={E2EEnterYourPasswordView}
|
component={E2EEnterYourPasswordView}
|
||||||
|
@ -313,7 +299,7 @@ const E2EEnterYourPasswordStackNavigator = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
const InsideStack = createStackNavigator();
|
const InsideStack = createStackNavigator<InsideStackParamList>();
|
||||||
const InsideStackNavigator = () => {
|
const InsideStackNavigator = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
|
import { StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { NavigationContainerProps } from '@react-navigation/core';
|
||||||
|
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
|
|
||||||
|
interface IModalContainer extends NavigationContainerProps {
|
||||||
|
navigation: StackNavigationProp<any>;
|
||||||
|
children: React.ReactNode;
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
root: {
|
root: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -12,11 +19,11 @@ const styles = StyleSheet.create({
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
},
|
},
|
||||||
backdrop: {
|
backdrop: {
|
||||||
...StyleSheet.absoluteFill
|
...StyleSheet.absoluteFillObject
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ModalContainer = ({ navigation, children, theme }) => (
|
export const ModalContainer = ({ navigation, children, theme }: IModalContainer): JSX.Element => (
|
||||||
<View style={[styles.root, { backgroundColor: `${themes[theme].backdropColor}70` }]}>
|
<View style={[styles.root, { backgroundColor: `${themes[theme].backdropColor}70` }]}>
|
||||||
<TouchableWithoutFeedback onPress={() => navigation.pop()}>
|
<TouchableWithoutFeedback onPress={() => navigation.pop()}>
|
||||||
<View style={styles.backdrop} />
|
<View style={styles.backdrop} />
|
||||||
|
@ -24,9 +31,3 @@ export const ModalContainer = ({ navigation, children, theme }) => (
|
||||||
<View style={sharedStyles.modalFormSheet}>{children}</View>
|
<View style={sharedStyles.modalFormSheet}>{children}</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
ModalContainer.propTypes = {
|
|
||||||
navigation: PropTypes.object,
|
|
||||||
children: PropTypes.element,
|
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
|
@ -1,12 +1,10 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useIsFocused } from '@react-navigation/native';
|
import { useIsFocused } from '@react-navigation/native';
|
||||||
import { createStackNavigator } from '@react-navigation/stack';
|
import { createStackNavigator, StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { createDrawerNavigator } from '@react-navigation/drawer';
|
import { createDrawerNavigator } from '@react-navigation/drawer';
|
||||||
|
|
||||||
import { ThemeContext } from '../../theme';
|
import { ThemeContext } from '../../theme';
|
||||||
import { FadeFromCenterModal, StackAnimation, defaultHeader, themedHeader } from '../../utils/navigation';
|
import { FadeFromCenterModal, StackAnimation, defaultHeader, themedHeader } from '../../utils/navigation';
|
||||||
|
|
||||||
// Chats Stack
|
// Chats Stack
|
||||||
import RoomView from '../../views/RoomView';
|
import RoomView from '../../views/RoomView';
|
||||||
import RoomsListView from '../../views/RoomsListView';
|
import RoomsListView from '../../views/RoomsListView';
|
||||||
|
@ -22,7 +20,6 @@ import MessagesView from '../../views/MessagesView';
|
||||||
import AutoTranslateView from '../../views/AutoTranslateView';
|
import AutoTranslateView from '../../views/AutoTranslateView';
|
||||||
import DirectoryView from '../../views/DirectoryView';
|
import DirectoryView from '../../views/DirectoryView';
|
||||||
import NotificationPrefView from '../../views/NotificationPreferencesView';
|
import NotificationPrefView from '../../views/NotificationPreferencesView';
|
||||||
import VisitorNavigationView from '../../views/VisitorNavigationView';
|
|
||||||
import ForwardLivechatView from '../../views/ForwardLivechatView';
|
import ForwardLivechatView from '../../views/ForwardLivechatView';
|
||||||
import CannedResponsesListView from '../../views/CannedResponsesListView';
|
import CannedResponsesListView from '../../views/CannedResponsesListView';
|
||||||
import CannedResponseDetail from '../../views/CannedResponseDetail';
|
import CannedResponseDetail from '../../views/CannedResponseDetail';
|
||||||
|
@ -46,7 +43,6 @@ import UserPreferencesView from '../../views/UserPreferencesView';
|
||||||
import UserNotificationPrefView from '../../views/UserNotificationPreferencesView';
|
import UserNotificationPrefView from '../../views/UserNotificationPreferencesView';
|
||||||
import SecurityPrivacyView from '../../views/SecurityPrivacyView';
|
import SecurityPrivacyView from '../../views/SecurityPrivacyView';
|
||||||
import E2EEncryptionSecurityView from '../../views/E2EEncryptionSecurityView';
|
import E2EEncryptionSecurityView from '../../views/E2EEncryptionSecurityView';
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
import AttachmentView from '../../views/AttachmentView';
|
import AttachmentView from '../../views/AttachmentView';
|
||||||
import ModalBlockView from '../../views/ModalBlockView';
|
import ModalBlockView from '../../views/ModalBlockView';
|
||||||
|
@ -63,9 +59,15 @@ import AddChannelTeamView from '../../views/AddChannelTeamView';
|
||||||
import AddExistingChannelView from '../../views/AddExistingChannelView';
|
import AddExistingChannelView from '../../views/AddExistingChannelView';
|
||||||
import SelectListView from '../../views/SelectListView';
|
import SelectListView from '../../views/SelectListView';
|
||||||
import { ModalContainer } from './ModalContainer';
|
import { ModalContainer } from './ModalContainer';
|
||||||
|
import {
|
||||||
|
MasterDetailChatsStackParamList,
|
||||||
|
MasterDetailDrawerParamList,
|
||||||
|
MasterDetailInsideStackParamList,
|
||||||
|
ModalStackParamList
|
||||||
|
} from './types';
|
||||||
|
|
||||||
// ChatsStackNavigator
|
// ChatsStackNavigator
|
||||||
const ChatsStack = createStackNavigator();
|
const ChatsStack = createStackNavigator<MasterDetailChatsStackParamList>();
|
||||||
const ChatsStackNavigator = React.memo(() => {
|
const ChatsStackNavigator = React.memo(() => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
|
@ -82,28 +84,35 @@ const ChatsStackNavigator = React.memo(() => {
|
||||||
}, [isFocused]);
|
}, [isFocused]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatsStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<ChatsStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<ChatsStack.Screen name='RoomView' component={RoomView} options={{ headerShown: false }} />
|
<ChatsStack.Screen name='RoomView' component={RoomView} options={{ headerShown: false }} />
|
||||||
</ChatsStack.Navigator>
|
</ChatsStack.Navigator>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// DrawerNavigator
|
// DrawerNavigator
|
||||||
const Drawer = createDrawerNavigator();
|
const Drawer = createDrawerNavigator<MasterDetailDrawerParamList>();
|
||||||
const DrawerNavigator = React.memo(() => (
|
const DrawerNavigator = React.memo(() => (
|
||||||
<Drawer.Navigator
|
<Drawer.Navigator
|
||||||
|
// @ts-ignore
|
||||||
drawerContent={({ navigation, state }) => <RoomsListView navigation={navigation} state={state} />}
|
drawerContent={({ navigation, state }) => <RoomsListView navigation={navigation} state={state} />}
|
||||||
drawerType='permanent'>
|
drawerType='permanent'>
|
||||||
<Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} />
|
<Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} />
|
||||||
</Drawer.Navigator>
|
</Drawer.Navigator>
|
||||||
));
|
));
|
||||||
|
|
||||||
const ModalStack = createStackNavigator();
|
export interface INavigation {
|
||||||
const ModalStackNavigator = React.memo(({ navigation }) => {
|
navigation: StackNavigationProp<ModalStackParamList>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModalStack = createStackNavigator<ModalStackParamList>();
|
||||||
|
const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<ModalContainer navigation={navigation} theme={theme}>
|
<ModalContainer navigation={navigation} theme={theme}>
|
||||||
<ModalStack.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<ModalStack.Navigator
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='RoomActionsView'
|
name='RoomActionsView'
|
||||||
component={RoomActionsView}
|
component={RoomActionsView}
|
||||||
|
@ -120,11 +129,7 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
||||||
/>
|
/>
|
||||||
<ModalStack.Screen name='SelectedUsersView' component={SelectedUsersView} />
|
<ModalStack.Screen name='SelectedUsersView' component={SelectedUsersView} />
|
||||||
<ModalStack.Screen name='InviteUsersView' component={InviteUsersView} options={InviteUsersView.navigationOptions} />
|
<ModalStack.Screen name='InviteUsersView' component={InviteUsersView} options={InviteUsersView.navigationOptions} />
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen name='AddChannelTeamView' component={AddChannelTeamView} />
|
||||||
name='AddChannelTeamView'
|
|
||||||
component={AddChannelTeamView}
|
|
||||||
options={AddChannelTeamView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='AddExistingChannelView'
|
name='AddExistingChannelView'
|
||||||
component={AddExistingChannelView}
|
component={AddExistingChannelView}
|
||||||
|
@ -152,26 +157,13 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
||||||
component={NotificationPrefView}
|
component={NotificationPrefView}
|
||||||
options={NotificationPrefView.navigationOptions}
|
options={NotificationPrefView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ModalStack.Screen
|
|
||||||
name='VisitorNavigationView'
|
|
||||||
component={VisitorNavigationView}
|
|
||||||
options={VisitorNavigationView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='ForwardLivechatView'
|
name='ForwardLivechatView'
|
||||||
component={ForwardLivechatView}
|
component={ForwardLivechatView}
|
||||||
options={ForwardLivechatView.navigationOptions}
|
options={ForwardLivechatView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen name='CannedResponsesListView' component={CannedResponsesListView} />
|
||||||
name='CannedResponsesListView'
|
<ModalStack.Screen name='CannedResponseDetail' component={CannedResponseDetail} />
|
||||||
component={CannedResponsesListView}
|
|
||||||
options={CannedResponsesListView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen
|
|
||||||
name='CannedResponseDetail'
|
|
||||||
component={CannedResponseDetail}
|
|
||||||
options={CannedResponseDetail.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen name='LivechatEditView' component={LivechatEditView} options={LivechatEditView.navigationOptions} />
|
<ModalStack.Screen name='LivechatEditView' component={LivechatEditView} options={LivechatEditView.navigationOptions} />
|
||||||
<ModalStack.Screen name='PickerView' component={PickerView} options={PickerView.navigationOptions} />
|
<ModalStack.Screen name='PickerView' component={PickerView} options={PickerView.navigationOptions} />
|
||||||
<ModalStack.Screen name='ThreadMessagesView' component={ThreadMessagesView} />
|
<ModalStack.Screen name='ThreadMessagesView' component={ThreadMessagesView} />
|
||||||
|
@ -226,21 +218,13 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
||||||
component={E2EEnterYourPasswordView}
|
component={E2EEnterYourPasswordView}
|
||||||
options={E2EEnterYourPasswordView.navigationOptions}
|
options={E2EEnterYourPasswordView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen name='UserPreferencesView' component={UserPreferencesView} />
|
||||||
name='UserPreferencesView'
|
|
||||||
component={UserPreferencesView}
|
|
||||||
options={UserPreferencesView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='UserNotificationPrefView'
|
name='UserNotificationPrefView'
|
||||||
component={UserNotificationPrefView}
|
component={UserNotificationPrefView}
|
||||||
options={UserNotificationPrefView.navigationOptions}
|
options={UserNotificationPrefView.navigationOptions}
|
||||||
/>
|
/>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen name='SecurityPrivacyView' component={SecurityPrivacyView} />
|
||||||
name='SecurityPrivacyView'
|
|
||||||
component={SecurityPrivacyView}
|
|
||||||
options={SecurityPrivacyView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name='E2EEncryptionSecurityView'
|
name='E2EEncryptionSecurityView'
|
||||||
component={E2EEncryptionSecurityView}
|
component={E2EEncryptionSecurityView}
|
||||||
|
@ -251,16 +235,14 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
ModalStackNavigator.propTypes = {
|
|
||||||
navigation: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
// InsideStackNavigator
|
// InsideStackNavigator
|
||||||
const InsideStack = createStackNavigator();
|
const InsideStack = createStackNavigator<MasterDetailInsideStackParamList>();
|
||||||
const InsideStackNavigator = React.memo(() => {
|
const InsideStackNavigator = React.memo(() => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
return (
|
return (
|
||||||
<InsideStack.Navigator mode='modal' screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...FadeFromCenterModal }}>
|
<InsideStack.Navigator
|
||||||
|
mode='modal'
|
||||||
|
screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...FadeFromCenterModal } as StackNavigationOptions}>
|
||||||
<InsideStack.Screen name='DrawerNavigator' component={DrawerNavigator} options={{ headerShown: false }} />
|
<InsideStack.Screen name='DrawerNavigator' component={DrawerNavigator} options={{ headerShown: false }} />
|
||||||
<InsideStack.Screen name='ModalStackNavigator' component={ModalStackNavigator} options={{ headerShown: false }} />
|
<InsideStack.Screen name='ModalStackNavigator' component={ModalStackNavigator} options={{ headerShown: false }} />
|
||||||
<InsideStack.Screen name='AttachmentView' component={AttachmentView} />
|
<InsideStack.Screen name='AttachmentView' component={AttachmentView} />
|
|
@ -0,0 +1,200 @@
|
||||||
|
import { TextInputProps } from 'react-native';
|
||||||
|
import { NavigatorScreenParams } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { IAttachment } from '../../definitions/IAttachment';
|
||||||
|
import { IMessage } from '../../definitions/IMessage';
|
||||||
|
import { IRoom, RoomType } from '../../definitions/IRoom';
|
||||||
|
|
||||||
|
export type MasterDetailChatsStackParamList = {
|
||||||
|
RoomView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
tmid?: string;
|
||||||
|
message?: string;
|
||||||
|
name?: string;
|
||||||
|
fname?: string;
|
||||||
|
prid?: string;
|
||||||
|
room: IRoom;
|
||||||
|
jumpToMessageId?: string;
|
||||||
|
jumpToThreadId?: string;
|
||||||
|
roomUserId?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MasterDetailDrawerParamList = {
|
||||||
|
ChatsStackNavigator: NavigatorScreenParams<MasterDetailChatsStackParamList>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ModalStackParamList = {
|
||||||
|
RoomActionsView: {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
joined: boolean;
|
||||||
|
};
|
||||||
|
RoomInfoView: {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
};
|
||||||
|
SelectListView: {
|
||||||
|
data: any;
|
||||||
|
title: string;
|
||||||
|
infoText: string;
|
||||||
|
nextAction: Function;
|
||||||
|
showAlert: boolean;
|
||||||
|
isSearch: boolean;
|
||||||
|
onSearch: Function;
|
||||||
|
isRadio?: boolean;
|
||||||
|
};
|
||||||
|
RoomInfoEditView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
RoomMembersView: {
|
||||||
|
rid: string;
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
SearchMessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
encrypted?: boolean;
|
||||||
|
showCloseModal?: boolean;
|
||||||
|
};
|
||||||
|
SelectedUsersView: {
|
||||||
|
maxUsers: number;
|
||||||
|
showButton: boolean;
|
||||||
|
title: string;
|
||||||
|
buttonText: string;
|
||||||
|
nextAction: Function;
|
||||||
|
};
|
||||||
|
InviteUsersView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
AddChannelTeamView: {
|
||||||
|
teamId?: string;
|
||||||
|
teamChannels: []; // TODO: Change
|
||||||
|
};
|
||||||
|
AddExistingChannelView: {
|
||||||
|
teamId?: boolean;
|
||||||
|
};
|
||||||
|
InviteUsersEditView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
MessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
AutoTranslateView: {
|
||||||
|
rid: string;
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
DirectoryView: undefined;
|
||||||
|
QueueListView: undefined;
|
||||||
|
NotificationPrefView: {
|
||||||
|
rid: string;
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
ForwardLivechatView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
CannedResponsesListView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
CannedResponseDetail: {
|
||||||
|
cannedResponse: {
|
||||||
|
shortcut: string;
|
||||||
|
text: string;
|
||||||
|
scopeName: string;
|
||||||
|
tags: string[];
|
||||||
|
};
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
LivechatEditView: {
|
||||||
|
room: IRoom;
|
||||||
|
roomUser: any; // TODO: Change
|
||||||
|
};
|
||||||
|
PickerView: {
|
||||||
|
title: string;
|
||||||
|
data: []; // TODO: Change
|
||||||
|
value: any; // TODO: Change
|
||||||
|
onChangeText: TextInputProps['onChangeText'];
|
||||||
|
goBack: Function;
|
||||||
|
onChangeValue: Function;
|
||||||
|
};
|
||||||
|
ThreadMessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
};
|
||||||
|
TeamChannelsView: {
|
||||||
|
teamId: string;
|
||||||
|
};
|
||||||
|
MarkdownTableView: {
|
||||||
|
renderRows: Function;
|
||||||
|
tableWidth: number;
|
||||||
|
};
|
||||||
|
ReadReceiptsView: {
|
||||||
|
messageId: string;
|
||||||
|
};
|
||||||
|
SettingsView: undefined;
|
||||||
|
LanguageView: undefined;
|
||||||
|
ThemeView: undefined;
|
||||||
|
DefaultBrowserView: undefined;
|
||||||
|
ScreenLockConfigView: undefined;
|
||||||
|
StatusView: undefined;
|
||||||
|
ProfileView: undefined;
|
||||||
|
DisplayPrefsView: undefined;
|
||||||
|
AdminPanelView: undefined;
|
||||||
|
NewMessageView: undefined;
|
||||||
|
SelectedUsersViewCreateChannel: {
|
||||||
|
maxUsers: number;
|
||||||
|
showButton: boolean;
|
||||||
|
title: string;
|
||||||
|
buttonText: string;
|
||||||
|
nextAction: Function;
|
||||||
|
}; // TODO: Change
|
||||||
|
CreateChannelView: {
|
||||||
|
isTeam?: boolean; // TODO: To check
|
||||||
|
teamId?: string;
|
||||||
|
};
|
||||||
|
CreateDiscussionView: {
|
||||||
|
channel: IRoom;
|
||||||
|
message: IMessage;
|
||||||
|
showCloseModal: boolean;
|
||||||
|
};
|
||||||
|
E2ESaveYourPasswordView: undefined;
|
||||||
|
E2EHowItWorksView: {
|
||||||
|
showCloseModal: boolean;
|
||||||
|
};
|
||||||
|
E2EEnterYourPasswordView: undefined;
|
||||||
|
UserPreferencesView: undefined;
|
||||||
|
UserNotificationPrefView: undefined;
|
||||||
|
SecurityPrivacyView: undefined;
|
||||||
|
E2EEncryptionSecurityView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MasterDetailInsideStackParamList = {
|
||||||
|
DrawerNavigator: NavigatorScreenParams<Partial<MasterDetailDrawerParamList>>; // TODO: Change
|
||||||
|
ModalStackNavigator: NavigatorScreenParams<ModalStackParamList>;
|
||||||
|
AttachmentView: {
|
||||||
|
attachment: IAttachment;
|
||||||
|
};
|
||||||
|
ModalBlockView: {
|
||||||
|
data: any; // TODO: Change
|
||||||
|
};
|
||||||
|
JitsiMeetView: {
|
||||||
|
rid: string;
|
||||||
|
url: string;
|
||||||
|
onlyAudio?: boolean;
|
||||||
|
};
|
||||||
|
ShareView: {
|
||||||
|
attachments: IAttachment[];
|
||||||
|
isShareView?: boolean;
|
||||||
|
serverInfo: {};
|
||||||
|
text: string;
|
||||||
|
room: IRoom;
|
||||||
|
thread: any; // TODO: Change
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,10 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createStackNavigator } from '@react-navigation/stack';
|
import { createStackNavigator, StackNavigationOptions } from '@react-navigation/stack';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { ThemeContext } from '../theme';
|
import { ThemeContext } from '../theme';
|
||||||
import { ModalAnimation, StackAnimation, defaultHeader, themedHeader } from '../utils/navigation';
|
import { ModalAnimation, StackAnimation, defaultHeader, themedHeader } from '../utils/navigation';
|
||||||
|
|
||||||
// Outside Stack
|
// Outside Stack
|
||||||
// import NewServerView from '../views/NewServerView';
|
// import NewServerView from '../views/NewServerView';
|
||||||
import WorkspaceView from '../views/WorkspaceView';
|
import WorkspaceView from '../views/WorkspaceView';
|
||||||
|
@ -14,37 +13,34 @@ import SendEmailConfirmationView from '../views/SendEmailConfirmationView';
|
||||||
import RegisterView from '../views/RegisterView';
|
import RegisterView from '../views/RegisterView';
|
||||||
import LegalView from '../views/LegalView';
|
import LegalView from '../views/LegalView';
|
||||||
import AuthenticationWebView from '../views/AuthenticationWebView';
|
import AuthenticationWebView from '../views/AuthenticationWebView';
|
||||||
|
import { OutsideModalParamList, OutsideParamList } from './types';
|
||||||
|
|
||||||
// Outside
|
// Outside
|
||||||
const Outside = createStackNavigator();
|
const Outside = createStackNavigator<OutsideParamList>();
|
||||||
const _OutsideStack = () => {
|
const _OutsideStack = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Outside.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation }}>
|
<Outside.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme), ...StackAnimation } as StackNavigationOptions}>
|
||||||
{/* <Outside.Screen name='NewServerView' component={NewServerView} options={NewServerView.navigationOptions} /> */}
|
{/* <Outside.Screen name='NewServerView' component={NewServerView} options={NewServerView.navigationOptions} /> */}
|
||||||
<Outside.Screen name='WorkspaceView' component={WorkspaceView} options={WorkspaceView.navigationOptions} />
|
<Outside.Screen name='WorkspaceView' component={WorkspaceView} options={WorkspaceView.navigationOptions} />
|
||||||
<Outside.Screen name='LoginView' component={LoginView} options={LoginView.navigationOptions} />
|
<Outside.Screen name='LoginView' component={LoginView} options={LoginView.navigationOptions} />
|
||||||
<Outside.Screen name='ForgotPasswordView' component={ForgotPasswordView} options={ForgotPasswordView.navigationOptions} />
|
<Outside.Screen name='ForgotPasswordView' component={ForgotPasswordView} options={ForgotPasswordView.navigationOptions} />
|
||||||
<Outside.Screen
|
<Outside.Screen name='SendEmailConfirmationView' component={SendEmailConfirmationView} />
|
||||||
name='SendEmailConfirmationView'
|
|
||||||
component={SendEmailConfirmationView}
|
|
||||||
options={SendEmailConfirmationView.navigationOptions}
|
|
||||||
/>
|
|
||||||
<Outside.Screen name='RegisterView' component={RegisterView} options={RegisterView.navigationOptions} />
|
<Outside.Screen name='RegisterView' component={RegisterView} options={RegisterView.navigationOptions} />
|
||||||
<Outside.Screen name='LegalView' component={LegalView} options={LegalView.navigationOptions} />
|
<Outside.Screen name='LegalView' component={LegalView} options={LegalView.navigationOptions} />
|
||||||
</Outside.Navigator>
|
</Outside.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
root: state.app.root
|
root: state.app.root
|
||||||
});
|
});
|
||||||
|
|
||||||
const OutsideStack = connect(mapStateToProps)(_OutsideStack);
|
const OutsideStack = connect(mapStateToProps)(_OutsideStack);
|
||||||
|
|
||||||
// OutsideStackModal
|
// OutsideStackModal
|
||||||
const OutsideModal = createStackNavigator();
|
const OutsideModal = createStackNavigator<OutsideModalParamList>();
|
||||||
const OutsideStackModal = () => {
|
const OutsideStackModal = () => {
|
||||||
const { theme } = React.useContext(ThemeContext);
|
const { theme } = React.useContext(ThemeContext);
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
import { NavigatorScreenParams } from '@react-navigation/core';
|
||||||
|
import { TextInputProps } from 'react-native';
|
||||||
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
|
||||||
|
import { IOptionsField } from '../views/NotificationPreferencesView/options';
|
||||||
|
import { IServer } from '../definitions/IServer';
|
||||||
|
import { IAttachment } from '../definitions/IAttachment';
|
||||||
|
import { IMessage } from '../definitions/IMessage';
|
||||||
|
import { IRoom, RoomType } from '../definitions/IRoom';
|
||||||
|
|
||||||
|
export type ChatsStackParamList = {
|
||||||
|
RoomsListView: undefined;
|
||||||
|
RoomView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
tmid?: string;
|
||||||
|
message?: string;
|
||||||
|
name?: string;
|
||||||
|
fname?: string;
|
||||||
|
prid?: string;
|
||||||
|
room: IRoom;
|
||||||
|
jumpToMessageId?: string;
|
||||||
|
jumpToThreadId?: string;
|
||||||
|
roomUserId?: string;
|
||||||
|
};
|
||||||
|
RoomActionsView: {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
joined: boolean;
|
||||||
|
};
|
||||||
|
SelectListView: {
|
||||||
|
data: any;
|
||||||
|
title: string;
|
||||||
|
infoText: string;
|
||||||
|
nextAction: Function;
|
||||||
|
showAlert: boolean;
|
||||||
|
isSearch: boolean;
|
||||||
|
onSearch: Function;
|
||||||
|
isRadio?: boolean;
|
||||||
|
};
|
||||||
|
RoomInfoView: {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
};
|
||||||
|
RoomInfoEditView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
RoomMembersView: {
|
||||||
|
rid: string;
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
SearchMessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
encrypted?: boolean;
|
||||||
|
showCloseModal?: boolean;
|
||||||
|
};
|
||||||
|
SelectedUsersView: {
|
||||||
|
maxUsers?: number;
|
||||||
|
showButton?: boolean;
|
||||||
|
title?: string;
|
||||||
|
buttonText?: string;
|
||||||
|
nextAction?: Function;
|
||||||
|
};
|
||||||
|
InviteUsersView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
InviteUsersEditView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
MessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
AutoTranslateView: {
|
||||||
|
rid: string;
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
DirectoryView: undefined;
|
||||||
|
NotificationPrefView: {
|
||||||
|
rid: string;
|
||||||
|
room: Model;
|
||||||
|
};
|
||||||
|
ForwardLivechatView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
LivechatEditView: {
|
||||||
|
room: IRoom;
|
||||||
|
roomUser: any; // TODO: Change
|
||||||
|
};
|
||||||
|
PickerView: {
|
||||||
|
title: string;
|
||||||
|
data: IOptionsField[];
|
||||||
|
value?: any; // TODO: Change
|
||||||
|
onChangeText?: ((text: string) => IOptionsField[]) | ((term?: string) => Promise<any>);
|
||||||
|
goBack?: boolean;
|
||||||
|
onChangeValue: Function;
|
||||||
|
};
|
||||||
|
ThreadMessagesView: {
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
};
|
||||||
|
TeamChannelsView: {
|
||||||
|
teamId: string;
|
||||||
|
};
|
||||||
|
CreateChannelView: {
|
||||||
|
isTeam?: boolean; // TODO: To check
|
||||||
|
teamId?: string;
|
||||||
|
};
|
||||||
|
AddChannelTeamView: {
|
||||||
|
teamId?: string;
|
||||||
|
teamChannels: []; // TODO: Change
|
||||||
|
};
|
||||||
|
AddExistingChannelView: {
|
||||||
|
teamId?: string;
|
||||||
|
teamChannels: []; // TODO: Change
|
||||||
|
};
|
||||||
|
MarkdownTableView: {
|
||||||
|
renderRows: (drawExtraBorders?: boolean) => JSX.Element;
|
||||||
|
tableWidth: number;
|
||||||
|
};
|
||||||
|
ReadReceiptsView: {
|
||||||
|
messageId: string;
|
||||||
|
};
|
||||||
|
QueueListView: undefined;
|
||||||
|
CannedResponsesListView: {
|
||||||
|
rid: string;
|
||||||
|
};
|
||||||
|
CannedResponseDetail: {
|
||||||
|
cannedResponse: {
|
||||||
|
shortcut: string;
|
||||||
|
text: string;
|
||||||
|
scopeName: string;
|
||||||
|
tags: string[];
|
||||||
|
};
|
||||||
|
room: IRoom;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProfileStackParamList = {
|
||||||
|
ProfileView: undefined;
|
||||||
|
UserPreferencesView: undefined;
|
||||||
|
UserNotificationPrefView: undefined;
|
||||||
|
PickerView: {
|
||||||
|
title: string;
|
||||||
|
data: IOptionsField[];
|
||||||
|
value: any; // TODO: Change
|
||||||
|
onChangeText?: TextInputProps['onChangeText'];
|
||||||
|
goBack?: Function;
|
||||||
|
onChangeValue: Function;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SettingsStackParamList = {
|
||||||
|
SettingsView: undefined;
|
||||||
|
SecurityPrivacyView: undefined;
|
||||||
|
E2EEncryptionSecurityView: undefined;
|
||||||
|
LanguageView: undefined;
|
||||||
|
ThemeView: undefined;
|
||||||
|
DefaultBrowserView: undefined;
|
||||||
|
ScreenLockConfigView: undefined;
|
||||||
|
ProfileView: undefined;
|
||||||
|
DisplayPrefsView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AdminPanelStackParamList = {
|
||||||
|
AdminPanelView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DisplayPrefStackParamList = {
|
||||||
|
DisplayPrefsView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DrawerParamList = {
|
||||||
|
ChatsStackNavigator: NavigatorScreenParams<ChatsStackParamList>;
|
||||||
|
ProfileStackNavigator: NavigatorScreenParams<ProfileStackParamList>;
|
||||||
|
SettingsStackNavigator: NavigatorScreenParams<SettingsStackParamList>;
|
||||||
|
AdminPanelStackNavigator: NavigatorScreenParams<AdminPanelStackParamList>;
|
||||||
|
DisplayPrefStackNavigator: NavigatorScreenParams<DisplayPrefStackParamList>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NewMessageStackParamList = {
|
||||||
|
NewMessageView: undefined;
|
||||||
|
SelectedUsersViewCreateChannel: {
|
||||||
|
maxUsers?: number;
|
||||||
|
showButton?: boolean;
|
||||||
|
title?: string;
|
||||||
|
buttonText?: string;
|
||||||
|
nextAction?: Function;
|
||||||
|
}; // TODO: Change
|
||||||
|
CreateChannelView: {
|
||||||
|
isTeam?: boolean; // TODO: To check
|
||||||
|
teamId?: string;
|
||||||
|
};
|
||||||
|
CreateDiscussionView: {
|
||||||
|
channel: IRoom;
|
||||||
|
message: IMessage;
|
||||||
|
showCloseModal: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type E2ESaveYourPasswordStackParamList = {
|
||||||
|
E2ESaveYourPasswordView: undefined;
|
||||||
|
E2EHowItWorksView?: {
|
||||||
|
showCloseModal?: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type E2EEnterYourPasswordStackParamList = {
|
||||||
|
E2EEnterYourPasswordView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type InsideStackParamList = {
|
||||||
|
DrawerNavigator: NavigatorScreenParams<DrawerParamList>;
|
||||||
|
NewMessageStackNavigator: NavigatorScreenParams<NewMessageStackParamList>;
|
||||||
|
E2ESaveYourPasswordStackNavigator: NavigatorScreenParams<E2ESaveYourPasswordStackParamList>;
|
||||||
|
E2EEnterYourPasswordStackNavigator: NavigatorScreenParams<E2EEnterYourPasswordStackParamList>;
|
||||||
|
AttachmentView: {
|
||||||
|
attachment: IAttachment;
|
||||||
|
};
|
||||||
|
StatusView: undefined;
|
||||||
|
ShareView: {
|
||||||
|
attachments: IAttachment[];
|
||||||
|
isShareView?: boolean;
|
||||||
|
isShareExtension: boolean;
|
||||||
|
serverInfo: IServer;
|
||||||
|
text: string;
|
||||||
|
room: IRoom;
|
||||||
|
thread: any; // TODO: Change
|
||||||
|
};
|
||||||
|
ModalBlockView: {
|
||||||
|
data: any; // TODO: Change;
|
||||||
|
};
|
||||||
|
JitsiMeetView: {
|
||||||
|
rid: string;
|
||||||
|
url: string;
|
||||||
|
onlyAudio?: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OutsideParamList = {
|
||||||
|
NewServerView: undefined;
|
||||||
|
WorkspaceView: undefined;
|
||||||
|
LoginView: {
|
||||||
|
title: string;
|
||||||
|
username?: string;
|
||||||
|
};
|
||||||
|
ForgotPasswordView: {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
SendEmailConfirmationView: {
|
||||||
|
user?: string;
|
||||||
|
};
|
||||||
|
RegisterView: {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
LegalView: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OutsideModalParamList = {
|
||||||
|
OutsideStack: NavigatorScreenParams<OutsideParamList>;
|
||||||
|
AuthenticationWebView: {
|
||||||
|
authType: string;
|
||||||
|
url: string;
|
||||||
|
ssoToken?: string;
|
||||||
|
};
|
||||||
|
};
|
|
@ -12,7 +12,7 @@ interface IThemeContextProps {
|
||||||
|
|
||||||
export const ThemeContext = React.createContext<IThemeContextProps>({ theme: 'light' });
|
export const ThemeContext = React.createContext<IThemeContextProps>({ theme: 'light' });
|
||||||
|
|
||||||
export function withTheme(Component: any) {
|
export function withTheme(Component: any): any {
|
||||||
const ThemedComponent = (props: any) => (
|
const ThemedComponent = (props: any) => (
|
||||||
<ThemeContext.Consumer>{contexts => <Component {...props} {...contexts} />}</ThemeContext.Consumer>
|
<ThemeContext.Consumer>{contexts => <Component {...props} {...contexts} />}</ThemeContext.Consumer>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,13 +5,7 @@ import EventEmitter from '../events';
|
||||||
import { LISTENER } from '../../containers/Toast';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { DOCUMENTS_PATH, DOWNLOAD_PATH } from '../../constants/localPath';
|
import { DOCUMENTS_PATH, DOWNLOAD_PATH } from '../../constants/localPath';
|
||||||
|
import { IAttachment } from '../../definitions/IAttachment';
|
||||||
interface IAttachment {
|
|
||||||
title: string;
|
|
||||||
title_link: string;
|
|
||||||
type: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getLocalFilePathFromFile = (localPath: string, attachment: IAttachment): string => `${localPath}${attachment.title}`;
|
export const getLocalFilePathFromFile = (localPath: string, attachment: IAttachment): string => `${localPath}${attachment.title}`;
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,6 @@ export default {
|
||||||
RA_GO_AUTOTRANSLATE: 'ra_go_autotranslate',
|
RA_GO_AUTOTRANSLATE: 'ra_go_autotranslate',
|
||||||
RA_GO_NOTIFICATIONPREF: 'ra_go_notification_pref',
|
RA_GO_NOTIFICATIONPREF: 'ra_go_notification_pref',
|
||||||
RA_GO_FORWARDLIVECHAT: 'ra_go_forward_livechat',
|
RA_GO_FORWARDLIVECHAT: 'ra_go_forward_livechat',
|
||||||
RA_GO_VISITORNAVIGATION: 'ra_go_visitor_navigation',
|
|
||||||
RA_SHARE: 'ra_share',
|
RA_SHARE: 'ra_share',
|
||||||
RA_LEAVE: 'ra_leave',
|
RA_LEAVE: 'ra_leave',
|
||||||
RA_LEAVE_F: 'ra_leave_f',
|
RA_LEAVE_F: 'ra_leave_f',
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
export const canUploadFile = (file, allowList, maxFileSize) => {
|
export const canUploadFile = (file, allowList, maxFileSize, permissionToUploadFile) => {
|
||||||
if (!(file && file.path)) {
|
if (!(file && file.path)) {
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
if (maxFileSize > -1 && file.size > maxFileSize) {
|
if (maxFileSize > -1 && file.size > maxFileSize) {
|
||||||
return { success: false, error: 'error-file-too-large' };
|
return { success: false, error: 'error-file-too-large' };
|
||||||
}
|
}
|
||||||
|
if (!permissionToUploadFile) {
|
||||||
|
return { success: false, error: 'error-not-permission-to-upload-file' };
|
||||||
|
}
|
||||||
// if white list is empty, all media types are enabled
|
// if white list is empty, all media types are enabled
|
||||||
if (!allowList || allowList === '*') {
|
if (!allowList || allowList === '*') {
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
|
|
@ -7,6 +7,21 @@ import I18n from '../i18n';
|
||||||
import { extractHostname } from './server';
|
import { extractHostname } from './server';
|
||||||
|
|
||||||
const { SSLPinning } = NativeModules;
|
const { SSLPinning } = NativeModules;
|
||||||
|
const { documentDirectory } = FileSystem;
|
||||||
|
|
||||||
|
const extractFileScheme = path => path.replace('file://', ''); // file:// isn't allowed by obj-C
|
||||||
|
|
||||||
|
const getPath = name => `${documentDirectory}/${name}`;
|
||||||
|
|
||||||
|
const persistCertificate = async (name, password) => {
|
||||||
|
const certificatePath = getPath(name);
|
||||||
|
const certificate = {
|
||||||
|
path: extractFileScheme(certificatePath),
|
||||||
|
password
|
||||||
|
};
|
||||||
|
await UserPreferences.setMapAsync(name, certificate);
|
||||||
|
return certificate;
|
||||||
|
};
|
||||||
|
|
||||||
const RCSSLPinning = Platform.select({
|
const RCSSLPinning = Platform.select({
|
||||||
ios: {
|
ios: {
|
||||||
|
@ -25,17 +40,9 @@ const RCSSLPinning = Platform.select({
|
||||||
text: 'OK',
|
text: 'OK',
|
||||||
onPress: async password => {
|
onPress: async password => {
|
||||||
try {
|
try {
|
||||||
const certificatePath = `${FileSystem.documentDirectory}/${name}`;
|
const certificatePath = getPath(name);
|
||||||
|
|
||||||
await FileSystem.copyAsync({ from: uri, to: certificatePath });
|
await FileSystem.copyAsync({ from: uri, to: certificatePath });
|
||||||
|
await persistCertificate(name, password);
|
||||||
const certificate = {
|
|
||||||
path: certificatePath.replace('file://', ''), // file:// isn't allowed by obj-C
|
|
||||||
password
|
|
||||||
};
|
|
||||||
|
|
||||||
await UserPreferences.setMapAsync(name, certificate);
|
|
||||||
|
|
||||||
resolve(name);
|
resolve(name);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(e);
|
reject(e);
|
||||||
|
@ -49,16 +56,19 @@ const RCSSLPinning = Platform.select({
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
setCertificate: async (alias, server) => {
|
setCertificate: async (name, server) => {
|
||||||
if (alias) {
|
if (name) {
|
||||||
const certificate = await UserPreferences.getMapAsync(alias);
|
let certificate = await UserPreferences.getMapAsync(name);
|
||||||
|
if (!certificate.path.match(extractFileScheme(documentDirectory))) {
|
||||||
|
certificate = await persistCertificate(name, certificate.password);
|
||||||
|
}
|
||||||
await UserPreferences.setMapAsync(extractHostname(server), certificate);
|
await UserPreferences.setMapAsync(extractHostname(server), certificate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
android: {
|
android: {
|
||||||
pickCertificate: () => SSLPinning?.pickCertificate(),
|
pickCertificate: () => SSLPinning?.pickCertificate(),
|
||||||
setCertificate: alias => SSLPinning?.setCertificate(alias)
|
setCertificate: name => SSLPinning?.setCertificate(name)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
|
||||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { RouteProp } from '@react-navigation/native';
|
import { RouteProp } from '@react-navigation/native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { CompositeNavigationProp } from '@react-navigation/core';
|
||||||
|
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
@ -9,16 +10,24 @@ import { useTheme } from '../theme';
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
import { ChatsStackParamList, DrawerParamList, NewMessageStackParamList } from '../stacks/types';
|
||||||
type TNavigation = StackNavigationProp<any, 'AddChannelTeamView'>;
|
|
||||||
|
|
||||||
interface IAddChannelTeamView {
|
interface IAddChannelTeamView {
|
||||||
route: RouteProp<{ AddChannelTeamView: { teamId: string; teamChannels: object[] } }, 'AddChannelTeamView'>;
|
navigation: CompositeNavigationProp<
|
||||||
navigation: TNavigation;
|
StackNavigationProp<ChatsStackParamList, 'AddChannelTeamView'>,
|
||||||
|
CompositeNavigationProp<StackNavigationProp<NewMessageStackParamList>, StackNavigationProp<DrawerParamList>>
|
||||||
|
>;
|
||||||
|
route: RouteProp<ChatsStackParamList, 'AddChannelTeamView'>;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setHeader = (navigation: TNavigation, isMasterDetail: boolean) => {
|
const setHeader = ({
|
||||||
|
navigation,
|
||||||
|
isMasterDetail
|
||||||
|
}: {
|
||||||
|
navigation: StackNavigationProp<ChatsStackParamList, 'AddChannelTeamView'>;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
}) => {
|
||||||
const options: StackNavigationOptions = {
|
const options: StackNavigationOptions = {
|
||||||
headerTitle: I18n.t('Add_Channel_to_Team')
|
headerTitle: I18n.t('Add_Channel_to_Team')
|
||||||
};
|
};
|
||||||
|
@ -35,7 +44,7 @@ const AddChannelTeamView = ({ navigation, route, isMasterDetail }: IAddChannelTe
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setHeader(navigation, isMasterDetail);
|
setHeader({ navigation, isMasterDetail });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { animateNextTransition } from '../utils/layoutAnimation';
|
||||||
import { goRoom } from '../utils/goRoom';
|
import { goRoom } from '../utils/goRoom';
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import debounce from '../utils/debounce';
|
import debounce from '../utils/debounce';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
interface IAddExistingChannelViewState {
|
interface IAddExistingChannelViewState {
|
||||||
// TODO: refactor with Room Model
|
// TODO: refactor with Room Model
|
||||||
|
@ -31,8 +32,8 @@ interface IAddExistingChannelViewState {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAddExistingChannelViewProps {
|
interface IAddExistingChannelViewProps {
|
||||||
navigation: StackNavigationProp<any, 'AddExistingChannelView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'AddExistingChannelView'>;
|
||||||
route: RouteProp<{ AddExistingChannelView: { teamId: string } }, 'AddExistingChannelView'>;
|
route: RouteProp<ChatsStackParamList, 'AddExistingChannelView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
addTeamChannelPermission: string[];
|
addTeamChannelPermission: string[];
|
||||||
|
@ -41,7 +42,7 @@ interface IAddExistingChannelViewProps {
|
||||||
const QUERY_SIZE = 50;
|
const QUERY_SIZE = 50;
|
||||||
|
|
||||||
class AddExistingChannelView extends React.Component<IAddExistingChannelViewProps, IAddExistingChannelViewState> {
|
class AddExistingChannelView extends React.Component<IAddExistingChannelViewProps, IAddExistingChannelViewState> {
|
||||||
private teamId: string;
|
private teamId?: string;
|
||||||
constructor(props: IAddExistingChannelViewProps) {
|
constructor(props: IAddExistingChannelViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.query();
|
this.query();
|
||||||
|
|
|
@ -9,6 +9,7 @@ import * as HeaderButton from '../../containers/HeaderButton';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
|
import { AdminPanelStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
interface IAdminPanelViewProps {
|
interface IAdminPanelViewProps {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
|
@ -16,7 +17,7 @@ interface IAdminPanelViewProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface INavigationOptions {
|
interface INavigationOptions {
|
||||||
navigation: DrawerScreenProps<any>;
|
navigation: DrawerScreenProps<AdminPanelStackParamList, 'AdminPanelView'>;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ import { getUserSelector } from '../selectors/login';
|
||||||
import { withDimensions } from '../dimensions';
|
import { withDimensions } from '../dimensions';
|
||||||
import { getHeaderHeight } from '../containers/Header';
|
import { getHeaderHeight } from '../containers/Header';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import { InsideStackParamList } from '../stacks/types';
|
||||||
|
import { IAttachment } from '../definitions/IAttachment';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -31,24 +33,14 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: refactor when react-navigation is done
|
|
||||||
export interface IAttachment {
|
|
||||||
title: string;
|
|
||||||
title_link?: string;
|
|
||||||
image_url?: string;
|
|
||||||
image_type?: string;
|
|
||||||
video_url?: string;
|
|
||||||
video_type?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IAttachmentViewState {
|
interface IAttachmentViewState {
|
||||||
attachment: IAttachment;
|
attachment: IAttachment;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAttachmentViewProps {
|
interface IAttachmentViewProps {
|
||||||
navigation: StackNavigationProp<any, 'AttachmentView'>;
|
navigation: StackNavigationProp<InsideStackParamList, 'AttachmentView'>;
|
||||||
route: RouteProp<{ AttachmentView: { attachment: IAttachment } }, 'AttachmentView'>;
|
route: RouteProp<InsideStackParamList, 'AttachmentView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
width: number;
|
width: number;
|
||||||
|
|
|
@ -4,7 +4,9 @@ import { connect } from 'react-redux';
|
||||||
import parse from 'url-parse';
|
import parse from 'url-parse';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { WebViewMessage } from 'react-native-webview/lib/WebViewTypes';
|
import { WebViewMessage } from 'react-native-webview/lib/WebViewTypes';
|
||||||
|
import { RouteProp } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { OutsideModalParamList } from '../stacks/types';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { isIOS } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
@ -41,17 +43,9 @@ window.addEventListener('popstate', function() {
|
||||||
});
|
});
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface IRoute {
|
|
||||||
params: {
|
|
||||||
authType: string;
|
|
||||||
url: string;
|
|
||||||
ssoToken?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface INavigationOption {
|
interface INavigationOption {
|
||||||
navigation: StackNavigationProp<any, 'AuthenticationWebView'>;
|
navigation: StackNavigationProp<OutsideModalParamList, 'AuthenticationWebView'>;
|
||||||
route: IRoute;
|
route: RouteProp<OutsideModalParamList, 'AuthenticationWebView'>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAuthenticationWebView extends INavigationOption {
|
interface IAuthenticationWebView extends INavigationOption {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlatList, StyleSheet, Switch } from 'react-native';
|
import { FlatList, StyleSheet, Switch } from 'react-native';
|
||||||
|
import { RouteProp } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import StatusBar from '../../containers/StatusBar';
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
@ -9,6 +11,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../../constants/colors';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import { events, logEvent } from '../../utils/log';
|
import { events, logEvent } from '../../utils/log';
|
||||||
|
import { IRoom } from '../../definitions/IRoom';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
list: {
|
list: {
|
||||||
|
@ -16,19 +19,8 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IRoom {
|
|
||||||
observe: Function;
|
|
||||||
autoTranslateLanguage: boolean;
|
|
||||||
autoTranslate: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IAutoTranslateViewProps {
|
interface IAutoTranslateViewProps {
|
||||||
route: {
|
route: RouteProp<ChatsStackParamList, 'AutoTranslateView'>;
|
||||||
params: {
|
|
||||||
rid?: string;
|
|
||||||
room?: IRoom;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { events, logEvent } from '../utils/log';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -91,8 +92,8 @@ interface ICreateChannelViewState {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICreateChannelViewProps {
|
interface ICreateChannelViewProps {
|
||||||
navigation: StackNavigationProp<any, 'CreateChannelView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'CreateChannelView'>;
|
||||||
route: RouteProp<{ CreateChannelView: { isTeam: boolean; teamId: string } }, 'CreateChannelView'>;
|
route: RouteProp<ChatsStackParamList, 'CreateChannelView'>;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
create: (data: ICreateFunction) => void;
|
create: (data: ICreateFunction) => void;
|
||||||
removeUser: (user: IOtherUser) => void;
|
removeUser: (user: IOtherUser) => void;
|
||||||
|
@ -118,7 +119,7 @@ interface ISwitch extends SwitchProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreateChannelViewState> {
|
class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreateChannelViewState> {
|
||||||
private teamId: string;
|
private teamId?: string;
|
||||||
|
|
||||||
constructor(props: ICreateChannelViewProps) {
|
constructor(props: ICreateChannelViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -240,7 +241,7 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
|
||||||
broadcast,
|
broadcast,
|
||||||
encrypted,
|
encrypted,
|
||||||
isTeam,
|
isTeam,
|
||||||
teamId: this.teamId
|
teamId: this.teamId!
|
||||||
});
|
});
|
||||||
|
|
||||||
Review.pushPositiveEvent();
|
Review.pushPositiveEvent();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { ScrollView, Switch, Text } from 'react-native';
|
import { ScrollView, Switch, Text } from 'react-native';
|
||||||
|
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||||
|
|
||||||
import Loading from '../../containers/Loading';
|
import Loading from '../../containers/Loading';
|
||||||
import KeyboardView from '../../presentation/KeyboardView';
|
import KeyboardView from '../../presentation/KeyboardView';
|
||||||
|
@ -89,7 +90,7 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, any> {
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
headerLeft: showCloseModal ? () => <HeaderButton.CloseModal navigation={navigation} /> : undefined
|
headerLeft: showCloseModal ? () => <HeaderButton.CloseModal navigation={navigation} /> : undefined
|
||||||
});
|
} as StackNavigationOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
submit = () => {
|
submit = () => {
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
|
import { RouteProp } from '@react-navigation/core';
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
import { NewMessageStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
export interface ICreateChannelViewProps {
|
export interface ICreateChannelViewProps {
|
||||||
navigation: any;
|
navigation: StackNavigationProp<NewMessageStackParamList, 'CreateDiscussionView'>;
|
||||||
route: {
|
route: RouteProp<NewMessageStackParamList, 'CreateDiscussionView'>;
|
||||||
params?: {
|
|
||||||
channel: string;
|
|
||||||
message: {
|
|
||||||
msg: string;
|
|
||||||
};
|
|
||||||
showCloseModal: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
server: string;
|
server: string;
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -63,7 +63,11 @@ export default class DirectoryOptions extends PureComponent<IDirectoryOptionsPro
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Touch onPress={() => changeType(itemType)} style={styles.dropdownItemButton} theme={theme}>
|
<Touch
|
||||||
|
onPress={() => changeType(itemType)}
|
||||||
|
style={styles.dropdownItemButton}
|
||||||
|
theme={theme}
|
||||||
|
accessibilityLabel={I18n.t(text)}>
|
||||||
<View style={styles.dropdownItemContainer}>
|
<View style={styles.dropdownItemContainer}>
|
||||||
<CustomIcon style={[styles.dropdownItemIcon, { color: themes[theme].bodyText }]} size={22} name={icon} />
|
<CustomIcon style={[styles.dropdownItemIcon, { color: themes[theme].bodyText }]} size={22} name={icon} />
|
||||||
<Text style={[styles.dropdownItemText, { color: themes[theme].bodyText }]}>{I18n.t(text)}</Text>
|
<Text style={[styles.dropdownItemText, { color: themes[theme].bodyText }]}>{I18n.t(text)}</Text>
|
||||||
|
@ -90,7 +94,7 @@ export default class DirectoryOptions extends PureComponent<IDirectoryOptionsPro
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: themes[theme].backgroundColor }]}>
|
style={[styles.dropdownContainer, { transform: [{ translateY }], backgroundColor: themes[theme].backgroundColor }]}>
|
||||||
<Touch onPress={this.close} theme={theme}>
|
<Touch onPress={this.close} theme={theme} accessibilityLabel={I18n.t('Search_by')}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.dropdownContainerHeader,
|
styles.dropdownContainerHeader,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlatList, Text, View } from 'react-native';
|
import { FlatList, Text, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
import * as List from '../../containers/List';
|
import * as List from '../../containers/List';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
@ -24,7 +26,7 @@ import styles from './styles';
|
||||||
import Options from './Options';
|
import Options from './Options';
|
||||||
|
|
||||||
interface IDirectoryViewProps {
|
interface IDirectoryViewProps {
|
||||||
navigation: object;
|
navigation: StackNavigationProp<ChatsStackParamList, 'DirectoryView'>;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
isFederationEnabled: boolean;
|
isFederationEnabled: boolean;
|
||||||
user: {
|
user: {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import KeyboardView from '../presentation/KeyboardView';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { events, logEvent } from '../utils/log';
|
import { events, logEvent } from '../utils/log';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { E2EEnterYourPasswordStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -36,7 +37,7 @@ interface IE2EEnterYourPasswordViewState {
|
||||||
interface IE2EEnterYourPasswordViewProps {
|
interface IE2EEnterYourPasswordViewProps {
|
||||||
encryptionDecodeKey: (password: string) => void;
|
encryptionDecodeKey: (password: string) => void;
|
||||||
theme: string;
|
theme: string;
|
||||||
navigation: StackNavigationProp<any, 'E2EEnterYourPasswordView'>;
|
navigation: StackNavigationProp<E2EEnterYourPasswordStackParamList, 'E2EEnterYourPasswordView'>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class E2EEnterYourPasswordView extends React.Component<IE2EEnterYourPasswordViewProps, IE2EEnterYourPasswordViewState> {
|
class E2EEnterYourPasswordView extends React.Component<IE2EEnterYourPasswordViewProps, IE2EEnterYourPasswordViewState> {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import Markdown from '../containers/markdown';
|
import Markdown from '../containers/markdown';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
import { E2ESaveYourPasswordStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -23,8 +24,8 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface INavigation {
|
interface INavigation {
|
||||||
navigation: StackNavigationProp<any, 'E2EHowItWorksView'>;
|
navigation: StackNavigationProp<E2ESaveYourPasswordStackParamList, 'E2EHowItWorksView'>;
|
||||||
route: RouteProp<{ E2EHowItWorksView: { showCloseModal: boolean } }, 'E2EHowItWorksView'>;
|
route: RouteProp<E2ESaveYourPasswordStackParamList, 'E2EHowItWorksView'>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IE2EHowItWorksViewProps extends INavigation {
|
interface IE2EHowItWorksViewProps extends INavigation {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import Button from '../containers/Button';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { E2ESaveYourPasswordStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -60,7 +61,7 @@ interface IE2ESaveYourPasswordViewState {
|
||||||
|
|
||||||
interface IE2ESaveYourPasswordViewProps {
|
interface IE2ESaveYourPasswordViewProps {
|
||||||
server: string;
|
server: string;
|
||||||
navigation: StackNavigationProp<any, 'E2ESaveYourPasswordView'>;
|
navigation: StackNavigationProp<E2ESaveYourPasswordStackParamList, 'E2ESaveYourPasswordView'>;
|
||||||
encryptionSetBanner(): void;
|
encryptionSetBanner(): void;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { themes } from '../constants/colors';
|
||||||
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
||||||
import { events, logEvent } from '../utils/log';
|
import { events, logEvent } from '../utils/log';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { OutsideParamList } from '../stacks/types';
|
||||||
|
|
||||||
interface IForgotPasswordViewState {
|
interface IForgotPasswordViewState {
|
||||||
email: string;
|
email: string;
|
||||||
|
@ -22,8 +23,8 @@ interface IForgotPasswordViewState {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IForgotPasswordViewProps {
|
interface IForgotPasswordViewProps {
|
||||||
navigation: StackNavigationProp<any, 'ForgotPasswordView'>;
|
navigation: StackNavigationProp<OutsideParamList, 'ForgotPasswordView'>;
|
||||||
route: RouteProp<{ ForgotPasswordView: { title: string } }, 'ForgotPasswordView'>;
|
route: RouteProp<OutsideParamList, 'ForgotPasswordView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import OrSeparator from '../containers/OrSeparator';
|
||||||
import Input from '../containers/UIKit/MultiSelect/Input';
|
import Input from '../containers/UIKit/MultiSelect/Input';
|
||||||
import { forwardRoom as forwardRoomAction } from '../actions/room';
|
import { forwardRoom as forwardRoomAction } from '../actions/room';
|
||||||
import { ILivechatDepartment } from './definition/ILivechatDepartment';
|
import { ILivechatDepartment } from './definition/ILivechatDepartment';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -47,8 +48,8 @@ interface IParsedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IForwardLivechatViewProps {
|
interface IForwardLivechatViewProps {
|
||||||
navigation: StackNavigationProp<any, 'ForwardLivechatView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'ForwardLivechatView'>;
|
||||||
route: RouteProp<{ ForwardLivechatView: { rid: string } }, 'ForwardLivechatView'>;
|
route: RouteProp<ChatsStackParamList, 'ForwardLivechatView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
forwardRoom: (rid: string, transferData: ITransferData) => void;
|
forwardRoom: (rid: string, transferData: ITransferData) => void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { withTheme } from '../../theme';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import { events, logEvent } from '../../utils/log';
|
import { events, logEvent } from '../../utils/log';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
const OPTIONS = {
|
const OPTIONS = {
|
||||||
days: [
|
days: [
|
||||||
|
@ -67,9 +68,9 @@ const OPTIONS = {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IInviteUsersEditView {
|
interface IInviteUsersEditViewProps {
|
||||||
navigation: StackNavigationProp<any, 'InviteUsersEditView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'InviteUsersEditView'>;
|
||||||
route: RouteProp<{ InviteUsersEditView: { rid: string } }, 'InviteUsersEditView'>;
|
route: RouteProp<ChatsStackParamList, 'InviteUsersEditView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
createInviteLink(rid: string): void;
|
createInviteLink(rid: string): void;
|
||||||
inviteLinksSetParams(params: { [key: string]: number }): void;
|
inviteLinksSetParams(params: { [key: string]: number }): void;
|
||||||
|
@ -77,14 +78,14 @@ interface IInviteUsersEditView {
|
||||||
maxUses: number;
|
maxUses: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InviteUsersView extends React.Component<IInviteUsersEditView, any> {
|
class InviteUsersEditView extends React.Component<IInviteUsersEditViewProps, any> {
|
||||||
static navigationOptions = (): StackNavigationOptions => ({
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Invite_users')
|
title: I18n.t('Invite_users')
|
||||||
});
|
});
|
||||||
|
|
||||||
private rid: string;
|
private rid: string;
|
||||||
|
|
||||||
constructor(props: IInviteUsersEditView) {
|
constructor(props: IInviteUsersEditViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.rid = props.route.params?.rid;
|
this.rid = props.route.params?.rid;
|
||||||
}
|
}
|
||||||
|
@ -160,4 +161,4 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
createInviteLink: (rid: string) => dispatch(inviteLinksCreateAction(rid))
|
createInviteLink: (rid: string) => dispatch(inviteLinksCreateAction(rid))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(InviteUsersView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(InviteUsersEditView));
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { StackNavigationProp, StackNavigationOptions } from '@react-navigation/s
|
||||||
import { RouteProp } from '@react-navigation/core';
|
import { RouteProp } from '@react-navigation/core';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
import {
|
import {
|
||||||
inviteLinksClear as inviteLinksClearAction,
|
inviteLinksClear as inviteLinksClearAction,
|
||||||
inviteLinksCreate as inviteLinksCreateAction
|
inviteLinksCreate as inviteLinksCreateAction
|
||||||
|
@ -22,9 +23,9 @@ import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import { events, logEvent } from '../../utils/log';
|
import { events, logEvent } from '../../utils/log';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
interface IInviteUsersView {
|
interface IInviteUsersViewProps {
|
||||||
navigation: StackNavigationProp<any, 'InviteUsersView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'InviteUsersView'>;
|
||||||
route: RouteProp<any, 'InviteUsersView'>;
|
route: RouteProp<ChatsStackParamList, 'InviteUsersView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
timeDateFormat: string;
|
timeDateFormat: string;
|
||||||
invite: {
|
invite: {
|
||||||
|
@ -36,14 +37,14 @@ interface IInviteUsersView {
|
||||||
createInviteLink(rid: string): void;
|
createInviteLink(rid: string): void;
|
||||||
clearInviteLink(): void;
|
clearInviteLink(): void;
|
||||||
}
|
}
|
||||||
class InviteUsersView extends React.Component<IInviteUsersView, any> {
|
class InviteUsersView extends React.Component<IInviteUsersViewProps, any> {
|
||||||
private rid: string;
|
private rid: string;
|
||||||
|
|
||||||
static navigationOptions: StackNavigationOptions = {
|
static navigationOptions: StackNavigationOptions = {
|
||||||
title: I18n.t('Invite_users')
|
title: I18n.t('Invite_users')
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: IInviteUsersView) {
|
constructor(props: IInviteUsersViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.rid = props.route.params?.rid;
|
this.rid = props.route.params?.rid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import ActivityIndicator from '../containers/ActivityIndicator';
|
||||||
import { events, logEvent } from '../utils/log';
|
import { events, logEvent } from '../utils/log';
|
||||||
import { isAndroid, isIOS } from '../utils/deviceInfo';
|
import { isAndroid, isIOS } from '../utils/deviceInfo';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
import { InsideStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const formatUrl = (url: string, baseUrl: string, uriSize: number, avatarAuthURLFragment: string) =>
|
const formatUrl = (url: string, baseUrl: string, uriSize: number, avatarAuthURLFragment: string) =>
|
||||||
`${baseUrl}/avatar/${url}?format=png&width=${uriSize}&height=${uriSize}${avatarAuthURLFragment}`;
|
`${baseUrl}/avatar/${url}?format=png&width=${uriSize}&height=${uriSize}${avatarAuthURLFragment}`;
|
||||||
|
@ -25,8 +26,8 @@ interface IJitsiMeetViewState {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IJitsiMeetViewProps {
|
interface IJitsiMeetViewProps {
|
||||||
navigation: StackNavigationProp<any, 'JitsiMeetView'>;
|
navigation: StackNavigationProp<InsideStackParamList, 'JitsiMeetView'>;
|
||||||
route: RouteProp<{ JitsiMeetView: { rid: string; url: string; onlyAudio?: boolean } }, 'JitsiMeetView'>;
|
route: RouteProp<InsideStackParamList, 'JitsiMeetView'>;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
user: {
|
user: {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import TextInput from '../containers/TextInput';
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest as loginRequestAction } from '../actions/login';
|
||||||
import LoginServices from '../containers/LoginServices';
|
import LoginServices from '../containers/LoginServices';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { OutsideParamList } from '../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
registerDisabled: {
|
registerDisabled: {
|
||||||
|
@ -47,9 +48,9 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IProps {
|
interface ILoginViewProps {
|
||||||
navigation: StackNavigationProp<any>;
|
navigation: StackNavigationProp<OutsideParamList, 'LoginView'>;
|
||||||
route: RouteProp<any, 'RegisterView'>;
|
route: RouteProp<OutsideParamList, 'LoginView'>;
|
||||||
Site_Name: string;
|
Site_Name: string;
|
||||||
Accounts_RegistrationForm: string;
|
Accounts_RegistrationForm: string;
|
||||||
Accounts_RegistrationForm_LinkReplacementText: string;
|
Accounts_RegistrationForm_LinkReplacementText: string;
|
||||||
|
@ -67,15 +68,15 @@ interface IProps {
|
||||||
inviteLinkToken: string;
|
inviteLinkToken: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoginView extends React.Component<IProps, any> {
|
class LoginView extends React.Component<ILoginViewProps, any> {
|
||||||
private passwordInput: any;
|
private passwordInput: any;
|
||||||
|
|
||||||
static navigationOptions = ({ route, navigation }: Partial<IProps>) => ({
|
static navigationOptions = ({ route, navigation }: ILoginViewProps) => ({
|
||||||
title: route?.params?.title ?? 'Rocket.Chat',
|
title: route?.params?.title ?? 'Rocket.Chat',
|
||||||
headerRight: () => <HeaderButton.Legal testID='login-view-more' navigation={navigation} />
|
headerRight: () => <HeaderButton.Legal testID='login-view-more' navigation={navigation} />
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: ILoginViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
user: props.route.params?.username ?? '',
|
user: props.route.params?.username ?? '',
|
||||||
|
@ -83,7 +84,7 @@ class LoginView extends React.Component<IProps, any> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps: IProps) {
|
UNSAFE_componentWillReceiveProps(nextProps: ILoginViewProps) {
|
||||||
const { error } = this.props;
|
const { error } = this.props;
|
||||||
if (nextProps.failure && !dequal(error, nextProps.error)) {
|
if (nextProps.failure && !dequal(error, nextProps.error)) {
|
||||||
if (nextProps.error?.error === 'error-invalid-email') {
|
if (nextProps.error?.error === 'error-invalid-email') {
|
||||||
|
|
|
@ -7,12 +7,10 @@ import I18n from '../i18n';
|
||||||
import { isIOS } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
interface IMarkdownTableViewProps {
|
interface IMarkdownTableViewProps {
|
||||||
route: RouteProp<
|
route: RouteProp<ChatsStackParamList, 'MarkdownTableView'>;
|
||||||
{ MarkdownTableView: { renderRows: (drawExtraBorders?: boolean) => JSX.Element; tableWidth: number } },
|
|
||||||
'MarkdownTableView'
|
|
||||||
>;
|
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { FlatList, Text, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { RouteProp } from '@react-navigation/core';
|
import { CompositeNavigationProp, RouteProp } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
|
||||||
import Message from '../../containers/message';
|
import Message from '../../containers/message';
|
||||||
import ActivityIndicator from '../../containers/ActivityIndicator';
|
import ActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
@ -18,22 +19,19 @@ import { withActionSheet } from '../../containers/ActionSheet';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import getThreadName from '../../lib/methods/getThreadName';
|
import getThreadName from '../../lib/methods/getThreadName';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
type TMessagesViewRouteParams = {
|
import { IRoom, RoomType } from '../../definitions/IRoom';
|
||||||
MessagesView: {
|
|
||||||
rid: string;
|
|
||||||
t: string;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
interface IMessagesViewProps {
|
interface IMessagesViewProps {
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
navigation: StackNavigationProp<any, 'MessagesView'>;
|
navigation: CompositeNavigationProp<
|
||||||
route: RouteProp<TMessagesViewRouteParams, 'MessagesView'>;
|
StackNavigationProp<ChatsStackParamList, 'MessagesView'>,
|
||||||
|
StackNavigationProp<MasterDetailInsideStackParamList>
|
||||||
|
>;
|
||||||
|
route: RouteProp<ChatsStackParamList, 'MessagesView'>;
|
||||||
customEmojis: { [key: string]: string };
|
customEmojis: { [key: string]: string };
|
||||||
theme: string;
|
theme: string;
|
||||||
showActionSheet: Function;
|
showActionSheet: Function;
|
||||||
|
@ -41,6 +39,14 @@ interface IMessagesViewProps {
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IRoomInfoParam {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
joined: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface IMessagesViewState {
|
interface IMessagesViewState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
messages: [];
|
messages: [];
|
||||||
|
@ -65,17 +71,22 @@ interface IMessageItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
rid?: string;
|
rid: string;
|
||||||
jumpToMessageId: string;
|
t: RoomType;
|
||||||
t?: string;
|
|
||||||
room: any;
|
|
||||||
tmid?: string;
|
tmid?: string;
|
||||||
|
message?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
fname?: string;
|
||||||
|
prid?: string;
|
||||||
|
room: IRoom;
|
||||||
|
jumpToMessageId?: string;
|
||||||
|
jumpToThreadId?: string;
|
||||||
|
roomUserId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessagesView extends React.Component<IMessagesViewProps, any> {
|
class MessagesView extends React.Component<IMessagesViewProps, any> {
|
||||||
private rid?: string;
|
private rid: string;
|
||||||
private t?: string;
|
private t: RoomType;
|
||||||
private content: any;
|
private content: any;
|
||||||
private room: any;
|
private room: any;
|
||||||
|
|
||||||
|
@ -121,7 +132,7 @@ class MessagesView extends React.Component<IMessagesViewProps, any> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
navToRoomInfo = (navParam: { rid: string }) => {
|
navToRoomInfo = (navParam: IRoomInfoParam) => {
|
||||||
const { navigation, user } = this.props;
|
const { navigation, user } = this.props;
|
||||||
if (navParam.rid === user.id) {
|
if (navParam.rid === user.id) {
|
||||||
return;
|
return;
|
||||||
|
@ -147,7 +158,7 @@ class MessagesView extends React.Component<IMessagesViewProps, any> {
|
||||||
...params,
|
...params,
|
||||||
tmid: item.tmid,
|
tmid: item.tmid,
|
||||||
name: await getThreadName(this.rid, item.tmid, item._id),
|
name: await getThreadName(this.rid, item.tmid, item._id),
|
||||||
t: 'thread'
|
t: RoomType.THREAD
|
||||||
};
|
};
|
||||||
navigation.push('RoomView', params);
|
navigation.push('RoomView', params);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, View } from 'react-native';
|
import { StyleSheet, View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
|
import { KeyboardAwareScrollView } from '@codler/react-native-keyboard-aware-scroll-view';
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ import { CONTAINER_TYPES, MODAL_ACTIONS } from '../lib/methods/actions';
|
||||||
import { textParser } from '../containers/UIKit/utils';
|
import { textParser } from '../containers/UIKit/utils';
|
||||||
import Navigation from '../lib/Navigation';
|
import Navigation from '../lib/Navigation';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -30,14 +32,49 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.fromEntries = Object.fromEntries || (arr => arr.reduce((acc, [k, v]) => ((acc[k] = v), acc), {}));
|
interface IValueBlockId {
|
||||||
const groupStateByBlockIdMap = (obj, [key, { blockId, value }]) => {
|
value: string;
|
||||||
|
blockId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type TElementToState = [string, IValueBlockId];
|
||||||
|
interface IActions {
|
||||||
|
actionId: string;
|
||||||
|
value: any;
|
||||||
|
blockId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IValues {
|
||||||
|
[key: string]: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
interface IModalBlockViewState {
|
||||||
|
data: any;
|
||||||
|
loading: boolean;
|
||||||
|
errors?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IModalBlockViewProps {
|
||||||
|
navigation: StackNavigationProp<MasterDetailInsideStackParamList, 'ModalBlockView'>;
|
||||||
|
route: RouteProp<MasterDetailInsideStackParamList, 'ModalBlockView'>;
|
||||||
|
theme: string;
|
||||||
|
language: string;
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
token: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-sequences
|
||||||
|
Object.fromEntries = Object.fromEntries || ((arr: any[]) => arr.reduce((acc, [k, v]) => ((acc[k] = v), acc), {}));
|
||||||
|
const groupStateByBlockIdMap = (obj: any, [key, { blockId, value }]: TElementToState) => {
|
||||||
obj[blockId] = obj[blockId] || {};
|
obj[blockId] = obj[blockId] || {};
|
||||||
obj[blockId][key] = value;
|
obj[blockId][key] = value;
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
const groupStateByBlockId = obj => Object.entries(obj).reduce(groupStateByBlockIdMap, {});
|
const groupStateByBlockId = (obj: { [key: string]: any }) => Object.entries(obj).reduce(groupStateByBlockIdMap, {});
|
||||||
const filterInputFields = ({ element, elements = [] }) => {
|
const filterInputFields = ({ element, elements = [] }: { element: any; elements?: any[] }) => {
|
||||||
if (element && element.initialValue) {
|
if (element && element.initialValue) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +82,8 @@ const filterInputFields = ({ element, elements = [] }) => {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const mapElementToState = ({ element, blockId, elements = [] }) => {
|
|
||||||
|
const mapElementToState = ({ element, blockId, elements = [] }: { element: any; blockId: string; elements?: any[] }): any => {
|
||||||
if (elements.length) {
|
if (elements.length) {
|
||||||
return elements
|
return elements
|
||||||
.map(e => ({ element: e, blockId }))
|
.map(e => ({ element: e, blockId }))
|
||||||
|
@ -54,10 +92,15 @@ const mapElementToState = ({ element, blockId, elements = [] }) => {
|
||||||
}
|
}
|
||||||
return [element.actionId, { value: element.initialValue, blockId }];
|
return [element.actionId, { value: element.initialValue, blockId }];
|
||||||
};
|
};
|
||||||
const reduceState = (obj, el) => (Array.isArray(el[0]) ? { ...obj, ...Object.fromEntries(el) } : { ...obj, [el[0]]: el[1] });
|
const reduceState = (obj: any, el: any) =>
|
||||||
|
Array.isArray(el[0]) ? { ...obj, ...Object.fromEntries(el) } : { ...obj, [el[0]]: el[1] };
|
||||||
|
|
||||||
class ModalBlockView extends React.Component {
|
class ModalBlockView extends React.Component<IModalBlockViewProps, IModalBlockViewState> {
|
||||||
static navigationOptions = ({ route }) => {
|
private submitting: boolean;
|
||||||
|
|
||||||
|
private values: IValues;
|
||||||
|
|
||||||
|
static navigationOptions = ({ route }: Pick<IModalBlockViewProps, 'route'>): StackNavigationOptions => {
|
||||||
const data = route.params?.data;
|
const data = route.params?.data;
|
||||||
const { view } = data;
|
const { view } = data;
|
||||||
const { title } = view;
|
const { title } = view;
|
||||||
|
@ -66,18 +109,7 @@ class ModalBlockView extends React.Component {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: IModalBlockViewProps) {
|
||||||
navigation: PropTypes.object,
|
|
||||||
route: PropTypes.object,
|
|
||||||
theme: PropTypes.string,
|
|
||||||
language: PropTypes.string,
|
|
||||||
user: PropTypes.shape({
|
|
||||||
id: PropTypes.string,
|
|
||||||
token: PropTypes.string
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.submitting = false;
|
this.submitting = false;
|
||||||
const data = props.route.params?.data;
|
const data = props.route.params?.data;
|
||||||
|
@ -95,7 +127,7 @@ class ModalBlockView extends React.Component {
|
||||||
EventEmitter.addEventListener(viewId, this.handleUpdate);
|
EventEmitter.addEventListener(viewId, this.handleUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: IModalBlockViewProps) {
|
||||||
const { navigation, route } = this.props;
|
const { navigation, route } = this.props;
|
||||||
const oldData = prevProps.route.params?.data ?? {};
|
const oldData = prevProps.route.params?.data ?? {};
|
||||||
const newData = route.params?.data ?? {};
|
const newData = route.params?.data ?? {};
|
||||||
|
@ -128,7 +160,7 @@ class ModalBlockView extends React.Component {
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</HeaderButton.Container>
|
||||||
)
|
)
|
||||||
: null,
|
: undefined,
|
||||||
headerRight: submit
|
headerRight: submit
|
||||||
? () => (
|
? () => (
|
||||||
<HeaderButton.Container>
|
<HeaderButton.Container>
|
||||||
|
@ -140,13 +172,13 @@ class ModalBlockView extends React.Component {
|
||||||
/>
|
/>
|
||||||
</HeaderButton.Container>
|
</HeaderButton.Container>
|
||||||
)
|
)
|
||||||
: null
|
: undefined
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleUpdate = ({ type, ...data }) => {
|
handleUpdate = ({ type, ...data }: { type: string }) => {
|
||||||
if ([MODAL_ACTIONS.ERRORS].includes(type)) {
|
if ([MODAL_ACTIONS.ERRORS].includes(type)) {
|
||||||
const { errors } = data;
|
const { errors }: any = data;
|
||||||
this.setState({ errors });
|
this.setState({ errors });
|
||||||
} else {
|
} else {
|
||||||
this.setState({ data });
|
this.setState({ data });
|
||||||
|
@ -154,7 +186,7 @@ class ModalBlockView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cancel = async ({ closeModal }) => {
|
cancel = async ({ closeModal }: { closeModal?: () => void }) => {
|
||||||
const { data } = this.state;
|
const { data } = this.state;
|
||||||
const { appId, viewId, view } = data;
|
const { appId, viewId, view } = data;
|
||||||
|
|
||||||
|
@ -210,7 +242,7 @@ class ModalBlockView extends React.Component {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
action = async ({ actionId, value, blockId }) => {
|
action = async ({ actionId, value, blockId }: IActions) => {
|
||||||
const { data } = this.state;
|
const { data } = this.state;
|
||||||
const { mid, appId, viewId } = data;
|
const { mid, appId, viewId } = data;
|
||||||
await RocketChat.triggerBlockAction({
|
await RocketChat.triggerBlockAction({
|
||||||
|
@ -227,7 +259,7 @@ class ModalBlockView extends React.Component {
|
||||||
this.changeState({ actionId, value, blockId });
|
this.changeState({ actionId, value, blockId });
|
||||||
};
|
};
|
||||||
|
|
||||||
changeState = ({ actionId, value, blockId = 'default' }) => {
|
changeState = ({ actionId, value, blockId = 'default' }: IActions) => {
|
||||||
this.values[actionId] = {
|
this.values[actionId] = {
|
||||||
blockId,
|
blockId,
|
||||||
value
|
value
|
||||||
|
@ -266,7 +298,7 @@ class ModalBlockView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
language: state.login.user && state.login.user.language
|
language: state.login.user && state.login.user.language
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
@ -18,7 +19,6 @@ import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import { getUserSelector } from '../selectors/login';
|
|
||||||
import Navigation from '../lib/Navigation';
|
import Navigation from '../lib/Navigation';
|
||||||
import { createChannelRequest } from '../actions/createChannel';
|
import { createChannelRequest } from '../actions/createChannel';
|
||||||
import { goRoom } from '../utils/goRoom';
|
import { goRoom } from '../utils/goRoom';
|
||||||
|
@ -47,33 +47,54 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class NewMessageView extends React.Component {
|
interface IButton {
|
||||||
static navigationOptions = ({ navigation }) => ({
|
onPress: () => void;
|
||||||
|
testID: string;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
first?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISearch {
|
||||||
|
_id: string;
|
||||||
|
status: string;
|
||||||
|
username: string;
|
||||||
|
avatarETag: string;
|
||||||
|
outside: boolean;
|
||||||
|
rid: string;
|
||||||
|
name: string;
|
||||||
|
t: string;
|
||||||
|
search: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INewMessageViewState {
|
||||||
|
search: ISearch[];
|
||||||
|
// TODO: Refactor when migrate room
|
||||||
|
chats: any[];
|
||||||
|
permissions: boolean[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INewMessageViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'NewMessageView'>;
|
||||||
|
create: (params: { group: boolean }) => void;
|
||||||
|
maxUsers: number;
|
||||||
|
theme: string;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
serverVersion: string;
|
||||||
|
createTeamPermission: string[];
|
||||||
|
createDirectMessagePermission: string[];
|
||||||
|
createPublicChannelPermission: string[];
|
||||||
|
createPrivateChannelPermission: string[];
|
||||||
|
createDiscussionPermission: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class NewMessageView extends React.Component<INewMessageViewProps, INewMessageViewState> {
|
||||||
|
static navigationOptions = ({ navigation }: INewMessageViewProps): StackNavigationOptions => ({
|
||||||
headerLeft: () => <HeaderButton.CloseModal navigation={navigation} testID='new-message-view-close' />,
|
headerLeft: () => <HeaderButton.CloseModal navigation={navigation} testID='new-message-view-close' />,
|
||||||
title: I18n.t('New_Message')
|
title: I18n.t('New_Message')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: INewMessageViewProps) {
|
||||||
navigation: PropTypes.object,
|
|
||||||
baseUrl: PropTypes.string,
|
|
||||||
user: PropTypes.shape({
|
|
||||||
id: PropTypes.string,
|
|
||||||
token: PropTypes.string,
|
|
||||||
roles: PropTypes.array
|
|
||||||
}),
|
|
||||||
create: PropTypes.func,
|
|
||||||
maxUsers: PropTypes.number,
|
|
||||||
theme: PropTypes.string,
|
|
||||||
isMasterDetail: PropTypes.bool,
|
|
||||||
serverVersion: PropTypes.string,
|
|
||||||
createTeamPermission: PropTypes.array,
|
|
||||||
createDirectMessagePermission: PropTypes.array,
|
|
||||||
createPublicChannelPermission: PropTypes.array,
|
|
||||||
createPrivateChannelPermission: PropTypes.array,
|
|
||||||
createDiscussionPermission: PropTypes.array
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.init();
|
this.init();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -102,7 +123,7 @@ class NewMessageView extends React.Component {
|
||||||
this.handleHasPermission();
|
this.handleHasPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: INewMessageViewProps) {
|
||||||
const {
|
const {
|
||||||
createTeamPermission,
|
createTeamPermission,
|
||||||
createPublicChannelPermission,
|
createPublicChannelPermission,
|
||||||
|
@ -122,7 +143,7 @@ class NewMessageView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchChangeText(text) {
|
onSearchChangeText(text: string) {
|
||||||
this.search(text);
|
this.search(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +152,7 @@ class NewMessageView extends React.Component {
|
||||||
return navigation.pop();
|
return navigation.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
const result = await RocketChat.search({ text, filterRooms: false });
|
const result = await RocketChat.search({ text, filterRooms: false });
|
||||||
this.setState({
|
this.setState({
|
||||||
search: result
|
search: result
|
||||||
|
@ -162,7 +183,8 @@ class NewMessageView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
goRoom = item => {
|
// TODO: Refactor when migrate room
|
||||||
|
goRoom = (item: any) => {
|
||||||
logEvent(events.NEW_MSG_CHAT_WITH_USER);
|
logEvent(events.NEW_MSG_CHAT_WITH_USER);
|
||||||
const { isMasterDetail, navigation } = this.props;
|
const { isMasterDetail, navigation } = this.props;
|
||||||
if (isMasterDetail) {
|
if (isMasterDetail) {
|
||||||
|
@ -171,7 +193,7 @@ class NewMessageView extends React.Component {
|
||||||
goRoom({ item, isMasterDetail });
|
goRoom({ item, isMasterDetail });
|
||||||
};
|
};
|
||||||
|
|
||||||
renderButton = ({ onPress, testID, title, icon, first }) => {
|
renderButton = ({ onPress, testID, title, icon, first }: IButton) => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<Touch onPress={onPress} style={{ backgroundColor: themes[theme].backgroundColor }} testID={testID} theme={theme}>
|
<Touch onPress={onPress} style={{ backgroundColor: themes[theme].backgroundColor }} testID={testID} theme={theme}>
|
||||||
|
@ -218,7 +240,7 @@ class NewMessageView extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
||||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='new-message-view-search' />
|
<SearchBox onChangeText={(text: string) => this.onSearchChangeText(text)} testID='new-message-view-search' />
|
||||||
<View style={styles.buttonContainer}>
|
<View style={styles.buttonContainer}>
|
||||||
{permissions[0] || permissions[1]
|
{permissions[0] || permissions[1]
|
||||||
? this.renderButton({
|
? this.renderButton({
|
||||||
|
@ -258,9 +280,10 @@ class NewMessageView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item, index }) => {
|
// TODO: Refactor when migrate room
|
||||||
|
renderItem = ({ item, index }: { item: ISearch | any; index: number }) => {
|
||||||
const { search, chats } = this.state;
|
const { search, chats } = this.state;
|
||||||
const { baseUrl, user, theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
let style = { borderColor: themes[theme].separatorColor };
|
let style = { borderColor: themes[theme].separatorColor };
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
@ -277,10 +300,8 @@ class NewMessageView extends React.Component {
|
||||||
name={item.search ? item.name : item.fname}
|
name={item.search ? item.name : item.fname}
|
||||||
username={item.search ? item.username : item.name}
|
username={item.search ? item.username : item.name}
|
||||||
onPress={() => this.goRoom(item)}
|
onPress={() => this.goRoom(item)}
|
||||||
baseUrl={baseUrl}
|
|
||||||
testID={`new-message-view-item-${item.name}`}
|
testID={`new-message-view-item-${item.name}`}
|
||||||
style={style}
|
style={style}
|
||||||
user={user}
|
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -313,12 +334,10 @@ class NewMessageView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
serverVersion: state.server.version,
|
serverVersion: state.server.version,
|
||||||
isMasterDetail: state.app.isMasterDetail,
|
isMasterDetail: state.app.isMasterDetail,
|
||||||
baseUrl: state.server.server,
|
|
||||||
maxUsers: state.settings.DirectMesssage_maxUsers || 1,
|
maxUsers: state.settings.DirectMesssage_maxUsers || 1,
|
||||||
user: getUserSelector(state),
|
|
||||||
createTeamPermission: state.permissions['create-team'],
|
createTeamPermission: state.permissions['create-team'],
|
||||||
createDirectMessagePermission: state.permissions['create-d'],
|
createDirectMessagePermission: state.permissions['create-d'],
|
||||||
createPublicChannelPermission: state.permissions['create-c'],
|
createPublicChannelPermission: state.permissions['create-c'],
|
||||||
|
@ -326,8 +345,8 @@ const mapStateToProps = state => ({
|
||||||
createDiscussionPermission: state.permissions['start-discussion']
|
createDiscussionPermission: state.permissions['start-discussion']
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||||
create: params => dispatch(createChannelRequest(params))
|
create: (params: { group: boolean }) => dispatch(createChannelRequest(params))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
|
@ -33,6 +33,7 @@ import { isTablet } from '../../utils/deviceInfo';
|
||||||
import { verticalScale, moderateScale } from '../../utils/scaling';
|
import { verticalScale, moderateScale } from '../../utils/scaling';
|
||||||
import { withDimensions } from '../../dimensions';
|
import { withDimensions } from '../../dimensions';
|
||||||
import ServerInput from './ServerInput';
|
import ServerInput from './ServerInput';
|
||||||
|
import { OutsideParamList } from '../../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
onboardingImage: {
|
onboardingImage: {
|
||||||
|
@ -73,7 +74,7 @@ export interface IServer extends Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface INewServerView {
|
interface INewServerView {
|
||||||
navigation: StackNavigationProp<any, 'NewServerView'>;
|
navigation: StackNavigationProp<OutsideParamList, 'NewServerView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
connecting: boolean;
|
connecting: boolean;
|
||||||
connectServer(server: string, username?: string, fromServerHistory?: boolean): void;
|
connectServer(server: string, username?: string, fromServerHistory?: boolean): void;
|
||||||
|
|
|
@ -17,6 +17,7 @@ import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import log, { events, logEvent } from '../../utils/log';
|
import log, { events, logEvent } from '../../utils/log';
|
||||||
import sharedStyles from '../Styles';
|
import sharedStyles from '../Styles';
|
||||||
import { OPTIONS } from './options';
|
import { OPTIONS } from './options';
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
pickerText: {
|
pickerText: {
|
||||||
|
@ -26,16 +27,8 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface INotificationPreferencesView {
|
interface INotificationPreferencesView {
|
||||||
navigation: StackNavigationProp<any, 'NotificationPreferencesView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'NotificationPrefView'>;
|
||||||
route: RouteProp<
|
route: RouteProp<ChatsStackParamList, 'NotificationPrefView'>;
|
||||||
{
|
|
||||||
NotificationPreferencesView: {
|
|
||||||
rid: string;
|
|
||||||
room: Model;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
'NotificationPreferencesView'
|
|
||||||
>;
|
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface IOptionsField {
|
export interface IOptionsField {
|
||||||
label: string;
|
label: string;
|
||||||
value: string | number;
|
value: string | number;
|
||||||
second?: number;
|
second?: number;
|
||||||
|
|
|
@ -11,6 +11,8 @@ import * as List from '../containers/List';
|
||||||
import SearchBox from '../containers/SearchBox';
|
import SearchBox from '../containers/SearchBox';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
import { IOptionsField } from './NotificationPreferencesView/options';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
search: {
|
search: {
|
||||||
|
@ -25,37 +27,21 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IData {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
second?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IItem {
|
interface IItem {
|
||||||
item: IData;
|
item: IOptionsField;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
onItemPress: () => void;
|
onItemPress: () => void;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPickerViewState {
|
interface IPickerViewState {
|
||||||
data: IData[];
|
data: IOptionsField[];
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IParams {
|
|
||||||
title: string;
|
|
||||||
value: string;
|
|
||||||
data: IData[];
|
|
||||||
onChangeText: (value: string) => IData[];
|
|
||||||
goBack: boolean;
|
|
||||||
onChange: Function;
|
|
||||||
onChangeValue: (value: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IPickerViewProps {
|
interface IPickerViewProps {
|
||||||
navigation: StackNavigationProp<any, 'PickerView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'PickerView'>;
|
||||||
route: RouteProp<{ PickerView: IParams }, 'PickerView'>;
|
route: RouteProp<ChatsStackParamList, 'PickerView'>;
|
||||||
theme: string;
|
theme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +55,7 @@ const Item = React.memo(({ item, selected, onItemPress, theme }: IItem) => (
|
||||||
));
|
));
|
||||||
|
|
||||||
class PickerView extends React.PureComponent<IPickerViewProps, IPickerViewState> {
|
class PickerView extends React.PureComponent<IPickerViewProps, IPickerViewState> {
|
||||||
private onSearch: (text: string) => IData[];
|
private onSearch?: ((text: string) => IOptionsField[]) | ((term?: string | undefined) => Promise<any>);
|
||||||
|
|
||||||
static navigationOptions = ({ route }: IPickerViewProps) => ({
|
static navigationOptions = ({ route }: IPickerViewProps) => ({
|
||||||
title: route.params?.title ?? I18n.t('Select_an_option')
|
title: route.params?.title ?? I18n.t('Select_an_option')
|
||||||
|
@ -126,13 +112,13 @@ class PickerView extends React.PureComponent<IPickerViewProps, IPickerViewState>
|
||||||
{this.renderSearch()}
|
{this.renderSearch()}
|
||||||
<FlatList
|
<FlatList
|
||||||
data={data}
|
data={data}
|
||||||
keyExtractor={item => item.value}
|
keyExtractor={item => item.value as string}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<Item
|
<Item
|
||||||
item={item}
|
item={item}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
selected={!this.onSearch && (value || data[0]?.value) === item.value}
|
selected={!this.onSearch && (value || data[0]?.value) === item.value}
|
||||||
onItemPress={() => this.onChangeValue(item.value)}
|
onItemPress={() => this.onChangeValue(item.value as string)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { ProfileStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
export interface IUser {
|
export interface IUser {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -31,14 +33,12 @@ export interface IAvatarButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INavigationOptions {
|
export interface INavigationOptions {
|
||||||
navigation: StackNavigationProp<any, 'ProfileView'>;
|
navigation: StackNavigationProp<ProfileStackParamList, 'ProfileView'>;
|
||||||
isMasterDetail?: boolean;
|
isMasterDetail?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfileViewProps {
|
export interface IProfileViewProps {
|
||||||
user: IUser;
|
user: IUser;
|
||||||
navigation: StackNavigationProp<any, 'ProfileView'>;
|
|
||||||
isMasterDetail?: boolean;
|
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
Accounts_AllowEmailChange: boolean;
|
Accounts_AllowEmailChange: boolean;
|
||||||
Accounts_AllowPasswordChange: boolean;
|
Accounts_AllowPasswordChange: boolean;
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { withTheme } from '../../theme';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
interface IReceipts {
|
interface IReceipts {
|
||||||
_id: string;
|
_id: string;
|
||||||
|
@ -36,8 +37,8 @@ interface IReadReceiptViewState {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface INavigationOption {
|
interface INavigationOption {
|
||||||
navigation: StackNavigationProp<any, 'ReadReceiptView'>;
|
navigation: StackNavigationProp<ChatsStackParamList, 'ReadReceiptsView'>;
|
||||||
route: RouteProp<{ ReadReceiptView: { messageId: string } }, 'ReadReceiptView'>;
|
route: RouteProp<ChatsStackParamList, 'ReadReceiptsView'>;
|
||||||
isMasterDetail: boolean;
|
isMasterDetail: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { RouteProp } from '@react-navigation/core';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import RNPickerSelect from 'react-native-picker-select';
|
import RNPickerSelect from 'react-native-picker-select';
|
||||||
|
|
||||||
|
import { OutsideParamList } from '../stacks/types';
|
||||||
import log, { events, logEvent } from '../utils/log';
|
import log, { events, logEvent } from '../utils/log';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
@ -51,8 +52,8 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
navigation: StackNavigationProp<any>;
|
navigation: StackNavigationProp<OutsideParamList, 'RegisterView'>;
|
||||||
route: RouteProp<any, 'RegisterView'>;
|
route: RouteProp<OutsideParamList, 'RegisterView'>;
|
||||||
server: string;
|
server: string;
|
||||||
Site_Name: string;
|
Site_Name: string;
|
||||||
Gitlab_URL: string;
|
Gitlab_URL: string;
|
||||||
|
|
|
@ -918,7 +918,6 @@ class RoomActionsView extends React.Component {
|
||||||
event: this.convertTeamToChannel
|
event: this.convertTeamToChannel
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
testID='room-actions-convert-channel-to-team'
|
|
||||||
left={() => <List.Icon name='channel-public' />}
|
left={() => <List.Icon name='channel-public' />}
|
||||||
showActionIndicator
|
showActionIndicator
|
||||||
/>
|
/>
|
||||||
|
@ -1198,23 +1197,6 @@ class RoomActionsView extends React.Component {
|
||||||
<List.Separator />
|
<List.Separator />
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{['l'].includes(t) && !this.isOmnichannelPreview ? (
|
|
||||||
<>
|
|
||||||
<List.Item
|
|
||||||
title='Navigation_history'
|
|
||||||
onPress={() =>
|
|
||||||
this.onPressTouchable({
|
|
||||||
route: 'VisitorNavigationView',
|
|
||||||
params: { rid }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
left={() => <List.Icon name='history' />}
|
|
||||||
showActionIndicator
|
|
||||||
/>
|
|
||||||
<List.Separator />
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</List.Section>
|
</List.Section>
|
||||||
|
|
||||||
{this.renderLastSection()}
|
{this.renderLastSection()}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Switch } from 'react-native';
|
import { Switch } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||||
|
import Model from '@nozbe/watermelondb/Model';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
|
@ -16,19 +18,42 @@ import { events, logEvent } from '../utils/log';
|
||||||
|
|
||||||
const DEFAULT_BIOMETRY = false;
|
const DEFAULT_BIOMETRY = false;
|
||||||
|
|
||||||
class ScreenLockConfigView extends React.Component {
|
interface IServerRecords extends Model {
|
||||||
static navigationOptions = () => ({
|
autoLock?: boolean;
|
||||||
|
autoLockTime?: number;
|
||||||
|
biometry?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IItem {
|
||||||
|
title: string;
|
||||||
|
value: number;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IScreenLockConfigViewProps {
|
||||||
|
theme: string;
|
||||||
|
server: string;
|
||||||
|
Force_Screen_Lock: boolean;
|
||||||
|
Force_Screen_Lock_After: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IScreenLockConfigViewState {
|
||||||
|
autoLock?: boolean;
|
||||||
|
autoLockTime?: number | null;
|
||||||
|
biometry?: boolean;
|
||||||
|
biometryLabel: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScreenLockConfigView extends React.Component<IScreenLockConfigViewProps, IScreenLockConfigViewState> {
|
||||||
|
private serverRecord?: IServerRecords;
|
||||||
|
|
||||||
|
private observable?: Subscription;
|
||||||
|
|
||||||
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Screen_lock')
|
title: I18n.t('Screen_lock')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
constructor(props: IScreenLockConfigViewProps) {
|
||||||
theme: PropTypes.string,
|
|
||||||
server: PropTypes.string,
|
|
||||||
Force_Screen_Lock: PropTypes.string,
|
|
||||||
Force_Screen_Lock_After: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
autoLock: false,
|
autoLock: false,
|
||||||
|
@ -104,7 +129,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
logEvent(events.SLC_SAVE_SCREEN_LOCK);
|
logEvent(events.SLC_SAVE_SCREEN_LOCK);
|
||||||
const { autoLock, autoLockTime, biometry } = this.state;
|
const { autoLock, autoLockTime, biometry } = this.state;
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
await serversDB.action(async () => {
|
await serversDB.write(async () => {
|
||||||
await this.serverRecord?.update(record => {
|
await this.serverRecord?.update(record => {
|
||||||
record.autoLock = autoLock;
|
record.autoLock = autoLock;
|
||||||
record.autoLockTime = autoLockTime === null ? DEFAULT_AUTO_LOCK : autoLockTime;
|
record.autoLockTime = autoLockTime === null ? DEFAULT_AUTO_LOCK : autoLockTime;
|
||||||
|
@ -113,7 +138,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
changePasscode = async ({ force }) => {
|
changePasscode = async ({ force }: { force: boolean }) => {
|
||||||
logEvent(events.SLC_CHANGE_PASSCODE);
|
logEvent(events.SLC_CHANGE_PASSCODE);
|
||||||
await changePasscode({ force });
|
await changePasscode({ force });
|
||||||
};
|
};
|
||||||
|
@ -144,12 +169,12 @@ class ScreenLockConfigView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
isSelected = value => {
|
isSelected = (value: number) => {
|
||||||
const { autoLockTime } = this.state;
|
const { autoLockTime } = this.state;
|
||||||
return autoLockTime === value;
|
return autoLockTime === value;
|
||||||
};
|
};
|
||||||
|
|
||||||
changeAutoLockTime = autoLockTime => {
|
changeAutoLockTime = (autoLockTime: number) => {
|
||||||
logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
|
logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
|
||||||
this.setState({ autoLockTime }, () => this.save());
|
this.setState({ autoLockTime }, () => this.save());
|
||||||
};
|
};
|
||||||
|
@ -159,7 +184,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
return <List.Icon name='check' color={themes[theme].tintColor} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IItem }) => {
|
||||||
const { title, value, disabled } = item;
|
const { title, value, disabled } = item;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -194,7 +219,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
if (!autoLock) {
|
if (!autoLock) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let items = this.defaultAutoLockOptions;
|
let items: IItem[] = this.defaultAutoLockOptions;
|
||||||
if (Force_Screen_Lock && Force_Screen_Lock_After > 0) {
|
if (Force_Screen_Lock && Force_Screen_Lock_After > 0) {
|
||||||
items = [
|
items = [
|
||||||
{
|
{
|
||||||
|
@ -262,7 +287,7 @@ class ScreenLockConfigView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
Force_Screen_Lock: state.settings.Force_Screen_Lock,
|
Force_Screen_Lock: state.settings.Force_Screen_Lock,
|
||||||
Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After
|
Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After
|
|
@ -1,19 +1,25 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
import useDeepCompareEffect from 'use-deep-compare-effect';
|
import useDeepCompareEffect from 'use-deep-compare-effect';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import Orientation from 'react-native-orientation-locker';
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import { withTheme } from '../theme';
|
import { useTheme } from '../theme';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { LOCAL_AUTHENTICATE_EMITTER } from '../constants/localAuthentication';
|
import { LOCAL_AUTHENTICATE_EMITTER } from '../constants/localAuthentication';
|
||||||
import { isTablet } from '../utils/deviceInfo';
|
import { isTablet } from '../utils/deviceInfo';
|
||||||
import { PasscodeEnter } from '../containers/Passcode';
|
import { PasscodeEnter } from '../containers/Passcode';
|
||||||
|
|
||||||
const ScreenLockedView = ({ theme }) => {
|
interface IData {
|
||||||
|
submit?: () => void;
|
||||||
|
hasBiometry?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ScreenLockedView = (): JSX.Element => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState<IData>({});
|
||||||
|
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
useDeepCompareEffect(() => {
|
useDeepCompareEffect(() => {
|
||||||
if (!isEmpty(data)) {
|
if (!isEmpty(data)) {
|
||||||
|
@ -23,7 +29,7 @@ const ScreenLockedView = ({ theme }) => {
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const showScreenLock = args => {
|
const showScreenLock = (args: IData) => {
|
||||||
setData(args);
|
setData(args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,13 +62,9 @@ const ScreenLockedView = ({ theme }) => {
|
||||||
style={{ margin: 0 }}
|
style={{ margin: 0 }}
|
||||||
animationIn='fadeIn'
|
animationIn='fadeIn'
|
||||||
animationOut='fadeOut'>
|
animationOut='fadeOut'>
|
||||||
<PasscodeEnter theme={theme} hasBiometry={data?.hasBiometry} finishProcess={onSubmit} />
|
<PasscodeEnter theme={theme} hasBiometry={!!data?.hasBiometry} finishProcess={onSubmit} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreenLockedView.propTypes = {
|
export default ScreenLockedView;
|
||||||
theme: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withTheme(ScreenLockedView);
|
|
|
@ -1,11 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { RouteProp } from '@react-navigation/core';
|
import { CompositeNavigationProp, RouteProp } from '@react-navigation/core';
|
||||||
import { FlatList, Text, View } from 'react-native';
|
import { FlatList, Text, View } from 'react-native';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
|
||||||
|
import { IRoom, RoomType } from '../../definitions/IRoom';
|
||||||
|
import { IAttachment } from '../../definitions/IAttachment';
|
||||||
import RCTextInput from '../../containers/TextInput';
|
import RCTextInput from '../../containers/TextInput';
|
||||||
import ActivityIndicator from '../../containers/ActivityIndicator';
|
import ActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import Markdown from '../../containers/markdown';
|
import Markdown from '../../containers/markdown';
|
||||||
|
@ -13,7 +15,7 @@ import debounce from '../../utils/debounce';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import Message from '../../containers/message';
|
import Message from '../../containers/message';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import { IMessage, IMessageAttachments } from '../../containers/message/interfaces';
|
import { IMessage } from '../../containers/message/interfaces';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import StatusBar from '../../containers/StatusBar';
|
import StatusBar from '../../containers/StatusBar';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
|
@ -29,26 +31,30 @@ import getRoomInfo from '../../lib/methods/getRoomInfo';
|
||||||
import { isIOS } from '../../utils/deviceInfo';
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
import { compareServerVersion, methods } from '../../lib/utils';
|
import { compareServerVersion, methods } from '../../lib/utils';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { InsideStackParamList, ChatsStackParamList } from '../../stacks/types';
|
||||||
|
|
||||||
const QUERY_SIZE = 50;
|
const QUERY_SIZE = 50;
|
||||||
|
|
||||||
type TRouteParams = {
|
|
||||||
SearchMessagesView: {
|
|
||||||
showCloseModal?: boolean;
|
|
||||||
rid: string;
|
|
||||||
t?: string;
|
|
||||||
encrypted?: boolean;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
interface ISearchMessagesViewState {
|
interface ISearchMessagesViewState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
messages: IMessage[];
|
messages: IMessage[];
|
||||||
searchText: string;
|
searchText: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IRoomInfoParam {
|
||||||
|
room: IRoom;
|
||||||
|
member: any;
|
||||||
|
rid: string;
|
||||||
|
t: RoomType;
|
||||||
|
joined: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface INavigationOption {
|
interface INavigationOption {
|
||||||
navigation: StackNavigationProp<any, 'SearchMessagesView'>;
|
navigation: CompositeNavigationProp<
|
||||||
route: RouteProp<TRouteParams, 'SearchMessagesView'>;
|
StackNavigationProp<ChatsStackParamList, 'SearchMessagesView'>,
|
||||||
|
StackNavigationProp<InsideStackParamList>
|
||||||
|
>;
|
||||||
|
route: RouteProp<ChatsStackParamList, 'SearchMessagesView'>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISearchMessagesViewProps extends INavigationOption {
|
interface ISearchMessagesViewProps extends INavigationOption {
|
||||||
|
@ -183,12 +189,12 @@ class SearchMessagesView extends React.Component<ISearchMessagesViewProps, ISear
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
showAttachment = (attachment: IMessageAttachments) => {
|
showAttachment = (attachment: IAttachment) => {
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
navigation.navigate('AttachmentView', { attachment });
|
navigation.navigate('AttachmentView', { attachment });
|
||||||
};
|
};
|
||||||
|
|
||||||
navToRoomInfo = (navParam: IMessage) => {
|
navToRoomInfo = (navParam: IRoomInfoParam) => {
|
||||||
const { navigation, user } = this.props;
|
const { navigation, user } = this.props;
|
||||||
if (navParam.rid === user.id) {
|
if (navParam.rid === user.id) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Switch } from 'react-native';
|
import { Switch } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
@ -20,11 +20,15 @@ import {
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import { isFDroidBuild } from '../constants/environment';
|
import { isFDroidBuild } from '../constants/environment';
|
||||||
|
|
||||||
const SecurityPrivacyView = ({ navigation }) => {
|
interface ISecurityPrivacyViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SecurityPrivacyView'>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SecurityPrivacyView = ({ navigation }: ISecurityPrivacyViewProps): JSX.Element => {
|
||||||
const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
|
const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
|
||||||
const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
|
const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
|
||||||
|
|
||||||
const e2eEnabled = useSelector(state => state.settings.E2E_Enable);
|
const e2eEnabled = useSelector((state: any) => state.settings.E2E_Enable);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
|
@ -32,21 +36,22 @@ const SecurityPrivacyView = ({ navigation }) => {
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleCrashReport = value => {
|
const toggleCrashReport = (value: boolean) => {
|
||||||
logEvent(events.SE_TOGGLE_CRASH_REPORT);
|
logEvent(events.SP_TOGGLE_CRASH_REPORT);
|
||||||
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
|
AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
|
||||||
setCrashReportState(value);
|
setCrashReportState(value);
|
||||||
toggleCrashErrorsReport(value);
|
toggleCrashErrorsReport(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleAnalyticsEvents = value => {
|
const toggleAnalyticsEvents = (value: boolean) => {
|
||||||
logEvent(events.SE_TOGGLE_ANALYTICS_EVENTS);
|
logEvent(events.SP_TOGGLE_ANALYTICS_EVENTS);
|
||||||
AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value));
|
AsyncStorage.setItem(ANALYTICS_EVENTS_KEY, JSON.stringify(value));
|
||||||
setAnalyticsEventsState(value);
|
setAnalyticsEventsState(value);
|
||||||
toggleAnalyticsEventsReport(value);
|
toggleAnalyticsEventsReport(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateToScreen = screen => {
|
const navigateToScreen = (screen: 'E2EEncryptionSecurityView' | 'ScreenLockConfigView') => {
|
||||||
|
// @ts-ignore
|
||||||
logEvent(events[`SP_GO_${screen.replace('View', '').toUpperCase()}`]);
|
logEvent(events[`SP_GO_${screen.replace('View', '').toUpperCase()}`]);
|
||||||
navigation.navigate(screen);
|
navigation.navigate(screen);
|
||||||
};
|
};
|
||||||
|
@ -106,8 +111,4 @@ const SecurityPrivacyView = ({ navigation }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
SecurityPrivacyView.propTypes = {
|
|
||||||
navigation: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SecurityPrivacyView;
|
export default SecurityPrivacyView;
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RadioButton } from 'react-native-ui-lib';
|
import { RadioButton } from 'react-native-ui-lib';
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
@ -25,15 +26,58 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class SelectListView extends React.Component {
|
interface IData {
|
||||||
static propTypes = {
|
rid: string;
|
||||||
navigation: PropTypes.object,
|
name: string;
|
||||||
route: PropTypes.object,
|
t?: string;
|
||||||
theme: PropTypes.string,
|
teamMain?: boolean;
|
||||||
isMasterDetail: PropTypes.bool
|
alert?: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
constructor(props) {
|
interface ISelectListViewState {
|
||||||
|
data: IData[];
|
||||||
|
dataFiltered: IData[];
|
||||||
|
isSearching: boolean;
|
||||||
|
selected: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectListViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SelectListView'>;
|
||||||
|
route: RouteProp<
|
||||||
|
{
|
||||||
|
SelectView: {
|
||||||
|
data: IData[];
|
||||||
|
title: string;
|
||||||
|
infoText: string;
|
||||||
|
nextAction(selected: string[]): void;
|
||||||
|
showAlert(): void;
|
||||||
|
isSearch: boolean;
|
||||||
|
onSearch(text: string): IData[];
|
||||||
|
isRadio: boolean;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'SelectView'
|
||||||
|
>;
|
||||||
|
theme: string;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectListView extends React.Component<ISelectListViewProps, ISelectListViewState> {
|
||||||
|
private title: string;
|
||||||
|
|
||||||
|
private infoText: string;
|
||||||
|
|
||||||
|
private nextAction: (selected: string[]) => void;
|
||||||
|
|
||||||
|
private showAlert: () => void;
|
||||||
|
|
||||||
|
private isSearch: boolean;
|
||||||
|
|
||||||
|
private onSearch: (text: string) => IData[];
|
||||||
|
|
||||||
|
private isRadio: boolean;
|
||||||
|
|
||||||
|
constructor(props: ISelectListViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
const data = props.route?.params?.data;
|
const data = props.route?.params?.data;
|
||||||
this.title = props.route?.params?.title;
|
this.title = props.route?.params?.title;
|
||||||
|
@ -56,7 +100,7 @@ class SelectListView extends React.Component {
|
||||||
const { navigation, isMasterDetail } = this.props;
|
const { navigation, isMasterDetail } = this.props;
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
const options = {
|
const options: StackNavigationOptions = {
|
||||||
headerTitle: I18n.t(this.title)
|
headerTitle: I18n.t(this.title)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,7 +131,7 @@ class SelectListView extends React.Component {
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
<View style={{ backgroundColor: themes[theme].auxiliaryBackground }}>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
onChangeText={text => this.search(text)}
|
onChangeText={(text: string) => this.search(text)}
|
||||||
testID='select-list-view-search'
|
testID='select-list-view-search'
|
||||||
onCancelPress={() => this.setState({ isSearching: false })}
|
onCancelPress={() => this.setState({ isSearching: false })}
|
||||||
/>
|
/>
|
||||||
|
@ -95,7 +139,7 @@ class SelectListView extends React.Component {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
try {
|
try {
|
||||||
this.setState({ isSearching: true });
|
this.setState({ isSearching: true });
|
||||||
const result = await this.onSearch(text);
|
const result = await this.onSearch(text);
|
||||||
|
@ -105,12 +149,12 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
isChecked = rid => {
|
isChecked = (rid: string) => {
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
return selected.includes(rid);
|
return selected.includes(rid);
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleItem = rid => {
|
toggleItem = (rid: string) => {
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
animateNextTransition();
|
animateNextTransition();
|
||||||
|
@ -126,7 +170,7 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IData }) => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
const { selected } = this.state;
|
const { selected } = this.state;
|
||||||
|
|
||||||
|
@ -187,7 +231,7 @@ class SelectListView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
isMasterDetail: state.app.isMasterDetail
|
isMasterDetail: state.app.isMasterDetail
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FlatList } from 'react-native';
|
import { FlatList } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q, Model } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
@ -12,29 +12,39 @@ import database from '../lib/database';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
|
||||||
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
const getItemLayout = (data: any, index: number) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||||
const keyExtractor = item => item.id;
|
const keyExtractor = (item: IServer) => item.id;
|
||||||
|
|
||||||
class SelectServerView extends React.Component {
|
interface IServer extends Model {
|
||||||
static navigationOptions = () => ({
|
id: string;
|
||||||
|
iconURL?: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectServerViewState {
|
||||||
|
servers: IServer[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISelectServerViewProps {
|
||||||
|
navigation: StackNavigationProp<any, 'SelectServerView'>;
|
||||||
|
server: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectServerView extends React.Component<ISelectServerViewProps, ISelectServerViewState> {
|
||||||
|
static navigationOptions = (): StackNavigationOptions => ({
|
||||||
title: I18n.t('Select_Server')
|
title: I18n.t('Select_Server')
|
||||||
});
|
});
|
||||||
|
|
||||||
static propTypes = {
|
state = { servers: [] as IServer[] };
|
||||||
server: PropTypes.string,
|
|
||||||
navigation: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
state = { servers: [] };
|
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
const servers = await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch();
|
const servers: IServer[] = await serversCollection.query(Q.where('rooms_updated_at', Q.notEq(null))).fetch();
|
||||||
this.setState({ servers });
|
this.setState({ servers });
|
||||||
}
|
}
|
||||||
|
|
||||||
select = async server => {
|
select = async (server: string) => {
|
||||||
const { server: currentServer, navigation } = this.props;
|
const { server: currentServer, navigation } = this.props;
|
||||||
|
|
||||||
navigation.navigate('ShareListView');
|
navigation.navigate('ShareListView');
|
||||||
|
@ -43,7 +53,7 @@ class SelectServerView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
renderItem = ({ item }: { item: IServer }) => {
|
||||||
const { server } = this.props;
|
const { server } = this.props;
|
||||||
return <ServerItem onPress={() => this.select(item.id)} item={item} hasCheck={item.id === server} />;
|
return <ServerItem onPress={() => this.select(item.id)} item={item} hasCheck={item.id === server} />;
|
||||||
};
|
};
|
||||||
|
@ -62,7 +72,6 @@ class SelectServerView extends React.Component {
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
ListHeaderComponent={List.Separator}
|
ListHeaderComponent={List.Separator}
|
||||||
ListFooterComponent={List.Separator}
|
ListFooterComponent={List.Separator}
|
||||||
enableEmptySections
|
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
/>
|
/>
|
||||||
|
@ -71,7 +80,7 @@ class SelectServerView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({ share }) => ({
|
const mapStateToProps = ({ share }: any) => ({
|
||||||
server: share.server.server
|
server: share.server.server
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
import { FlatList, View } from 'react-native';
|
import { FlatList, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
|
@ -22,33 +24,51 @@ import { addUser as addUserAction, removeUser as removeUserAction, reset as rese
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
|
||||||
const ITEM_WIDTH = 250;
|
const ITEM_WIDTH = 250;
|
||||||
const getItemLayout = (_, index) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
|
const getItemLayout = (_: any, index: number) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
|
||||||
|
|
||||||
class SelectedUsersView extends React.Component {
|
interface IUser {
|
||||||
static propTypes = {
|
_id: string;
|
||||||
baseUrl: PropTypes.string,
|
name: string;
|
||||||
addUser: PropTypes.func.isRequired,
|
fname: string;
|
||||||
removeUser: PropTypes.func.isRequired,
|
search?: boolean;
|
||||||
reset: PropTypes.func.isRequired,
|
// username is used when is from searching
|
||||||
users: PropTypes.array,
|
username?: string;
|
||||||
loading: PropTypes.bool,
|
}
|
||||||
user: PropTypes.shape({
|
interface ISelectedUsersViewState {
|
||||||
id: PropTypes.string,
|
maxUsers?: number;
|
||||||
token: PropTypes.string,
|
search: IUser[];
|
||||||
username: PropTypes.string,
|
chats: IUser[];
|
||||||
name: PropTypes.string
|
}
|
||||||
}),
|
|
||||||
navigation: PropTypes.object,
|
interface ISelectedUsersViewProps {
|
||||||
route: PropTypes.object,
|
navigation: StackNavigationProp<ChatsStackParamList, 'SelectedUsersView'>;
|
||||||
theme: PropTypes.string
|
route: RouteProp<ChatsStackParamList, 'SelectedUsersView'>;
|
||||||
|
baseUrl: string;
|
||||||
|
addUser(user: IUser): void;
|
||||||
|
removeUser(user: IUser): void;
|
||||||
|
reset(): void;
|
||||||
|
users: IUser[];
|
||||||
|
loading: boolean;
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
token: string;
|
||||||
|
username: string;
|
||||||
|
name: string;
|
||||||
};
|
};
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelectedUsersViewState> {
|
||||||
|
private flatlist?: FlatList;
|
||||||
|
|
||||||
|
private querySubscription?: Subscription;
|
||||||
|
|
||||||
|
constructor(props: ISelectedUsersViewProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.init();
|
this.init();
|
||||||
this.flatlist = React.createRef();
|
|
||||||
const maxUsers = props.route.params?.maxUsers;
|
const maxUsers = props.route.params?.maxUsers;
|
||||||
this.state = {
|
this.state = {
|
||||||
maxUsers,
|
maxUsers,
|
||||||
|
@ -62,7 +82,7 @@ class SelectedUsersView extends React.Component {
|
||||||
this.setHeader(props.route.params?.showButton);
|
this.setHeader(props.route.params?.showButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: ISelectedUsersViewProps) {
|
||||||
if (this.isGroupChat()) {
|
if (this.isGroupChat()) {
|
||||||
const { users } = this.props;
|
const { users } = this.props;
|
||||||
if (prevProps.users.length !== users.length) {
|
if (prevProps.users.length !== users.length) {
|
||||||
|
@ -80,7 +100,7 @@ class SelectedUsersView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
// showButton can be sent as route params or updated by the component
|
// showButton can be sent as route params or updated by the component
|
||||||
setHeader = showButton => {
|
setHeader = (showButton?: boolean) => {
|
||||||
const { navigation, route } = this.props;
|
const { navigation, route } = this.props;
|
||||||
const title = route.params?.title ?? I18n.t('Select_Users');
|
const title = route.params?.title ?? I18n.t('Select_Users');
|
||||||
const buttonText = route.params?.buttonText ?? I18n.t('Next');
|
const buttonText = route.params?.buttonText ?? I18n.t('Next');
|
||||||
|
@ -107,7 +127,8 @@ class SelectedUsersView extends React.Component {
|
||||||
.query(Q.where('t', 'd'))
|
.query(Q.where('t', 'd'))
|
||||||
.observeWithColumns(['room_updated_at']);
|
.observeWithColumns(['room_updated_at']);
|
||||||
|
|
||||||
this.querySubscription = observable.subscribe(data => {
|
// TODO: Refactor when migrate room
|
||||||
|
this.querySubscription = observable.subscribe((data: any) => {
|
||||||
const chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
|
const chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
|
||||||
this.setState({ chats });
|
this.setState({ chats });
|
||||||
});
|
});
|
||||||
|
@ -116,11 +137,11 @@ class SelectedUsersView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onSearchChangeText(text) {
|
onSearchChangeText(text: string) {
|
||||||
this.search(text);
|
this.search(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
search = async text => {
|
search = async (text: string) => {
|
||||||
const result = await RocketChat.search({ text, filterRooms: false });
|
const result = await RocketChat.search({ text, filterRooms: false });
|
||||||
this.setState({
|
this.setState({
|
||||||
search: result
|
search: result
|
||||||
|
@ -129,15 +150,15 @@ class SelectedUsersView extends React.Component {
|
||||||
|
|
||||||
isGroupChat = () => {
|
isGroupChat = () => {
|
||||||
const { maxUsers } = this.state;
|
const { maxUsers } = this.state;
|
||||||
return maxUsers > 2;
|
return maxUsers! > 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
isChecked = username => {
|
isChecked = (username: string) => {
|
||||||
const { users } = this.props;
|
const { users } = this.props;
|
||||||
return users.findIndex(el => el.name === username) !== -1;
|
return users.findIndex(el => el.name === username) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleUser = user => {
|
toggleUser = (user: IUser) => {
|
||||||
const { maxUsers } = this.state;
|
const { maxUsers } = this.state;
|
||||||
const {
|
const {
|
||||||
addUser,
|
addUser,
|
||||||
|
@ -163,29 +184,29 @@ class SelectedUsersView extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onPressItem = (id, item = {}) => {
|
_onPressItem = (id: string, item = {} as IUser) => {
|
||||||
if (item.search) {
|
if (item.search) {
|
||||||
this.toggleUser({ _id: item._id, name: item.username, fname: item.name });
|
this.toggleUser({ _id: item._id, name: item.username!, fname: item.name });
|
||||||
} else {
|
} else {
|
||||||
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
|
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onPressSelectedItem = item => this.toggleUser(item);
|
_onPressSelectedItem = (item: IUser) => this.toggleUser(item);
|
||||||
|
|
||||||
renderHeader = () => {
|
renderHeader = () => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: themes[theme].backgroundColor }}>
|
<View style={{ backgroundColor: themes[theme].backgroundColor }}>
|
||||||
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='select-users-view-search' />
|
<SearchBox onChangeText={(text: string) => this.onSearchChangeText(text)} testID='select-users-view-search' />
|
||||||
{this.renderSelected()}
|
{this.renderSelected()}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
setFlatListRef = ref => (this.flatlist = ref);
|
setFlatListRef = (ref: FlatList) => (this.flatlist = ref);
|
||||||
|
|
||||||
onContentSizeChange = () => this.flatlist.scrollToEnd({ animated: true });
|
onContentSizeChange = () => this.flatlist?.scrollToEnd({ animated: true });
|
||||||
|
|
||||||
renderSelected = () => {
|
renderSelected = () => {
|
||||||
const { users, theme } = this.props;
|
const { users, theme } = this.props;
|
||||||
|
@ -204,35 +225,32 @@ class SelectedUsersView extends React.Component {
|
||||||
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
|
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
|
||||||
contentContainerStyle={{ marginVertical: 5 }}
|
contentContainerStyle={{ marginVertical: 5 }}
|
||||||
renderItem={this.renderSelectedItem}
|
renderItem={this.renderSelectedItem}
|
||||||
enableEmptySections
|
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
horizontal
|
horizontal
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderSelectedItem = ({ item }) => {
|
renderSelectedItem = ({ item }: { item: IUser }) => {
|
||||||
const { baseUrl, user, theme } = this.props;
|
const { theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<UserItem
|
<UserItem
|
||||||
name={item.fname}
|
name={item.fname}
|
||||||
username={item.name}
|
username={item.name}
|
||||||
onPress={() => this._onPressSelectedItem(item)}
|
onPress={() => this._onPressSelectedItem(item)}
|
||||||
testID={`selected-user-${item.name}`}
|
testID={`selected-user-${item.name}`}
|
||||||
baseUrl={baseUrl}
|
|
||||||
style={{ paddingRight: 15 }}
|
style={{ paddingRight: 15 }}
|
||||||
user={user}
|
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item, index }) => {
|
renderItem = ({ item, index }: { item: IUser; index: number }) => {
|
||||||
const { search, chats } = this.state;
|
const { search, chats } = this.state;
|
||||||
const { baseUrl, user, theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
const name = item.search ? item.name : item.fname;
|
const name = item.search ? item.name : item.fname;
|
||||||
const username = item.search ? item.username : item.name;
|
const username = item.search ? item.username! : item.name;
|
||||||
let style = { borderColor: themes[theme].separatorColor };
|
let style = { borderColor: themes[theme].separatorColor };
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
style = { ...style, ...sharedStyles.separatorTop };
|
style = { ...style, ...sharedStyles.separatorTop };
|
||||||
|
@ -250,9 +268,7 @@ class SelectedUsersView extends React.Component {
|
||||||
onPress={() => this._onPressItem(item._id, item)}
|
onPress={() => this._onPressItem(item._id, item)}
|
||||||
testID={`select-users-view-item-${item.name}`}
|
testID={`select-users-view-item-${item.name}`}
|
||||||
icon={this.isChecked(username) ? 'check' : null}
|
icon={this.isChecked(username) ? 'check' : null}
|
||||||
baseUrl={baseUrl}
|
|
||||||
style={style}
|
style={style}
|
||||||
user={user}
|
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -275,7 +291,6 @@ class SelectedUsersView extends React.Component {
|
||||||
ItemSeparatorComponent={List.Separator}
|
ItemSeparatorComponent={List.Separator}
|
||||||
ListHeaderComponent={this.renderHeader}
|
ListHeaderComponent={this.renderHeader}
|
||||||
contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
|
contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
|
||||||
enableEmptySections
|
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -293,16 +308,16 @@ class SelectedUsersView extends React.Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state: any) => ({
|
||||||
baseUrl: state.server.server,
|
baseUrl: state.server.server,
|
||||||
users: state.selectedUsers.users,
|
users: state.selectedUsers.users,
|
||||||
loading: state.selectedUsers.loading,
|
loading: state.selectedUsers.loading,
|
||||||
user: getUserSelector(state)
|
user: getUserSelector(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch: any) => ({
|
||||||
addUser: user => dispatch(addUserAction(user)),
|
addUser: (user: any) => dispatch(addUserAction(user)),
|
||||||
removeUser: user => dispatch(removeUserAction(user)),
|
removeUser: (user: any) => dispatch(removeUserAction(user)),
|
||||||
reset: () => dispatch(resetAction())
|
reset: () => dispatch(resetAction())
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { RouteProp } from '@react-navigation/core';
|
||||||
|
|
||||||
|
import { OutsideParamList } from '../stacks/types';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
|
@ -12,16 +14,12 @@ import FormContainer, { FormContainerInner } from '../containers/FormContainer';
|
||||||
import log, { events, logEvent } from '../utils/log';
|
import log, { events, logEvent } from '../utils/log';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
interface ISendEmailConfirmationView {
|
interface ISendEmailConfirmationViewProps {
|
||||||
navigation: StackNavigationProp<any, 'SendEmailConfirmationView'>;
|
navigation: StackNavigationProp<OutsideParamList, 'SendEmailConfirmationView'>;
|
||||||
route: {
|
route: RouteProp<OutsideParamList, 'SendEmailConfirmationView'>;
|
||||||
params: {
|
|
||||||
user?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmationView): JSX.Element => {
|
const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmationViewProps): JSX.Element => {
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [invalidEmail, setInvalidEmail] = useState(true);
|
const [invalidEmail, setInvalidEmail] = useState(true);
|
||||||
const [isFetching, setIsFetching] = useState(false);
|
const [isFetching, setIsFetching] = useState(false);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue