diff --git a/app/containers/FormContainer.tsx b/app/containers/FormContainer.tsx
index 46522508..3a784b38 100644
--- a/app/containers/FormContainer.tsx
+++ b/app/containers/FormContainer.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { ScrollView, StyleSheet, View } from 'react-native';
+import { ScrollView, ScrollViewProps, StyleSheet, View } from 'react-native';
import { themes } from '../constants/colors';
import sharedStyles from '../views/Styles';
@@ -10,10 +10,10 @@ import AppVersion from './AppVersion';
import { isTablet } from '../utils/deviceInfo';
import SafeAreaView from './SafeAreaView';
-interface IFormContainer {
+interface IFormContainer extends ScrollViewProps {
theme: string;
testID: string;
- children: JSX.Element;
+ children: React.ReactNode;
}
const styles = StyleSheet.create({
diff --git a/app/utils/scaling.js b/app/utils/scaling.js
deleted file mode 100644
index 7cf33f1f..00000000
--- a/app/utils/scaling.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { isTablet } from './deviceInfo';
-
-const guidelineBaseWidth = isTablet ? 600 : 375;
-const guidelineBaseHeight = isTablet ? 800 : 667;
-
-// TODO: we need to refactor this
-const scale = (size, width) => (width / guidelineBaseWidth) * size;
-const verticalScale = (size, height) => (height / guidelineBaseHeight) * size;
-const moderateScale = (size, factor = 0.5, width) => size + (scale(size, width) - size) * factor;
-
-export { scale, verticalScale, moderateScale };
diff --git a/app/utils/scaling.ts b/app/utils/scaling.ts
new file mode 100644
index 00000000..45d248d3
--- /dev/null
+++ b/app/utils/scaling.ts
@@ -0,0 +1,16 @@
+import { isTablet } from './deviceInfo';
+
+const guidelineBaseWidth = isTablet ? 600 : 375;
+const guidelineBaseHeight = isTablet ? 800 : 667;
+
+function scale({ size, width }: { size: number; width: number }): number {
+ return (width / guidelineBaseWidth) * size;
+}
+function verticalScale({ size, height }: { size: number; height: number }): number {
+ return (height / guidelineBaseHeight) * size;
+}
+function moderateScale({ size, factor = 0.5, width }: { size: number; factor?: number; width: number }): number {
+ return size + (scale({ size, width }) - size) * factor;
+}
+
+export { scale, verticalScale, moderateScale };
diff --git a/app/views/NewServerView/ServerInput/Item.js b/app/views/NewServerView/ServerInput/Item.tsx
similarity index 79%
rename from app/views/NewServerView/ServerInput/Item.js
rename to app/views/NewServerView/ServerInput/Item.tsx
index 59ae77f0..9fb44719 100644
--- a/app/views/NewServerView/ServerInput/Item.js
+++ b/app/views/NewServerView/ServerInput/Item.tsx
@@ -1,12 +1,12 @@
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
-import PropTypes from 'prop-types';
import { BorderlessButton } from 'react-native-gesture-handler';
import { themes } from '../../../constants/colors';
import { CustomIcon } from '../../../lib/Icons';
import sharedStyles from '../../Styles';
import Touch from '../../../utils/touch';
+import { IServer } from '../index';
const styles = StyleSheet.create({
container: {
@@ -27,13 +27,20 @@ const styles = StyleSheet.create({
}
});
-const Item = ({ item, theme, onPress, onDelete }) => (
+interface IItem {
+ item: IServer;
+ theme: string;
+ onPress(url: string): void;
+ onDelete(item: IServer): void;
+}
+
+const Item = ({ item, theme, onPress, onDelete }: IItem): JSX.Element => (
onPress(item.url)} theme={theme} testID={`server-history-${item.url}`}>
{item.url}
-
+
{item.username}
@@ -43,11 +50,4 @@ const Item = ({ item, theme, onPress, onDelete }) => (
);
-Item.propTypes = {
- item: PropTypes.object,
- theme: PropTypes.string,
- onPress: PropTypes.func,
- onDelete: PropTypes.func
-};
-
export default Item;
diff --git a/app/views/NewServerView/ServerInput/index.js b/app/views/NewServerView/ServerInput/index.tsx
similarity index 81%
rename from app/views/NewServerView/ServerInput/index.js
rename to app/views/NewServerView/ServerInput/index.tsx
index ef80c468..c3399b73 100644
--- a/app/views/NewServerView/ServerInput/index.js
+++ b/app/views/NewServerView/ServerInput/index.tsx
@@ -1,12 +1,12 @@
import React, { useState } from 'react';
import { FlatList, StyleSheet, View } from 'react-native';
-import PropTypes from 'prop-types';
import TextInput from '../../../containers/TextInput';
import * as List from '../../../containers/List';
import { themes } from '../../../constants/colors';
import I18n from '../../../i18n';
import Item from './Item';
+import { IServer } from '../index';
const styles = StyleSheet.create({
container: {
@@ -28,7 +28,25 @@ const styles = StyleSheet.create({
}
});
-const ServerInput = ({ text, theme, serversHistory, onChangeText, onSubmit, onDelete, onPressServerHistory }) => {
+interface IServerInput {
+ text: string;
+ theme: string;
+ serversHistory: any[];
+ onChangeText(text: string): void;
+ onSubmit(): void;
+ onDelete(item: IServer): void;
+ onPressServerHistory(serverHistory: IServer): void;
+}
+
+const ServerInput = ({
+ text,
+ theme,
+ serversHistory,
+ onChangeText,
+ onSubmit,
+ onDelete,
+ onPressServerHistory
+}: IServerInput): JSX.Element => {
const [focused, setFocused] = useState(false);
return (
@@ -68,14 +86,4 @@ const ServerInput = ({ text, theme, serversHistory, onChangeText, onSubmit, onDe
);
};
-ServerInput.propTypes = {
- text: PropTypes.string,
- theme: PropTypes.string,
- serversHistory: PropTypes.array,
- onChangeText: PropTypes.func,
- onSubmit: PropTypes.func,
- onDelete: PropTypes.func,
- onPressServerHistory: PropTypes.func
-};
-
export default ServerInput;
diff --git a/app/views/NewServerView/index.js b/app/views/NewServerView/index.tsx
similarity index 75%
rename from app/views/NewServerView/index.js
rename to app/views/NewServerView/index.tsx
index 8eaba349..815ec134 100644
--- a/app/views/NewServerView/index.js
+++ b/app/views/NewServerView/index.tsx
@@ -1,5 +1,4 @@
import React from 'react';
-import PropTypes from 'prop-types';
import { Text, Keyboard, StyleSheet, View, BackHandler, Image } from 'react-native';
import { connect } from 'react-redux';
import { Base64 } from 'js-base64';
@@ -7,6 +6,9 @@ import parse from 'url-parse';
import { Q } from '@nozbe/watermelondb';
import { TouchableOpacity } from 'react-native-gesture-handler';
import Orientation from 'react-native-orientation-locker';
+import { StackNavigationProp } from '@react-navigation/stack';
+import { Dispatch } from 'redux';
+import Model from '@nozbe/watermelondb/Model';
import UserPreferences from '../../lib/userPreferences';
import EventEmitter from '../../utils/events';
@@ -19,7 +21,6 @@ import FormContainer, { FormContainerInner } from '../../containers/FormContaine
import I18n from '../../i18n';
import { themes } from '../../constants/colors';
import { events, logEvent } from '../../utils/log';
-import { animateNextTransition } from '../../utils/layoutAnimation';
import { withTheme } from '../../theme';
import { BASIC_AUTH_KEY, setBasicAuth } from '../../utils/fetch';
import * as HeaderButton from '../../containers/HeaderButton';
@@ -66,19 +67,32 @@ const styles = StyleSheet.create({
}
});
-class NewServerView extends React.Component {
- static propTypes = {
- navigation: PropTypes.object,
- theme: PropTypes.string,
- connecting: PropTypes.bool.isRequired,
- connectServer: PropTypes.func.isRequired,
- selectServer: PropTypes.func.isRequired,
- previousServer: PropTypes.string,
- inviteLinksClear: PropTypes.func,
- serverFinishAdd: PropTypes.func
- };
+export interface IServer extends Model {
+ url: string;
+ username: string;
+}
+interface INewServerView {
+ navigation: StackNavigationProp;
+ theme: string;
+ connecting: boolean;
+ connectServer(server: string, username?: string, fromServerHistory?: boolean): void;
+ selectServer(server: string): void;
+ previousServer: string;
+ inviteLinksClear(): void;
+ serverFinishAdd(): void;
+ width: number;
+ height: number;
+}
- constructor(props) {
+interface IState {
+ text: string;
+ connectingOpen: boolean;
+ certificate: any;
+ serversHistory: IServer[];
+}
+
+class NewServerView extends React.Component {
+ constructor(props: INewServerView) {
super(props);
if (!isTablet) {
Orientation.lockToPortrait();
@@ -131,21 +145,21 @@ class NewServerView extends React.Component {
return false;
};
- onChangeText = text => {
+ onChangeText = (text: string) => {
this.setState({ text });
this.queryServerHistory(text);
};
- queryServerHistory = async text => {
+ queryServerHistory = async (text?: string) => {
const db = database.servers;
try {
const serversHistoryCollection = db.get('servers_history');
let whereClause = [Q.where('username', Q.notEq(null)), Q.experimentalSortBy('updated_at', Q.desc), Q.experimentalTake(3)];
- const likeString = sanitizeLikeString(text);
if (text) {
+ const likeString = sanitizeLikeString(text);
whereClause = [...whereClause, Q.where('url', Q.like(`%${likeString}%`))];
}
- const serversHistory = await serversHistoryCollection.query(...whereClause).fetch();
+ const serversHistory = (await serversHistoryCollection.query(...whereClause).fetch()) as IServer[];
this.setState({ serversHistory });
} catch {
// Do nothing
@@ -158,7 +172,7 @@ class NewServerView extends React.Component {
selectServer(previousServer);
};
- handleNewServerEvent = event => {
+ handleNewServerEvent = (event: { server: string }) => {
let { server } = event;
if (!server) {
return;
@@ -169,13 +183,11 @@ class NewServerView extends React.Component {
connectServer(server);
};
- onPressServerHistory = serverHistory => {
- this.setState({ text: serverHistory?.url }, () =>
- this.submit({ fromServerHistory: true, username: serverHistory?.username })
- );
+ onPressServerHistory = (serverHistory: IServer) => {
+ this.setState({ text: serverHistory.url }, () => this.submit(true, serverHistory?.username));
};
- submit = async ({ fromServerHistory = false, username }) => {
+ submit = async (fromServerHistory?: boolean, username?: string) => {
logEvent(events.NS_CONNECT_TO_WORKSPACE);
const { text, certificate } = this.state;
const { connectServer } = this.props;
@@ -207,7 +219,7 @@ class NewServerView extends React.Component {
connectServer('https://open.rocket.chat');
};
- basicAuth = async (server, text) => {
+ basicAuth = async (server: string, text: string) => {
try {
const parsedUrl = parse(text, true);
if (parsedUrl.auth.length) {
@@ -222,14 +234,14 @@ class NewServerView extends React.Component {
chooseCertificate = async () => {
try {
- const certificate = await SSLPinning.pickCertificate();
+ const certificate = await SSLPinning?.pickCertificate();
this.setState({ certificate });
} catch {
// Do nothing
}
};
- completeUrl = url => {
+ completeUrl = (url: string) => {
const parsedUrl = parse(url, true);
if (parsedUrl.auth.length) {
url = parsedUrl.origin;
@@ -252,14 +264,11 @@ class NewServerView extends React.Component {
return url.replace(/\/+$/, '').replace(/\\/g, '/');
};
- uriToPath = uri => uri.replace('file://', '');
-
- saveCertificate = certificate => {
- animateNextTransition();
- this.setState({ certificate });
- };
+ uriToPath = (uri: string) => uri.replace('file://', '');
handleRemove = () => {
+ // TODO: Remove ts-ignore when migrate the showConfirmationAlert
+ // @ts-ignore
showConfirmationAlert({
message: I18n.t('You_will_unset_a_certificate_for_this_server'),
confirmationText: I18n.t('Remove'),
@@ -267,14 +276,15 @@ class NewServerView extends React.Component {
});
};
- deleteServerHistory = async item => {
- const { serversHistory } = this.state;
+ deleteServerHistory = async (item: IServer) => {
const db = database.servers;
try {
- await db.action(async () => {
+ await db.write(async () => {
await item.destroyPermanently();
});
- this.setState({ serversHistory: serversHistory.filter(server => server.id !== item.id) });
+ this.setState((prevstate: IState) => ({
+ serversHistory: prevstate.serversHistory.filter((server: IServer) => server.id !== item.id)
+ }));
} catch {
// Nothing
}
@@ -288,20 +298,21 @@ class NewServerView extends React.Component {
style={[
styles.certificatePicker,
{
- marginBottom: verticalScale(previousServer && !isTablet ? 10 : 30, height)
+ marginBottom: verticalScale({ size: previousServer && !isTablet ? 10 : 30, height })
}
]}>
{certificate ? I18n.t('Your_certificate') : I18n.t('Do_you_have_a_certificate')}
-
+
{certificate ?? I18n.t('Apply_Your_Certificate')}
@@ -321,10 +332,10 @@ class NewServerView extends React.Component {
style={[
styles.onboardingImage,
{
- marginBottom: verticalScale(10, height),
- marginTop: isTablet ? 0 : verticalScale(marginTop, height),
- width: verticalScale(100, height),
- height: verticalScale(100, height)
+ marginBottom: verticalScale({ size: 10, height }),
+ marginTop: isTablet ? 0 : verticalScale({ size: marginTop, height }),
+ width: verticalScale({ size: 100, height }),
+ height: verticalScale({ size: 100, height })
}
]}
source={require('../../static/images/logo.png')}
@@ -335,8 +346,8 @@ class NewServerView extends React.Component {
styles.title,
{
color: themes[theme].titleText,
- fontSize: moderateScale(22, null, width),
- marginBottom: verticalScale(8, height)
+ fontSize: moderateScale({ size: 22, width }),
+ marginBottom: verticalScale({ size: 8, height })
}
]}>
Rocket.Chat
@@ -346,8 +357,8 @@ class NewServerView extends React.Component {
styles.subtitle,
{
color: themes[theme].controlText,
- fontSize: moderateScale(16, null, width),
- marginBottom: verticalScale(30, height)
+ fontSize: moderateScale({ size: 16, width }),
+ marginBottom: verticalScale({ size: 30, height })
}
]}>
{I18n.t('Onboarding_subtitle')}
@@ -367,7 +378,7 @@ class NewServerView extends React.Component {
onPress={this.submit}
disabled={!text || connecting}
loading={!connectingOpen && connecting}
- style={[styles.connectButton, { marginTop: verticalScale(16, height) }]}
+ style={[styles.connectButton, { marginTop: verticalScale({ size: 16, height }) }]}
theme={theme}
testID='new-server-view-button'
/>
@@ -377,8 +388,8 @@ class NewServerView extends React.Component {
styles.description,
{
color: themes[theme].auxiliaryText,
- fontSize: moderateScale(14, null, width),
- marginBottom: verticalScale(16, height)
+ fontSize: moderateScale({ size: 14, width }),
+ marginBottom: verticalScale({ size: 16, height })
}
]}>
{I18n.t('Onboarding_join_open_description')}
@@ -400,14 +411,15 @@ class NewServerView extends React.Component {
}
}
-const mapStateToProps = state => ({
+const mapStateToProps = (state: any) => ({
connecting: state.server.connecting,
previousServer: state.server.previousServer
});
-const mapDispatchToProps = dispatch => ({
- connectServer: (...params) => dispatch(serverRequest(...params)),
- selectServer: server => dispatch(selectServerRequest(server)),
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+ connectServer: (server: string, username: string & null, fromServerHistory?: boolean) =>
+ dispatch(serverRequest(server, username, fromServerHistory)),
+ selectServer: (server: string) => dispatch(selectServerRequest(server)),
inviteLinksClear: () => dispatch(inviteLinksClearAction()),
serverFinishAdd: () => dispatch(serverFinishAddAction())
});