From 308be2d2f4ae6b76fe245fc1d518846bb04a7886 Mon Sep 17 00:00:00 2001 From: Alex Junior Date: Wed, 15 Sep 2021 16:58:14 -0300 Subject: [PATCH] Chore: Migrate CreateDiscussionView to Typescript (#3378) * [improve] - migrate the view: CreateDiscussionView to typescript * minor changes Co-authored-by: Diego Mello --- app/containers/HeaderButton/Common.tsx | 4 +- app/containers/UIKit/MultiSelect/index.tsx | 12 ++-- .../{SelectChannel.js => SelectChannel.tsx} | 27 ++++----- .../{SelectUsers.js => SelectUsers.tsx} | 45 +++++++++------ .../{index.js => index.tsx} | 48 +++++++--------- app/views/CreateDiscussionView/interfaces.ts | 55 +++++++++++++++++++ .../{styles.js => styles.ts} | 0 7 files changed, 123 insertions(+), 68 deletions(-) rename app/views/CreateDiscussionView/{SelectChannel.js => SelectChannel.tsx} (75%) rename app/views/CreateDiscussionView/{SelectUsers.js => SelectUsers.tsx} (69%) rename app/views/CreateDiscussionView/{index.js => index.tsx} (86%) create mode 100644 app/views/CreateDiscussionView/interfaces.ts rename app/views/CreateDiscussionView/{styles.js => styles.ts} (100%) diff --git a/app/containers/HeaderButton/Common.tsx b/app/containers/HeaderButton/Common.tsx index f1e00628..b40543dd 100644 --- a/app/containers/HeaderButton/Common.tsx +++ b/app/containers/HeaderButton/Common.tsx @@ -7,8 +7,8 @@ import Item from './HeaderButtonItem'; interface IHeaderButtonCommon { navigation: any; - onPress(): void; - testID: string; + onPress?(): void; + testID?: string; } // Left diff --git a/app/containers/UIKit/MultiSelect/index.tsx b/app/containers/UIKit/MultiSelect/index.tsx index cd8d21a3..95bedbeb 100644 --- a/app/containers/UIKit/MultiSelect/index.tsx +++ b/app/containers/UIKit/MultiSelect/index.tsx @@ -14,19 +14,19 @@ import Input from './Input'; import styles from './styles'; interface IMultiSelect { - options: []; + options: any[]; onChange: Function; placeholder: { text: string; }; - context: number; - loading: boolean; - multiselect: boolean; + context?: number; + loading?: boolean; + multiselect?: boolean; onSearch: Function; onClose: Function; inputStyle: object; - value: { text: any }[]; - disabled: boolean; + value?: any[]; + disabled?: boolean | object; theme: string; } diff --git a/app/views/CreateDiscussionView/SelectChannel.js b/app/views/CreateDiscussionView/SelectChannel.tsx similarity index 75% rename from app/views/CreateDiscussionView/SelectChannel.js rename to app/views/CreateDiscussionView/SelectChannel.tsx index 5dfecfc3..e7653973 100644 --- a/app/views/CreateDiscussionView/SelectChannel.js +++ b/app/views/CreateDiscussionView/SelectChannel.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import { Text } from 'react-native'; -import PropTypes from 'prop-types'; import debounce from '../../utils/debounce'; import { avatarURL } from '../../utils/avatar'; @@ -9,8 +8,18 @@ import I18n from '../../i18n'; import { MultiSelect } from '../../containers/UIKit/MultiSelect'; import { themes } from '../../constants/colors'; import styles from './styles'; +import { ICreateDiscussionViewSelectChannel } from './interfaces'; -const SelectChannel = ({ server, token, userId, onChannelSelect, initial, blockUnauthenticatedAccess, serverVersion, theme }) => { +const SelectChannel = ({ + server, + token, + userId, + onChannelSelect, + initial, + blockUnauthenticatedAccess, + serverVersion, + theme +}: ICreateDiscussionViewSelectChannel): JSX.Element => { const [channels, setChannels] = useState([]); const getChannels = debounce(async (keyword = '') => { @@ -22,7 +31,9 @@ const SelectChannel = ({ server, token, userId, onChannelSelect, initial, blockU } }, 300); - const getAvatar = item => + const getAvatar = (item: any) => + // TODO: remove this ts-ignore when migrate the file: app/utils/avatar.js + // @ts-ignore avatarURL({ text: RocketChat.getRoomAvatar(item), type: item.t, @@ -55,15 +66,5 @@ const SelectChannel = ({ server, token, userId, onChannelSelect, initial, blockU ); }; -SelectChannel.propTypes = { - server: PropTypes.string, - token: PropTypes.string, - userId: PropTypes.string, - initial: PropTypes.object, - onChannelSelect: PropTypes.func, - blockUnauthenticatedAccess: PropTypes.bool, - serverVersion: PropTypes.string, - theme: PropTypes.string -}; export default SelectChannel; diff --git a/app/views/CreateDiscussionView/SelectUsers.js b/app/views/CreateDiscussionView/SelectUsers.tsx similarity index 69% rename from app/views/CreateDiscussionView/SelectUsers.js rename to app/views/CreateDiscussionView/SelectUsers.tsx index 323fc0fd..65a4e0a4 100644 --- a/app/views/CreateDiscussionView/SelectUsers.js +++ b/app/views/CreateDiscussionView/SelectUsers.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import { Text } from 'react-native'; -import PropTypes from 'prop-types'; import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit'; import { Q } from '@nozbe/watermelondb'; @@ -12,19 +11,37 @@ import I18n from '../../i18n'; import { MultiSelect } from '../../containers/UIKit/MultiSelect'; import { themes } from '../../constants/colors'; import styles from './styles'; +import { ICreateDiscussionViewSelectUsers } from './interfaces'; -const SelectUsers = ({ server, token, userId, selected, onUserSelect, blockUnauthenticatedAccess, serverVersion, theme }) => { - const [users, setUsers] = useState([]); +interface IUser { + name: string; + username: string; +} + +const SelectUsers = ({ + server, + token, + userId, + selected, + onUserSelect, + blockUnauthenticatedAccess, + serverVersion, + theme +}: ICreateDiscussionViewSelectUsers): JSX.Element => { + const [users, setUsers] = useState([]); const getUsers = debounce(async (keyword = '') => { try { const db = database.active; const usersCollection = db.get('users'); const res = await RocketChat.search({ text: keyword, filterRooms: false }); - let items = [...users.filter(u => selected.includes(u.name)), ...res.filter(r => !users.find(u => u.name === r.name))]; + let items = [ + ...users.filter((u: IUser) => selected.includes(u.name)), + ...res.filter((r: IUser) => !users.find((u: IUser) => u.name === r.name)) + ]; const records = await usersCollection.query(Q.where('username', Q.oneOf(items.map(u => u.name)))).fetch(); items = items.map(item => { - const index = records.findIndex(r => r.username === item.name); + const index = records.findIndex((r: IUser) => r.username === item.name); if (index > -1) { const record = records[index]; return { @@ -44,7 +61,9 @@ const SelectUsers = ({ server, token, userId, selected, onUserSelect, blockUnaut } }, 300); - const getAvatar = item => + const getAvatar = (item: any) => + // TODO: remove this ts-ignore when migrate the file: app/utils/avatar.js + // @ts-ignore avatarURL({ text: RocketChat.getRoomAvatar(item), type: 'd', @@ -63,12 +82,12 @@ const SelectUsers = ({ server, token, userId, selected, onUserSelect, blockUnaut inputStyle={styles.inputStyle} onSearch={getUsers} onChange={onUserSelect} - options={users.map(user => ({ + options={users.map((user: IUser) => ({ value: user.name, text: { text: RocketChat.getRoomTitle(user) }, imageUrl: getAvatar(user) }))} - onClose={() => setUsers(users.filter(u => selected.includes(u.name)))} + onClose={() => setUsers(users.filter((u: IUser) => selected.includes(u.name)))} placeholder={{ text: `${I18n.t('Select_Users')}...` }} context={BLOCK_CONTEXT.FORM} multiselect @@ -76,15 +95,5 @@ const SelectUsers = ({ server, token, userId, selected, onUserSelect, blockUnaut ); }; -SelectUsers.propTypes = { - server: PropTypes.string, - token: PropTypes.string, - userId: PropTypes.string, - selected: PropTypes.array, - onUserSelect: PropTypes.func, - blockUnauthenticatedAccess: PropTypes.bool, - serverVersion: PropTypes.string, - theme: PropTypes.string -}; export default SelectUsers; diff --git a/app/views/CreateDiscussionView/index.js b/app/views/CreateDiscussionView/index.tsx similarity index 86% rename from app/views/CreateDiscussionView/index.js rename to app/views/CreateDiscussionView/index.tsx index 0765d826..98b461f0 100644 --- a/app/views/CreateDiscussionView/index.js +++ b/app/views/CreateDiscussionView/index.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; import { ScrollView, Switch, Text } from 'react-native'; import Loading from '../../containers/Loading'; @@ -24,30 +23,16 @@ import { E2E_ROOM_TYPES } from '../../lib/encryption/constants'; import styles from './styles'; import SelectUsers from './SelectUsers'; import SelectChannel from './SelectChannel'; +import { ICreateChannelViewProps } from './interfaces'; -class CreateChannelView extends React.Component { - propTypes = { - navigation: PropTypes.object, - route: PropTypes.object, - server: PropTypes.string, - user: PropTypes.object, - create: PropTypes.func, - loading: PropTypes.bool, - result: PropTypes.object, - failure: PropTypes.bool, - error: PropTypes.object, - theme: PropTypes.string, - isMasterDetail: PropTypes.bool, - blockUnauthenticatedAccess: PropTypes.bool, - serverVersion: PropTypes.string, - encryptionEnabled: PropTypes.bool - }; +class CreateChannelView extends React.Component { + private channel: any; - constructor(props) { + constructor(props: ICreateChannelViewProps) { super(props); const { route } = props; this.channel = route.params?.channel; - const message = route.params?.message ?? {}; + const message: any = route.params?.message ?? {}; this.state = { channel: this.channel, message, @@ -59,7 +44,7 @@ class CreateChannelView extends React.Component { this.setHeader(); } - componentDidUpdate(prevProps, prevState) { + componentDidUpdate(prevProps: any, prevState: any) { const { channel, name } = this.state; const { loading, failure, error, result, isMasterDetail } = this.props; @@ -118,7 +103,7 @@ class CreateChannelView extends React.Component { } = this.state; const { create } = this.props; - const params = { + const params: any = { prid: prid || rid, pmid, t_name, @@ -138,12 +123,12 @@ class CreateChannelView extends React.Component { return channel && channel.rid && channel.rid.trim().length && name.trim().length; }; - selectChannel = ({ value }) => { + selectChannel = ({ value }: any) => { logEvent(events.CD_SELECT_CHANNEL); this.setState({ channel: value, encrypted: value?.encrypted }); }; - selectUsers = ({ value }) => { + selectUsers = ({ value }: any) => { logEvent(events.CD_SELECT_USERS); this.setState({ users: value }); }; @@ -151,10 +136,12 @@ class CreateChannelView extends React.Component { get isEncryptionEnabled() { const { channel } = this.state; const { encryptionEnabled } = this.props; + // TODO: remove this ts-ignore when migrate the file: app/lib/encryption/constants.js + // @ts-ignore return encryptionEnabled && E2E_ROOM_TYPES[channel?.t]; } - onEncryptedChange = value => { + onEncryptedChange = (value: any) => { logEvent(events.CD_TOGGLE_ENCRY); this.setState({ encrypted: value }); }; @@ -163,12 +150,14 @@ class CreateChannelView extends React.Component { const { name, users, encrypted } = this.state; const { server, user, loading, blockUnauthenticatedAccess, theme, serverVersion } = this.props; return ( + // @ts-ignore + {/* @ts-ignore*/} {I18n.t('Discussion_Desc')} this.setState({ name: text })} + onChangeText={(text: string) => this.setState({ name: text })} theme={theme} /> ({ +const mapStateToProps = (state: any) => ({ user: getUserSelector(state), server: state.server.server, error: state.createDiscussion.error, @@ -227,8 +217,8 @@ const mapStateToProps = state => ({ encryptionEnabled: state.encryption.enabled }); -const mapDispatchToProps = dispatch => ({ - create: data => dispatch(createDiscussionRequest(data)) +const mapDispatchToProps = (dispatch: any) => ({ + create: (data: any) => dispatch(createDiscussionRequest(data)) }); export default connect(mapStateToProps, mapDispatchToProps)(withTheme(CreateChannelView)); diff --git a/app/views/CreateDiscussionView/interfaces.ts b/app/views/CreateDiscussionView/interfaces.ts new file mode 100644 index 00000000..46883311 --- /dev/null +++ b/app/views/CreateDiscussionView/interfaces.ts @@ -0,0 +1,55 @@ +export interface ICreateChannelViewProps { + navigation: any; + route: { + params?: { + channel: string; + message: { + msg: string; + }; + showCloseModal: boolean; + }; + }; + server: string; + user: { + id: string; + token: string; + }; + create: Function; + loading: boolean; + result: { + rid: string; + t: string; + prid: string; + }; + failure: boolean; + error: { + reason: string; + }; + theme: string; + isMasterDetail: boolean; + blockUnauthenticatedAccess: boolean; + serverVersion: string; + encryptionEnabled: boolean; +} + +export interface ICreateDiscussionViewSelectChannel { + server: string; + token: string; + userId: string; + initial: object; + onChannelSelect: Function; + blockUnauthenticatedAccess: boolean; + serverVersion: string; + theme: string; +} + +export interface ICreateDiscussionViewSelectUsers { + server: string; + token: string; + userId: string; + selected: any[]; + onUserSelect: Function; + blockUnauthenticatedAccess: boolean; + serverVersion: string; + theme: string; +} diff --git a/app/views/CreateDiscussionView/styles.js b/app/views/CreateDiscussionView/styles.ts similarity index 100% rename from app/views/CreateDiscussionView/styles.js rename to app/views/CreateDiscussionView/styles.ts