From b0b62afc91f162daea06f8467a5b5a9ba75f2ab6 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Mon, 6 Dec 2021 13:39:06 -0300 Subject: [PATCH 01/28] Chore: Migrate Utils Folder to TS --- app/containers/Passcode/Base/Button.tsx | 20 +++++++++--------- app/utils/{touch.js => touch.tsx} | 27 +++++++++++++------------ app/utils/{url.js => url.ts} | 4 ++-- app/views/ProfileView/interfaces.ts | 4 ++-- 4 files changed, 28 insertions(+), 27 deletions(-) rename app/utils/{touch.js => touch.tsx} (55%) rename app/utils/{url.js => url.ts} (77%) diff --git a/app/containers/Passcode/Base/Button.tsx b/app/containers/Passcode/Base/Button.tsx index f7e6c1a9a3e..50a1cf417dd 100644 --- a/app/containers/Passcode/Base/Button.tsx +++ b/app/containers/Passcode/Base/Button.tsx @@ -7,28 +7,28 @@ import Touch from '../../../utils/touch'; import { CustomIcon } from '../../../lib/Icons'; interface IPasscodeButton { - text: string; - icon: string; + text?: string; + icon?: string; theme: string; - disabled: boolean; - onPress: Function; + disabled?: boolean; + onPress?: Function; } -const Button = React.memo(({ text, disabled, theme, onPress, icon }: Partial) => { - const press = () => onPress && onPress(text!); +const Button = React.memo(({ text, disabled, theme, onPress, icon }: IPasscodeButton) => { + const press = () => onPress && onPress(text); return ( {icon ? ( - + ) : ( - {text} + {text} )} ); diff --git a/app/utils/touch.js b/app/utils/touch.tsx similarity index 55% rename from app/utils/touch.js rename to app/utils/touch.tsx index 0bfece04a26..3573c87c50e 100644 --- a/app/utils/touch.js +++ b/app/utils/touch.tsx @@ -1,19 +1,27 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import { RectButton } from 'react-native-gesture-handler'; +import { RectButton, RectButtonProps } from 'react-native-gesture-handler'; import { themes } from '../constants/colors'; -class Touch extends React.Component { - setNativeProps(props) { +interface ITouchProps extends RectButtonProps { + children: React.ReactNode; + theme: string; + accessibilityLabel?: string; + testID?: string; +} + +class Touch extends React.Component { + private ref: any; + + setNativeProps(props: ITouchProps): void { this.ref.setNativeProps(props); } - getRef = ref => { + getRef = (ref: RectButton): void => { this.ref = ref; }; - render() { + render(): JSX.Element { const { children, onPress, theme, underlayColor, ...props } = this.props; return ( @@ -30,11 +38,4 @@ class Touch extends React.Component { } } -Touch.propTypes = { - children: PropTypes.node, - onPress: PropTypes.func, - theme: PropTypes.string, - underlayColor: PropTypes.string -}; - export default Touch; diff --git a/app/utils/url.js b/app/utils/url.ts similarity index 77% rename from app/utils/url.js rename to app/utils/url.ts index 623524d7a4c..5017959732b 100644 --- a/app/utils/url.js +++ b/app/utils/url.ts @@ -1,4 +1,4 @@ -export const isValidURL = url => { +export const isValidURL = (url: string): boolean => { const pattern = new RegExp( '^(https?:\\/\\/)?' + // protocol '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name @@ -12,4 +12,4 @@ export const isValidURL = url => { }; // Use useSsl: false only if server url starts with http:// -export const useSsl = url => !/http:\/\//.test(url); +export const useSsl = (url: string): boolean => !/http:\/\//.test(url); diff --git a/app/views/ProfileView/interfaces.ts b/app/views/ProfileView/interfaces.ts index bfec50c0dd3..0fe592f3227 100644 --- a/app/views/ProfileView/interfaces.ts +++ b/app/views/ProfileView/interfaces.ts @@ -26,9 +26,9 @@ export interface IParams { } export interface IAvatarButton { - key: React.Key; + key: string; child: React.ReactNode; - onPress: Function; + onPress: () => void; disabled: boolean; } From ee6be6c411e71bc804569493246481a0b63c207f Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Mon, 6 Dec 2021 14:59:07 -0300 Subject: [PATCH 02/28] avatar and twofactor --- app/containers/Avatar/Avatar.tsx | 13 ++++++----- app/utils/{appGroup.js => appGroup.ts} | 2 +- app/utils/{avatar.js => avatar.ts} | 22 +++++++++++++++---- app/utils/{twoFactor.js => twoFactor.ts} | 10 +++++++-- .../CreateDiscussionView/SelectChannel.tsx | 2 -- .../CreateDiscussionView/SelectUsers.tsx | 5 ++--- 6 files changed, 36 insertions(+), 18 deletions(-) rename app/utils/{appGroup.js => appGroup.ts} (83%) rename app/utils/{avatar.js => avatar.ts} (62%) rename app/utils/{twoFactor.js => twoFactor.ts} (71%) diff --git a/app/containers/Avatar/Avatar.tsx b/app/containers/Avatar/Avatar.tsx index 286bcc060b3..da4cfd24047 100644 --- a/app/containers/Avatar/Avatar.tsx +++ b/app/containers/Avatar/Avatar.tsx @@ -5,6 +5,7 @@ import Touchable from 'react-native-platform-touchable'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; import { avatarURL } from '../../utils/avatar'; +import { RoomType } from '../../definitions/IRoom'; import Emoji from '../markdown/Emoji'; import { IAvatar } from './interfaces'; @@ -27,7 +28,7 @@ const Avatar = React.memo( text, size = 25, borderRadius = 4, - type = 'd' + type = RoomType.DIRECT }: Partial) => { if ((!text && !avatar && !emoji && !rid) || !server) { return null; @@ -56,15 +57,15 @@ const Avatar = React.memo( if (!isStatic) { uri = avatarURL({ type, - text, + text: text!, size, - user, + user: user!, avatar, server, - avatarETag, - serverVersion, + avatarETag: avatarETag!, + serverVersion: serverVersion!, rid, - blockUnauthenticatedAccess + blockUnauthenticatedAccess: blockUnauthenticatedAccess! }); } diff --git a/app/utils/appGroup.js b/app/utils/appGroup.ts similarity index 83% rename from app/utils/appGroup.js rename to app/utils/appGroup.ts index 63fb428aa6d..f92227c03f4 100644 --- a/app/utils/appGroup.js +++ b/app/utils/appGroup.ts @@ -4,7 +4,7 @@ import { isIOS } from './deviceInfo'; const { AppGroup } = NativeModules; -const appGroup = { +const appGroup: { path: string } = { path: isIOS ? AppGroup.path : '' }; diff --git a/app/utils/avatar.js b/app/utils/avatar.ts similarity index 62% rename from app/utils/avatar.js rename to app/utils/avatar.ts index 4cc15cdadeb..13a7ed1cbf5 100644 --- a/app/utils/avatar.js +++ b/app/utils/avatar.ts @@ -1,21 +1,35 @@ import { compareServerVersion, methods } from '../lib/utils'; +import { RoomType } from '../definitions/IRoom'; -const formatUrl = (url, size, query) => `${url}?format=png&size=${size}${query}`; +const formatUrl = (url: string, size: number, query: string) => `${url}?format=png&size=${size}${query}`; + +interface IAvatarURL { + type: string; + text: string; + size?: number; + user: { id: string; token: string }; + avatar?: string; + server: string; + avatarETag: string; + rid?: string; + blockUnauthenticatedAccess: boolean; + serverVersion: string; +} export const avatarURL = ({ type, text, size = 25, - user = {}, + user, avatar, server, avatarETag, rid, blockUnauthenticatedAccess, serverVersion -}) => { +}: IAvatarURL): string => { let room; - if (type === 'd') { + if (type === RoomType.DIRECT) { room = text; } else if (rid && !compareServerVersion(serverVersion, '3.6.0', methods.lowerThan)) { room = `room/${rid}`; diff --git a/app/utils/twoFactor.js b/app/utils/twoFactor.ts similarity index 71% rename from app/utils/twoFactor.js rename to app/utils/twoFactor.ts index 6f2fa9c9de0..d9a9ae50002 100644 --- a/app/utils/twoFactor.js +++ b/app/utils/twoFactor.ts @@ -3,13 +3,19 @@ import { settings } from '@rocket.chat/sdk'; import { TWO_FACTOR } from '../containers/TwoFactor'; import EventEmitter from './events'; -export const twoFactor = ({ method, invalid }) => +export const twoFactor = ({ + method, + invalid +}: { + method: string; + invalid: boolean; +}): Promise<{ twoFactorCode: string; twoFactorMethod: string }> => new Promise((resolve, reject) => { EventEmitter.emit(TWO_FACTOR, { method, invalid, cancel: () => reject(), - submit: code => { + submit: (code: string) => { settings.customHeaders = { ...settings.customHeaders, 'x-2fa-code': code, diff --git a/app/views/CreateDiscussionView/SelectChannel.tsx b/app/views/CreateDiscussionView/SelectChannel.tsx index e7653973f06..41f7ab0b17e 100644 --- a/app/views/CreateDiscussionView/SelectChannel.tsx +++ b/app/views/CreateDiscussionView/SelectChannel.tsx @@ -32,8 +32,6 @@ const SelectChannel = ({ }, 300); 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, diff --git a/app/views/CreateDiscussionView/SelectUsers.tsx b/app/views/CreateDiscussionView/SelectUsers.tsx index 65a4e0a4ad0..ed29ad392ee 100644 --- a/app/views/CreateDiscussionView/SelectUsers.tsx +++ b/app/views/CreateDiscussionView/SelectUsers.tsx @@ -10,6 +10,7 @@ import database from '../../lib/database'; import I18n from '../../i18n'; import { MultiSelect } from '../../containers/UIKit/MultiSelect'; import { themes } from '../../constants/colors'; +import { RoomType } from '../../definitions/IRoom'; import styles from './styles'; import { ICreateDiscussionViewSelectUsers } from './interfaces'; @@ -62,11 +63,9 @@ const SelectUsers = ({ }, 300); 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', + type: RoomType.DIRECT, user: { id: userId, token }, server, avatarETag: item.avatarETag, From 498f0093279473e5ea8b6366575ab7e831acc77e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 7 Dec 2021 10:59:21 -0300 Subject: [PATCH 03/28] debounce --- app/utils/debounce.js | 20 -------------------- app/utils/debounce.ts | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 20 deletions(-) delete mode 100644 app/utils/debounce.js create mode 100644 app/utils/debounce.ts diff --git a/app/utils/debounce.js b/app/utils/debounce.js deleted file mode 100644 index 106c61d00c3..00000000000 --- a/app/utils/debounce.js +++ /dev/null @@ -1,20 +0,0 @@ -export default function debounce(func, wait, immediate) { - let timeout; - function _debounce(...args) { - const context = this; - const later = function __debounce() { - timeout = null; - if (!immediate) { - func.apply(context, args); - } - }; - const callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) { - func.apply(context, args); - } - } - _debounce.stop = () => clearTimeout(timeout); - return _debounce; -} diff --git a/app/utils/debounce.ts b/app/utils/debounce.ts new file mode 100644 index 00000000000..e0c28b239f1 --- /dev/null +++ b/app/utils/debounce.ts @@ -0,0 +1,22 @@ +export default function debounce(func: Function, wait?: number, immediate?: boolean) { + let timeout: number | null; + function _debounce(...args: any[]) { + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-this-alias + const context = this; + const later = function __debounce() { + timeout = null; + if (!immediate) { + func.apply(context, args); + } + }; + const callNow = immediate && !timeout; + clearTimeout(timeout!); + timeout = setTimeout(later, wait); + if (callNow) { + func.apply(context, args); + } + } + _debounce.stop = () => clearTimeout(timeout!); + return _debounce; +} From c68080693f00009426ba8bf6995d9d3cbd334ebc Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 7 Dec 2021 11:00:50 -0300 Subject: [PATCH 04/28] deviceInfo and isValidEmail --- app/utils/{deviceInfo.js => deviceInfo.ts} | 2 +- app/utils/{isValidEmail.js => isValidEmail.ts} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/utils/{deviceInfo.js => deviceInfo.ts} (92%) rename app/utils/{isValidEmail.js => isValidEmail.ts} (78%) diff --git a/app/utils/deviceInfo.js b/app/utils/deviceInfo.ts similarity index 92% rename from app/utils/deviceInfo.js rename to app/utils/deviceInfo.ts index 7961b440af9..9cb7ac727ef 100644 --- a/app/utils/deviceInfo.js +++ b/app/utils/deviceInfo.ts @@ -9,7 +9,7 @@ export const getBundleId = DeviceInfo.getBundleId(); export const getDeviceModel = DeviceInfo.getModel(); // Theme is supported by system on iOS 13+ or Android 10+ -export const supportSystemTheme = () => { +export const supportSystemTheme = (): boolean => { const systemVersion = parseInt(DeviceInfo.getSystemVersion(), 10); return systemVersion >= (isIOS ? 13 : 10); }; diff --git a/app/utils/isValidEmail.js b/app/utils/isValidEmail.ts similarity index 78% rename from app/utils/isValidEmail.js rename to app/utils/isValidEmail.ts index a8bd490f983..e230fc3289d 100644 --- a/app/utils/isValidEmail.js +++ b/app/utils/isValidEmail.ts @@ -1,4 +1,4 @@ -export default function isValidEmail(email) { +export default function isValidEmail(email: string): boolean { /* eslint-disable no-useless-escape */ const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; From 2d25f76468e75be26b9981262ebf593c9e30a898 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 7 Dec 2021 12:37:12 -0300 Subject: [PATCH 05/28] events, fetch, goRoom, isReadOnly, layoutAnimation, media, messageTypes, and minor tweaks IRoom, shareview --- app/definitions/IRoom.ts | 6 +++++ app/utils/{events.js => events.ts} | 9 +++---- app/utils/{fetch.js => fetch.ts} | 13 +++++++--- app/utils/{goRoom.js => goRoom.ts} | 24 +++++++++++++++---- app/utils/{isReadOnly.js => isReadOnly.ts} | 8 ++++--- ...{layoutAnimation.js => layoutAnimation.ts} | 0 app/utils/{media.js => media.ts} | 12 +++++++--- .../{messageTypes.js => messageTypes.ts} | 0 app/views/CreateDiscussionView/interfaces.ts | 3 ++- app/views/ShareView/index.tsx | 4 ++-- 10 files changed, 59 insertions(+), 20 deletions(-) rename app/utils/{events.js => events.ts} (74%) rename app/utils/{fetch.js => fetch.ts} (80%) rename app/utils/{goRoom.js => goRoom.ts} (64%) rename app/utils/{isReadOnly.js => isReadOnly.ts} (61%) rename app/utils/{layoutAnimation.js => layoutAnimation.ts} (100%) rename app/utils/{media.js => media.ts} (64%) rename app/utils/{messageTypes.js => messageTypes.ts} (100%) diff --git a/app/definitions/IRoom.ts b/app/definitions/IRoom.ts index 786c1d7c85b..c6980e9bac8 100644 --- a/app/definitions/IRoom.ts +++ b/app/definitions/IRoom.ts @@ -24,4 +24,10 @@ export interface IRoom extends IRocketChatRecord { autoTranslate?: boolean; observe?: Function; usedCannedResponse: string; + search?: boolean; + username?: string; + archived?: boolean; + ro?: boolean; + muted?: string[]; + joinCodeRequired?: boolean; } diff --git a/app/utils/events.js b/app/utils/events.ts similarity index 74% rename from app/utils/events.js rename to app/utils/events.ts index 8e67fc82e79..10857dedd89 100644 --- a/app/utils/events.js +++ b/app/utils/events.ts @@ -1,11 +1,12 @@ import log from './log'; class EventEmitter { + private events: { [key: string]: any }; constructor() { this.events = {}; } - addEventListener(event, listener) { + addEventListener(event: string, listener: any) { if (typeof this.events[event] !== 'object') { this.events[event] = []; } @@ -13,7 +14,7 @@ class EventEmitter { return listener; } - removeListener(event, listener) { + removeListener(event: string, listener: any) { if (typeof this.events[event] === 'object') { const idx = this.events[event].indexOf(listener); if (idx > -1) { @@ -25,9 +26,9 @@ class EventEmitter { } } - emit(event, ...args) { + emit(event: string, ...args: any[]) { if (typeof this.events[event] === 'object') { - this.events[event].forEach(listener => { + this.events[event].forEach((listener: any) => { try { listener.apply(this, args); } catch (e) { diff --git a/app/utils/fetch.js b/app/utils/fetch.ts similarity index 80% rename from app/utils/fetch.js rename to app/utils/fetch.ts index 84f5669aeb5..5f257c7d972 100644 --- a/app/utils/fetch.js +++ b/app/utils/fetch.ts @@ -4,15 +4,20 @@ import { settings as RocketChatSettings } from '@rocket.chat/sdk'; import RocketChat from '../lib/rocketchat'; +interface CustomHeaders { + 'User-Agent': string; + Authorization?: string; +} + // this form is required by Rocket.Chat's parser in "app/statistics/server/lib/UAParserCustom.js" -export const headers = { +export const headers: CustomHeaders = { 'User-Agent': `RC Mobile; ${ Platform.OS } ${DeviceInfo.getSystemVersion()}; v${DeviceInfo.getVersion()} (${DeviceInfo.getBuildNumber()})` }; let _basicAuth; -export const setBasicAuth = basicAuth => { +export const setBasicAuth = (basicAuth: string): void => { _basicAuth = basicAuth; if (basicAuth) { RocketChatSettings.customHeaders = { ...headers, Authorization: `Basic ${_basicAuth}` }; @@ -24,12 +29,14 @@ export const BASIC_AUTH_KEY = 'BASIC_AUTH_KEY'; RocketChatSettings.customHeaders = headers; -export default (url, options = {}) => { +export default (url: string, options: any = {}): Promise => { let customOptions = { ...options, headers: RocketChatSettings.customHeaders }; if (options && options.headers) { customOptions = { ...customOptions, headers: { ...options.headers, ...customOptions.headers } }; } + // @ts-ignore if (RocketChat.controller) { + // @ts-ignore const { signal } = RocketChat.controller; customOptions = { ...customOptions, signal }; } diff --git a/app/utils/goRoom.js b/app/utils/goRoom.ts similarity index 64% rename from app/utils/goRoom.js rename to app/utils/goRoom.ts index 1025a17d4ff..36c46b85ab6 100644 --- a/app/utils/goRoom.js +++ b/app/utils/goRoom.ts @@ -1,7 +1,8 @@ +import { IRoom, RoomType } from '../definitions/IRoom'; import Navigation from '../lib/Navigation'; import RocketChat from '../lib/rocketchat'; -const navigate = ({ item, isMasterDetail, ...props }) => { +const navigate = ({ item, isMasterDetail, ...props }: { item: IItem; isMasterDetail: boolean; navigationMethod?: any }) => { let navigationMethod = props.navigationMethod ?? Navigation.navigate; if (isMasterDetail) { @@ -20,7 +21,22 @@ const navigate = ({ item, isMasterDetail, ...props }) => { }); }; -export const goRoom = async ({ item = {}, isMasterDetail = false, ...props }) => { +interface IItem extends Partial { + rid: string; + name: string; + t: RoomType; +} + +export const goRoom = async ({ + item, + isMasterDetail = false, + ...props +}: { + item: IItem; + isMasterDetail: boolean; + navigationMethod?: any; + jumpToMessageId?: string; +}): Promise => { if (item.t === 'd' && item.search) { // if user is using the search we need first to join/create room try { @@ -30,8 +46,8 @@ export const goRoom = async ({ item = {}, isMasterDetail = false, ...props }) => return navigate({ item: { rid: result.room._id, - name: username, - t: 'd' + name: username!, + t: RoomType.DIRECT }, isMasterDetail, ...props diff --git a/app/utils/isReadOnly.js b/app/utils/isReadOnly.ts similarity index 61% rename from app/utils/isReadOnly.js rename to app/utils/isReadOnly.ts index 62ae4fffee2..f9ec98523e6 100644 --- a/app/utils/isReadOnly.js +++ b/app/utils/isReadOnly.ts @@ -1,16 +1,18 @@ import RocketChat from '../lib/rocketchat'; import reduxStore from '../lib/createStore'; +import { IRoom } from '../definitions/IRoom'; -const canPostReadOnly = async ({ rid }) => { +const canPostReadOnly = async ({ rid }: { rid: string }) => { // TODO: this is not reactive. If this permission changes, the component won't be updated const postReadOnlyPermission = reduxStore.getState().permissions['post-readonly']; const permission = await RocketChat.hasPermission([postReadOnlyPermission], rid); return permission[0]; }; -const isMuted = (room, user) => room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username); +const isMuted = (room: IRoom, user: { username: any }) => + room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username); -export const isReadOnly = async (room, user) => { +export const isReadOnly = async (room: IRoom, user: { id?: string; username: string; token?: string }): Promise => { if (room.archived) { return true; } diff --git a/app/utils/layoutAnimation.js b/app/utils/layoutAnimation.ts similarity index 100% rename from app/utils/layoutAnimation.js rename to app/utils/layoutAnimation.ts diff --git a/app/utils/media.js b/app/utils/media.ts similarity index 64% rename from app/utils/media.js rename to app/utils/media.ts index b05f95a9410..855a9a68289 100644 --- a/app/utils/media.js +++ b/app/utils/media.ts @@ -1,4 +1,10 @@ -export const canUploadFile = (file, allowList, maxFileSize) => { +import { IAttachment } from '../views/ShareView/interfaces'; + +export const canUploadFile = ( + file: IAttachment, + allowList: string, + maxFileSize: number +): { success: boolean; error?: string } => { if (!(file && file.path)) { return { success: true }; } @@ -10,11 +16,11 @@ export const canUploadFile = (file, allowList, maxFileSize) => { return { success: true }; } const allowedMime = allowList.split(','); - if (allowedMime.includes(file.mime)) { + if (allowedMime.includes(file.mime!)) { return { success: true }; } const wildCardGlob = '/*'; - const wildCards = allowedMime.filter(item => item.indexOf(wildCardGlob) > 0); + const wildCards = allowedMime.filter((item: string) => item.indexOf(wildCardGlob) > 0); if (file.mime && wildCards.includes(file.mime.replace(/(\/.*)$/, wildCardGlob))) { return { success: true }; } diff --git a/app/utils/messageTypes.js b/app/utils/messageTypes.ts similarity index 100% rename from app/utils/messageTypes.js rename to app/utils/messageTypes.ts diff --git a/app/views/CreateDiscussionView/interfaces.ts b/app/views/CreateDiscussionView/interfaces.ts index e9d076b16ac..42cfdc73375 100644 --- a/app/views/CreateDiscussionView/interfaces.ts +++ b/app/views/CreateDiscussionView/interfaces.ts @@ -2,6 +2,7 @@ import { RouteProp } from '@react-navigation/core'; import { StackNavigationProp } from '@react-navigation/stack'; import { NewMessageStackParamList } from '../../stacks/types'; +import { RoomType } from '../../definitions/IRoom'; export interface ICreateChannelViewProps { navigation: StackNavigationProp; @@ -15,7 +16,7 @@ export interface ICreateChannelViewProps { loading: boolean; result: { rid: string; - t: string; + t: RoomType; prid: string; }; failure: boolean; diff --git a/app/views/ShareView/index.tsx b/app/views/ShareView/index.tsx index 4061626e69a..58fd166d633 100644 --- a/app/views/ShareView/index.tsx +++ b/app/views/ShareView/index.tsx @@ -38,7 +38,7 @@ interface IShareViewState { room: IRoom; thread: any; // change maxFileSize: number; - mediaAllowList: number; + mediaAllowList: string; } interface IShareViewProps { @@ -51,7 +51,7 @@ interface IShareViewProps { token: string; }; server: string; - FileUpload_MediaTypeWhiteList?: number; + FileUpload_MediaTypeWhiteList?: string; FileUpload_MaxFileSize?: number; } From 844427ce1b0e3da8bd6b4923e748eb3e28065106 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 7 Dec 2021 19:10:23 -0300 Subject: [PATCH 06/28] moment, openLink, random, review, room, server, theme, fix externalModules --- app/definitions/IRoom.ts | 2 ++ app/definitions/ITheme.ts | 4 ++++ app/externalModules.d.ts | 1 + app/index.tsx | 3 ++- app/utils/{moment.js => moment.ts} | 4 ++-- app/utils/{openLink.js => openLink.ts} | 9 +++++---- app/utils/{random.js => random.ts} | 2 +- app/utils/{review.js => review.ts} | 4 ++-- app/utils/{room.js => room.ts} | 24 +++++++++++++++++------- app/utils/{server.js => server.ts} | 2 +- app/utils/{theme.js => theme.ts} | 16 +++++++++------- 11 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 app/definitions/ITheme.ts rename app/utils/{moment.js => moment.ts} (57%) rename app/utils/{openLink.js => openLink.ts} (83%) rename app/utils/{random.js => random.ts} (80%) rename app/utils/{review.js => review.ts} (96%) rename app/utils/{room.js => room.ts} (56%) rename app/utils/{server.js => server.ts} (84%) rename app/utils/{theme.js => theme.ts} (73%) diff --git a/app/definitions/IRoom.ts b/app/definitions/IRoom.ts index c6980e9bac8..444caf8e070 100644 --- a/app/definitions/IRoom.ts +++ b/app/definitions/IRoom.ts @@ -30,4 +30,6 @@ export interface IRoom extends IRocketChatRecord { ro?: boolean; muted?: string[]; joinCodeRequired?: boolean; + blocked?: boolean; + blocker?: boolean; } diff --git a/app/definitions/ITheme.ts b/app/definitions/ITheme.ts new file mode 100644 index 00000000000..f804149c379 --- /dev/null +++ b/app/definitions/ITheme.ts @@ -0,0 +1,4 @@ +export interface IThemePreference { + currentTheme: string; + darkLevel: string; +} diff --git a/app/externalModules.d.ts b/app/externalModules.d.ts index f68cb5e3914..02c57204f50 100644 --- a/app/externalModules.d.ts +++ b/app/externalModules.d.ts @@ -13,3 +13,4 @@ declare module 'react-native-mime-types'; declare module 'react-native-restart'; declare module 'react-native-prompt-android'; declare module 'react-native-jitsi-meet'; +declare module 'rn-root-view'; diff --git a/app/index.tsx b/app/index.tsx index e6457e233fd..6b2a0cf293e 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -30,6 +30,7 @@ import InAppNotification from './containers/InAppNotification'; import { ActionSheetProvider } from './containers/ActionSheet'; import debounce from './utils/debounce'; import { isFDroidBuild } from './constants/environment'; +import { IThemePreference } from './definitions/ITheme'; RNScreens.enableScreens(); @@ -175,7 +176,7 @@ export default class Root extends React.Component<{}, IState> { setTheme = (newTheme = {}) => { // change theme state this.setState( - prevState => newThemeState(prevState, newTheme), + prevState => newThemeState(prevState, newTheme as IThemePreference), () => { const { themePreferences } = this.state; // subscribe to Appearance changes diff --git a/app/utils/moment.js b/app/utils/moment.ts similarity index 57% rename from app/utils/moment.js rename to app/utils/moment.ts index 064b0f7f979..3379429c7ee 100644 --- a/app/utils/moment.js +++ b/app/utils/moment.ts @@ -1,4 +1,4 @@ -const localeKeys = { +const localeKeys: { [key: string]: string } = { en: 'en', ru: 'ru', 'pt-BR': 'pt-br', @@ -13,4 +13,4 @@ const localeKeys = { 'zh-TW': 'zh-tw' }; -export const toMomentLocale = locale => localeKeys[locale]; +export const toMomentLocale = (locale: string): string => localeKeys[locale]; diff --git a/app/utils/openLink.js b/app/utils/openLink.ts similarity index 83% rename from app/utils/openLink.js rename to app/utils/openLink.ts index 92df16a70af..f716519ae8f 100644 --- a/app/utils/openLink.js +++ b/app/utils/openLink.ts @@ -14,7 +14,7 @@ const scheme = { brave: 'brave:' }; -const appSchemeURL = (url, browser) => { +const appSchemeURL = (url: string, browser: string) => { let schemeUrl = url; const parsedUrl = parse(url, true); const { protocol } = parsedUrl; @@ -35,7 +35,7 @@ const appSchemeURL = (url, browser) => { return schemeUrl; }; -const openLink = async (url, theme = 'light') => { +const openLink = async (url: string, theme = 'light'): Promise => { try { const browser = await UserPreferences.getStringAsync(DEFAULT_BROWSER_KEY); @@ -43,11 +43,12 @@ const openLink = async (url, theme = 'light') => { await WebBrowser.openBrowserAsync(url, { toolbarColor: themes[theme].headerBackground, controlsColor: themes[theme].headerTintColor, - collapseToolbar: true, + // https://github.com/expo/expo/pull/4923 + enableBarCollapsing: true, showTitle: true }); } else { - const schemeUrl = appSchemeURL(url, browser.replace(':', '')); + const schemeUrl = appSchemeURL(url, browser!.replace(':', '')); await Linking.openURL(schemeUrl); } } catch { diff --git a/app/utils/random.js b/app/utils/random.ts similarity index 80% rename from app/utils/random.js rename to app/utils/random.ts index 8f6adb88061..2d2cd178b4e 100644 --- a/app/utils/random.js +++ b/app/utils/random.ts @@ -1,4 +1,4 @@ -export default function random(length) { +export default function random(length: number): string { let text = ''; const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i += 1) { diff --git a/app/utils/review.js b/app/utils/review.ts similarity index 96% rename from app/utils/review.js rename to app/utils/review.ts index 15f1cf968ff..326d40010ad 100644 --- a/app/utils/review.js +++ b/app/utils/review.ts @@ -15,7 +15,7 @@ const reviewDelay = 2000; const numberOfDays = 7; const numberOfPositiveEvent = 5; -const daysBetween = (date1, date2) => { +const daysBetween = (date1: Date, date2: Date) => { const one_day = 1000 * 60 * 60 * 24; const date1_ms = date1.getTime(); const date2_ms = date2.getTime(); @@ -32,7 +32,7 @@ const onCancelPress = () => { } }; -export const onReviewPress = async () => { +export const onReviewPress = async (): Promise => { logEvent(events.SE_REVIEW_THIS_APP); await onCancelPress(); try { diff --git a/app/utils/room.js b/app/utils/room.ts similarity index 56% rename from app/utils/room.js rename to app/utils/room.ts index 67df65a98c8..6520db65664 100644 --- a/app/utils/room.js +++ b/app/utils/room.ts @@ -1,9 +1,10 @@ import moment from 'moment'; +import { IRoom } from '../definitions/IRoom'; import { themes } from '../constants/colors'; import I18n from '../i18n'; -export const isBlocked = room => { +export const isBlocked = (room: IRoom): boolean => { if (room) { const { t, blocked, blocker } = room; if (t === 'd' && (blocked || blocker)) { @@ -13,14 +14,14 @@ export const isBlocked = room => { return false; }; -export const capitalize = s => { +export const capitalize = (s: string): string => { if (typeof s !== 'string') { return ''; } return s.charAt(0).toUpperCase() + s.slice(1); }; -export const formatDate = date => +export const formatDate = (date: Date): string => moment(date).calendar(null, { lastDay: `[${I18n.t('Yesterday')}]`, sameDay: 'LT', @@ -28,7 +29,7 @@ export const formatDate = date => sameElse: 'L' }); -export const formatDateThreads = date => +export const formatDateThreads = (date: Date): string => moment(date).calendar(null, { sameDay: 'LT', lastDay: `[${I18n.t('Yesterday')}] LT`, @@ -36,7 +37,15 @@ export const formatDateThreads = date => sameElse: 'LL' }); -export const getBadgeColor = ({ subscription, messageId, theme }) => { +export const getBadgeColor = ({ + subscription, + messageId, + theme +}: { + subscription: any; + messageId: string; + theme: string; +}): any => { if (subscription?.tunreadUser?.includes(messageId)) { return themes[theme].mentionMeColor; } @@ -48,6 +57,7 @@ export const getBadgeColor = ({ subscription, messageId, theme }) => { } }; -export const makeThreadName = messageRecord => messageRecord.msg || messageRecord?.attachments[0]?.title; +export const makeThreadName = (messageRecord: { id?: string | undefined; msg?: any; attachments?: any }): string => + messageRecord.msg || messageRecord?.attachments[0]?.title; -export const isTeamRoom = ({ teamId, joined }) => teamId && joined; +export const isTeamRoom = ({ teamId, joined }: { teamId: string; joined: boolean }): boolean => !!teamId && joined; diff --git a/app/utils/server.js b/app/utils/server.ts similarity index 84% rename from app/utils/server.js rename to app/utils/server.ts index e7be96b3055..52064757b85 100644 --- a/app/utils/server.js +++ b/app/utils/server.ts @@ -3,7 +3,7 @@ url = 'https://open.rocket.chat/method' hostname = 'open.rocket.chat' */ -export const extractHostname = url => { +export const extractHostname = (url: string): string => { let hostname; if (url.indexOf('//') > -1) { diff --git a/app/utils/theme.js b/app/utils/theme.ts similarity index 73% rename from app/utils/theme.js rename to app/utils/theme.ts index c9038941d83..c94150198ad 100644 --- a/app/utils/theme.js +++ b/app/utils/theme.ts @@ -2,12 +2,13 @@ import { Appearance } from 'react-native-appearance'; import changeNavigationBarColor from 'react-native-navigation-bar-color'; import setRootViewColor from 'rn-root-view'; +import { IThemePreference } from '../definitions/ITheme'; import { themes } from '../constants/colors'; import { isAndroid } from './deviceInfo'; -let themeListener; +let themeListener: { remove: () => void } | null; -export const defaultTheme = () => { +export const defaultTheme = (): string => { const systemTheme = Appearance.getColorScheme(); if (systemTheme && systemTheme !== 'no-preference') { return systemTheme; @@ -15,7 +16,7 @@ export const defaultTheme = () => { return 'light'; }; -export const getTheme = themePreferences => { +export const getTheme = (themePreferences: IThemePreference): string => { const { darkLevel, currentTheme } = themePreferences; let theme = currentTheme; if (currentTheme === 'automatic') { @@ -24,7 +25,7 @@ export const getTheme = themePreferences => { return theme === 'dark' ? darkLevel : 'light'; }; -export const newThemeState = (prevState, newTheme) => { +export const newThemeState = (prevState: any, newTheme: IThemePreference) => { // new theme preferences const themePreferences = { ...prevState.themePreferences, @@ -35,12 +36,13 @@ export const newThemeState = (prevState, newTheme) => { return { themePreferences, theme: getTheme(themePreferences) }; }; -export const setNativeTheme = async themePreferences => { +export const setNativeTheme = async (themePreferences: IThemePreference): Promise => { const theme = getTheme(themePreferences); if (isAndroid) { const iconsLight = theme === 'light'; try { - await changeNavigationBarColor(themes[theme].navbarBackground, iconsLight); + // The late param as default is true @ react-native-navigation-bar-color/src/index.js line 8 + await changeNavigationBarColor(themes[theme].navbarBackground, iconsLight, true); } catch (error) { // Do nothing } @@ -55,7 +57,7 @@ export const unsubscribeTheme = () => { } }; -export const subscribeTheme = (themePreferences, setTheme) => { +export const subscribeTheme = (themePreferences: IThemePreference, setTheme: () => void): void => { const { currentTheme } = themePreferences; if (!themeListener && currentTheme === 'automatic') { // not use listener params because we use getTheme From 3296798f7caf8d2621bf37e023e4547bee18b73d Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 15:17:09 -0300 Subject: [PATCH 07/28] sslPinning, deleted info and throttle --- app/utils/info.js | 25 --------------------- app/utils/{sslPinning.js => sslPinning.ts} | 3 ++- app/utils/throttle.js | 26 ---------------------- 3 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 app/utils/info.js rename app/utils/{sslPinning.js => sslPinning.ts} (95%) delete mode 100644 app/utils/throttle.js diff --git a/app/utils/info.js b/app/utils/info.js deleted file mode 100644 index 5d72f200e5a..00000000000 --- a/app/utils/info.js +++ /dev/null @@ -1,25 +0,0 @@ -import { Alert } from 'react-native'; - -import I18n from '../i18n'; - -export const showErrorAlert = (message, title, onPress = () => {}) => - Alert.alert(title, message, [{ text: 'OK', onPress }], { cancelable: true }); - -export const showConfirmationAlert = ({ title, message, confirmationText, dismissText = I18n.t('Cancel'), onPress, onCancel }) => - Alert.alert( - title || I18n.t('Are_you_sure_question_mark'), - message, - [ - { - text: dismissText, - onPress: onCancel, - style: 'cancel' - }, - { - text: confirmationText, - style: 'destructive', - onPress - } - ], - { cancelable: false } - ); diff --git a/app/utils/sslPinning.js b/app/utils/sslPinning.ts similarity index 95% rename from app/utils/sslPinning.js rename to app/utils/sslPinning.ts index 50f944e63f3..8bf6e7171f7 100644 --- a/app/utils/sslPinning.js +++ b/app/utils/sslPinning.ts @@ -14,6 +14,7 @@ const RCSSLPinning = Platform.select({ new Promise(async (resolve, reject) => { try { const res = await DocumentPicker.pick({ + // @ts-ignore type: ['com.rsa.pkcs-12'] }); const { uri, name } = res; @@ -49,7 +50,7 @@ const RCSSLPinning = Platform.select({ reject(e); } }), - setCertificate: async (alias, server) => { + setCertificate: async (alias: any, server: string) => { if (alias) { const certificate = await UserPreferences.getMapAsync(alias); await UserPreferences.setMapAsync(extractHostname(server), certificate); diff --git a/app/utils/throttle.js b/app/utils/throttle.js deleted file mode 100644 index 88751335f61..00000000000 --- a/app/utils/throttle.js +++ /dev/null @@ -1,26 +0,0 @@ -export default function throttle(fn, threshhold = 250, scope) { - let last; - let deferTimer; - - const _throttle = (...args) => { - const context = scope || this; - - const now = +new Date(); - - if (last && now < last + threshhold) { - // hold on to it - clearTimeout(deferTimer); - deferTimer = setTimeout(() => { - last = now; - fn.apply(context, args); - }, threshhold); - } else { - last = now; - fn.apply(context, args); - } - }; - - _throttle.stop = () => clearTimeout(deferTimer); - - return _throttle; -} From a343bc01a85537aed06ed5a9e0dcf5023b317b46 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 15:37:46 -0300 Subject: [PATCH 08/28] info.ts and tweaks --- app/containers/MessageActions/index.tsx | 2 -- app/containers/message/interfaces.ts | 2 +- app/share.tsx | 2 +- app/utils/info.ts | 41 +++++++++++++++++++++++++ app/views/E2EEncryptionSecurityView.tsx | 4 --- app/views/NewServerView/index.tsx | 3 +- app/views/ProfileView/index.tsx | 1 - app/views/SettingsView/index.tsx | 2 -- 8 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 app/utils/info.ts diff --git a/app/containers/MessageActions/index.tsx b/app/containers/MessageActions/index.tsx index eb9be9675e5..4d32abf3b4d 100644 --- a/app/containers/MessageActions/index.tsx +++ b/app/containers/MessageActions/index.tsx @@ -305,8 +305,6 @@ const MessageActions = React.memo( }; const handleDelete = (message: any) => { - // TODO - migrate this function for ts when fix the lint erros - // @ts-ignore showConfirmationAlert({ message: I18n.t('You_will_not_be_able_to_recover_this_message'), confirmationText: I18n.t('Delete'), diff --git a/app/containers/message/interfaces.ts b/app/containers/message/interfaces.ts index c9be40af91b..866e7e40ec9 100644 --- a/app/containers/message/interfaces.ts +++ b/app/containers/message/interfaces.ts @@ -84,7 +84,7 @@ export interface IMessageContent { export interface IMessageDiscussion { msg: string; dcount: number; - dlm: string; + dlm: Date; theme: string; } diff --git a/app/share.tsx b/app/share.tsx index daee2fba0bf..63db1fdad78 100644 --- a/app/share.tsx +++ b/app/share.tsx @@ -132,7 +132,7 @@ class Root extends React.Component<{}, IState> { setCurrentScreen(currentRouteName); }; - setTheme = (newTheme = {}) => { + setTheme = (newTheme: any = {}) => { // change theme state this.setState( prevState => newThemeState(prevState, newTheme), diff --git a/app/utils/info.ts b/app/utils/info.ts new file mode 100644 index 00000000000..da882ee41dc --- /dev/null +++ b/app/utils/info.ts @@ -0,0 +1,41 @@ +import { Alert } from 'react-native'; + +import I18n from '../i18n'; + +export const showErrorAlert = (message: string, title?: string, onPress = () => {}): void => + Alert.alert(title!, message, [{ text: 'OK', onPress }], { cancelable: true }); + +interface IShowConfirmationAlert { + title?: string; + message: string; + confirmationText: string; + dismissText?: string; + onPress: () => void; + onCancel?: () => void; +} + +export const showConfirmationAlert = ({ + title, + message, + confirmationText, + dismissText = I18n.t('Cancel'), + onPress, + onCancel +}: IShowConfirmationAlert): void => + Alert.alert( + title || I18n.t('Are_you_sure_question_mark'), + message, + [ + { + text: dismissText, + onPress: onCancel, + style: 'cancel' + }, + { + text: confirmationText, + style: 'destructive', + onPress + } + ], + { cancelable: false } + ); diff --git a/app/views/E2EEncryptionSecurityView.tsx b/app/views/E2EEncryptionSecurityView.tsx index d5b0b27a2e8..34759043041 100644 --- a/app/views/E2EEncryptionSecurityView.tsx +++ b/app/views/E2EEncryptionSecurityView.tsx @@ -75,8 +75,6 @@ class E2EEncryptionSecurityView extends React.Component { - // TODO: Remove ts-ignore when migrate the showConfirmationAlert - // @ts-ignore showConfirmationAlert({ title: I18n.t('Are_you_sure_question_mark'), message: I18n.t('E2E_encryption_reset_message'), diff --git a/app/views/NewServerView/index.tsx b/app/views/NewServerView/index.tsx index aaacdf90f01..89188098fdf 100644 --- a/app/views/NewServerView/index.tsx +++ b/app/views/NewServerView/index.tsx @@ -274,11 +274,10 @@ class NewServerView extends React.Component { 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'), + // @ts-ignore onPress: this.setState({ certificate: null }) // We not need delete file from DocumentPicker because it is a temp file }); }; diff --git a/app/views/ProfileView/index.tsx b/app/views/ProfileView/index.tsx index d0ca64eec91..fc409002df8 100644 --- a/app/views/ProfileView/index.tsx +++ b/app/views/ProfileView/index.tsx @@ -424,7 +424,6 @@ class ProfileView extends React.Component logoutOtherLocations = () => { logEvent(events.PL_OTHER_LOCATIONS); - // @ts-ignore showConfirmationAlert({ message: I18n.t('You_will_be_logged_out_from_other_locations'), confirmationText: I18n.t('Logout'), diff --git a/app/views/SettingsView/index.tsx b/app/views/SettingsView/index.tsx index edad2822e2e..3ab35b840c3 100644 --- a/app/views/SettingsView/index.tsx +++ b/app/views/SettingsView/index.tsx @@ -88,7 +88,6 @@ class SettingsView extends React.Component { handleLogout = () => { logEvent(events.SE_LOG_OUT); - // @ts-ignore showConfirmationAlert({ message: I18n.t('You_will_be_logged_out_of_this_application'), confirmationText: I18n.t('Logout'), @@ -98,7 +97,6 @@ class SettingsView extends React.Component { handleClearCache = () => { logEvent(events.SE_CLEAR_LOCAL_SERVER_CACHE); - /* @ts-ignore */ showConfirmationAlert({ message: I18n.t('This_will_clear_all_your_offline_data'), confirmationText: I18n.t('Clear'), From 756a4e2ea5d1a443906e0c511abd11352ea4ef20 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 20:03:08 -0300 Subject: [PATCH 09/28] localAuthentication and his tweaks --- app/definitions/IServer.ts | 8 +++- ...thentication.js => localAuthentication.ts} | 45 +++++++++++-------- app/views/ScreenLockConfigView.tsx | 18 +++----- 3 files changed, 38 insertions(+), 33 deletions(-) rename app/utils/{localAuthentication.js => localAuthentication.ts} (73%) diff --git a/app/definitions/IServer.ts b/app/definitions/IServer.ts index 534a29c9ce2..4e21bef8e41 100644 --- a/app/definitions/IServer.ts +++ b/app/definitions/IServer.ts @@ -1,3 +1,5 @@ +import Model from '@nozbe/watermelondb/Model'; + export interface IServer { name: string; iconURL: string; @@ -8,9 +10,11 @@ export interface IServer { version: string; lastLocalAuthenticatedSession: Date; autoLock: boolean; - autoLockTime: number | null; - biometry: boolean | null; + autoLockTime?: number; + biometry?: boolean; uniqueID: string; enterpriseModules: string; E2E_Enable: boolean; } + +export interface IServerRecord extends IServer, Model {} diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.ts similarity index 73% rename from app/utils/localAuthentication.js rename to app/utils/localAuthentication.ts index 29f25685085..89c1d602fa5 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.ts @@ -16,16 +16,17 @@ import { } from '../constants/localAuthentication'; import I18n from '../i18n'; import { setLocalAuthenticated } from '../actions/login'; +import { IServerRecord } from '../definitions/IServer'; import EventEmitter from './events'; import { isIOS } from './deviceInfo'; -export const saveLastLocalAuthenticationSession = async (server, serverRecord) => { +export const saveLastLocalAuthenticationSession = async (server: string, serverRecord?: IServerRecord): Promise => { const serversDB = database.servers; const serversCollection = serversDB.get('servers'); - await serversDB.action(async () => { + await serversDB.write(async () => { try { if (!serverRecord) { - serverRecord = await serversCollection.find(server); + serverRecord = (await serversCollection.find(server)) as IServerRecord; } await serverRecord.update(record => { record.lastLocalAuthenticatedSession = new Date(); @@ -36,31 +37,31 @@ export const saveLastLocalAuthenticationSession = async (server, serverRecord) = }); }; -export const resetAttempts = () => AsyncStorage.multiRemove([LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY]); +export const resetAttempts = (): Promise => AsyncStorage.multiRemove([LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY]); -const openModal = hasBiometry => - new Promise(resolve => { +const openModal = (hasBiometry: boolean) => + new Promise(resolve => { EventEmitter.emit(LOCAL_AUTHENTICATE_EMITTER, { submit: () => resolve(), hasBiometry }); }); -const openChangePasscodeModal = ({ force }) => - new Promise((resolve, reject) => { +const openChangePasscodeModal = ({ force }: { force: boolean }) => + new Promise((resolve, reject) => { EventEmitter.emit(CHANGE_PASSCODE_EMITTER, { - submit: passcode => resolve(passcode), + submit: (passcode: string) => resolve(passcode), cancel: () => reject(), force }); }); -export const changePasscode = async ({ force = false }) => { +export const changePasscode = async ({ force = false }: { force: boolean }): Promise => { const passcode = await openChangePasscodeModal({ force }); await UserPreferences.setStringAsync(PASSCODE_KEY, sha256(passcode)); }; -export const biometryAuth = force => +export const biometryAuth = (force?: boolean): Promise => LocalAuthentication.authenticateAsync({ disableDeviceFallback: true, cancelLabel: force ? I18n.t('Dont_activate') : I18n.t('Local_authentication_biometry_fallback'), @@ -71,11 +72,11 @@ export const biometryAuth = force => * It'll help us to get the permission to use FaceID * and enable/disable the biometry when user put their first passcode */ -const checkBiometry = async serverRecord => { +const checkBiometry = async (serverRecord: IServerRecord) => { const serversDB = database.servers; const result = await biometryAuth(true); - await serversDB.action(async () => { + await serversDB.write(async () => { try { await serverRecord.update(record => { record.biometry = !!result?.success; @@ -86,7 +87,13 @@ const checkBiometry = async serverRecord => { }); }; -export const checkHasPasscode = async ({ force = true, serverRecord }) => { +export const checkHasPasscode = async ({ + force = true, + serverRecord +}: { + force?: boolean; + serverRecord: IServerRecord; +}): Promise<{ newPasscode?: boolean } | void> => { const storedPasscode = await UserPreferences.getStringAsync(PASSCODE_KEY); if (!storedPasscode) { await changePasscode({ force }); @@ -96,13 +103,13 @@ export const checkHasPasscode = async ({ force = true, serverRecord }) => { return Promise.resolve(); }; -export const localAuthenticate = async server => { +export const localAuthenticate = async (server: string): Promise => { const serversDB = database.servers; const serversCollection = serversDB.get('servers'); - let serverRecord; + let serverRecord: IServerRecord; try { - serverRecord = await serversCollection.find(server); + serverRecord = (await serversCollection.find(server)) as IServerRecord; } catch (error) { return Promise.reject(); } @@ -125,7 +132,7 @@ export const localAuthenticate = async server => { const diffToLastSession = moment().diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds'); // if last authenticated session is older than configured auto lock time, authentication is required - if (diffToLastSession >= serverRecord?.autoLockTime) { + if (diffToLastSession >= serverRecord.autoLockTime!) { // set isLocalAuthenticated to false store.dispatch(setLocalAuthenticated(false)); @@ -150,7 +157,7 @@ export const localAuthenticate = async server => { } }; -export const supportedBiometryLabel = async () => { +export const supportedBiometryLabel = async (): Promise => { try { const enrolled = await LocalAuthentication.isEnrolledAsync(); diff --git a/app/views/ScreenLockConfigView.tsx b/app/views/ScreenLockConfigView.tsx index 57638f4178b..add03a1ad3d 100644 --- a/app/views/ScreenLockConfigView.tsx +++ b/app/views/ScreenLockConfigView.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { Switch } from 'react-native'; 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'; @@ -15,15 +14,10 @@ import { changePasscode, checkHasPasscode, supportedBiometryLabel } from '../uti import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; import { events, logEvent } from '../utils/log'; +import { IServerRecord } from '../definitions/IServer'; const DEFAULT_BIOMETRY = false; -interface IServerRecords extends Model { - autoLock?: boolean; - autoLockTime?: number; - biometry?: boolean; -} - interface IItem { title: string; value: number; @@ -38,14 +32,14 @@ interface IScreenLockConfigViewProps { } interface IScreenLockConfigViewState { - autoLock?: boolean; + autoLock: boolean; autoLockTime?: number | null; biometry?: boolean; - biometryLabel: null; + biometryLabel: string | null; } class ScreenLockConfigView extends React.Component { - private serverRecord?: IServerRecords; + private serverRecord?: IServerRecord; private observable?: Subscription; @@ -98,7 +92,7 @@ class ScreenLockConfigView extends React.Component Date: Wed, 8 Dec 2021 20:19:32 -0300 Subject: [PATCH 10/28] shortnameToUnicode and base64 folders --- app/utils/base64-js/{index.js => index.ts} | 19 ++++++++++--------- .../shortnameToUnicode/{ascii.js => ascii.ts} | 2 +- .../{emojis.js => emojis.ts} | 2 +- .../shortnameToUnicode/{index.js => index.ts} | 8 ++++---- 4 files changed, 16 insertions(+), 15 deletions(-) rename app/utils/base64-js/{index.js => index.ts} (87%) rename app/utils/shortnameToUnicode/{ascii.js => ascii.ts} (98%) rename app/utils/shortnameToUnicode/{emojis.js => emojis.ts} (99%) rename app/utils/shortnameToUnicode/{index.js => index.ts} (80%) diff --git a/app/utils/base64-js/index.js b/app/utils/base64-js/index.ts similarity index 87% rename from app/utils/base64-js/index.js rename to app/utils/base64-js/index.ts index 5616f71df3f..6d2936bc61b 100644 --- a/app/utils/base64-js/index.js +++ b/app/utils/base64-js/index.ts @@ -1,8 +1,8 @@ /* eslint-disable no-bitwise */ // https://github.com/beatgammit/base64-js/blob/master/index.js -const lookup = []; -const revLookup = []; +const lookup: any[] = []; +const revLookup: number[] = []; const Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; const code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; @@ -16,7 +16,7 @@ for (let i = 0, len = code.length; i < len; i += 1) { revLookup['-'.charCodeAt(0)] = 62; revLookup['_'.charCodeAt(0)] = 63; -const getLens = b64 => { +const getLens = (b64: string | string[]) => { const len = b64.length; // We're encoding some strings not multiple of 4, so, disable this check @@ -37,16 +37,17 @@ const getLens = b64 => { }; // base64 is 4/3 + up to two characters of the original data -export const byteLength = b64 => { +export const byteLength = (b64: string) => { const lens = getLens(b64); const validLen = lens[0]; const placeHoldersLen = lens[1]; return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen; }; -const _byteLength = (b64, validLen, placeHoldersLen) => ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen; +const _byteLength = (b64: any, validLen: number, placeHoldersLen: number) => + ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen; -export const toByteArray = b64 => { +export const toByteArray = (b64: string) => { let tmp; const lens = getLens(b64); const validLen = lens[0]; @@ -92,10 +93,10 @@ export const toByteArray = b64 => { return arr; }; -const tripletToBase64 = num => +const tripletToBase64 = (num: number) => lookup[(num >> 18) & 0x3f] + lookup[(num >> 12) & 0x3f] + lookup[(num >> 6) & 0x3f] + lookup[num & 0x3f]; -const encodeChunk = (uint8, start, end) => { +const encodeChunk = (uint8: number[] | Uint8Array, start: number, end: number) => { let tmp; const output = []; for (let i = start; i < end; i += 3) { @@ -105,7 +106,7 @@ const encodeChunk = (uint8, start, end) => { return output.join(''); }; -export const fromByteArray = uint8 => { +export const fromByteArray = (uint8: number[] | Uint8Array) => { let tmp; const len = uint8.length; const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes diff --git a/app/utils/shortnameToUnicode/ascii.js b/app/utils/shortnameToUnicode/ascii.ts similarity index 98% rename from app/utils/shortnameToUnicode/ascii.js rename to app/utils/shortnameToUnicode/ascii.ts index 4d9d04cd3ae..7eca5f7df94 100644 --- a/app/utils/shortnameToUnicode/ascii.js +++ b/app/utils/shortnameToUnicode/ascii.ts @@ -3,7 +3,7 @@ /* eslint-disable object-curly-spacing */ /* eslint-disable comma-spacing */ /* eslint-disable key-spacing */ -const ascii = { +const ascii: { [key: string]: string } = { '*\\0/*': '🙆', '*\\O/*': '🙆', '-___-': '😑', diff --git a/app/utils/shortnameToUnicode/emojis.js b/app/utils/shortnameToUnicode/emojis.ts similarity index 99% rename from app/utils/shortnameToUnicode/emojis.js rename to app/utils/shortnameToUnicode/emojis.ts index 14cd61337c0..6a8a63c3ab9 100644 --- a/app/utils/shortnameToUnicode/emojis.js +++ b/app/utils/shortnameToUnicode/emojis.ts @@ -3,7 +3,7 @@ /* eslint-disable object-curly-spacing */ /* eslint-disable comma-spacing */ /* eslint-disable key-spacing */ -const emojis = { +const emojis: { [key: string]: string } = { ':england:': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', ':scotland:': '🏴󠁧󠁢󠁳󠁣󠁴󠁿', ':wales:': '🏴󠁧󠁢󠁷󠁬󠁳󠁿', diff --git a/app/utils/shortnameToUnicode/index.js b/app/utils/shortnameToUnicode/index.ts similarity index 80% rename from app/utils/shortnameToUnicode/index.js rename to app/utils/shortnameToUnicode/index.ts index 0a54aa3a309..b533da8ffe6 100644 --- a/app/utils/shortnameToUnicode/index.js +++ b/app/utils/shortnameToUnicode/index.ts @@ -2,11 +2,11 @@ import emojis from './emojis'; import ascii, { asciiRegexp } from './ascii'; const shortnamePattern = new RegExp(/:[-+_a-z0-9]+:/, 'gi'); -const replaceShortNameWithUnicode = shortname => emojis[shortname] || shortname; +const replaceShortNameWithUnicode = (shortname: string) => emojis[shortname] || shortname; const regAscii = new RegExp(`((\\s|^)${asciiRegexp}(?=\\s|$|[!,.?]))`, 'gi'); -const unescapeHTML = string => { - const unescaped = { +const unescapeHTML = (string: string) => { + const unescaped: { [key: string]: string } = { '&': '&', '&': '&', '&': '&', @@ -27,7 +27,7 @@ const unescapeHTML = string => { return string.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/gi, match => unescaped[match]); }; -const shortnameToUnicode = str => { +const shortnameToUnicode = (str: string): string => { str = str.replace(shortnamePattern, replaceShortNameWithUnicode); str = str.replace(regAscii, (entire, m1, m2, m3) => { From e35d883fd6efd4ff6358e21b7a6d0f13f6409319 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 21:42:23 -0300 Subject: [PATCH 11/28] log folder --- app/utils/log/{events.js => events.ts} | 0 app/utils/log/{index.js => index.ts} | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) rename app/utils/log/{events.js => events.ts} (100%) rename app/utils/log/{index.js => index.ts} (66%) diff --git a/app/utils/log/events.js b/app/utils/log/events.ts similarity index 100% rename from app/utils/log/events.js rename to app/utils/log/events.ts diff --git a/app/utils/log/index.js b/app/utils/log/index.ts similarity index 66% rename from app/utils/log/index.js rename to app/utils/log/index.ts index 41074832f18..9f0e0b2249e 100644 --- a/app/utils/log/index.js +++ b/app/utils/log/index.ts @@ -4,13 +4,13 @@ import { isFDroidBuild } from '../../constants/environment'; import events from './events'; const analytics = firebaseAnalytics || ''; -let bugsnag = ''; -let crashlytics; +let bugsnag: any = ''; +let crashlytics: any; let reportCrashErrors = true; let reportAnalyticsEvents = true; -export const getReportCrashErrorsValue = () => reportCrashErrors; -export const getReportAnalyticsEventsValue = () => reportAnalyticsEvents; +export const getReportCrashErrorsValue = (): boolean => reportCrashErrors; +export const getReportAnalyticsEventsValue = (): boolean => reportAnalyticsEvents; if (!isFDroidBuild) { bugsnag = require('@bugsnag/react-native').default; @@ -18,7 +18,7 @@ if (!isFDroidBuild) { onBreadcrumb() { return reportAnalyticsEvents; }, - onError(error) { + onError(error: { breadcrumbs: string[] }) { if (!reportAnalyticsEvents) { error.breadcrumbs = []; } @@ -34,13 +34,13 @@ export { events }; let metadata = {}; -export const logServerVersion = serverVersion => { +export const logServerVersion = (serverVersion: string): void => { metadata = { serverVersion }; }; -export const logEvent = (eventName, payload) => { +export const logEvent = (eventName: string, payload: { [key: string]: any }): void => { try { if (!isFDroidBuild) { analytics().logEvent(eventName, payload); @@ -51,26 +51,26 @@ export const logEvent = (eventName, payload) => { } }; -export const setCurrentScreen = currentScreen => { +export const setCurrentScreen = (currentScreen: string): void => { if (!isFDroidBuild) { analytics().setCurrentScreen(currentScreen); bugsnag.leaveBreadcrumb(currentScreen, { type: 'navigation' }); } }; -export const toggleCrashErrorsReport = value => { +export const toggleCrashErrorsReport = (value: boolean): boolean => { crashlytics().setCrashlyticsCollectionEnabled(value); return (reportCrashErrors = value); }; -export const toggleAnalyticsEventsReport = value => { +export const toggleAnalyticsEventsReport = (value: boolean): boolean => { analytics().setAnalyticsCollectionEnabled(value); return (reportAnalyticsEvents = value); }; -export default e => { +export default (e: { message: string }): void => { if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) { - bugsnag.notify(e, event => { + bugsnag.notify(e, (event: { addMetadata: (arg0: string, arg1: {}) => void }) => { event.addMetadata('details', { ...metadata }); }); if (!isFDroidBuild) { From 67858dfbecfc731986766b4423b3e0efb61fbedd Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 21:52:42 -0300 Subject: [PATCH 12/28] fileUpload folder --- .../{index.android.js => index.android.ts} | 4 +++- .../fileUpload/{index.ios.js => index.ios.ts} | 21 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) rename app/utils/fileUpload/{index.android.js => index.android.ts} (69%) rename app/utils/fileUpload/{index.ios.js => index.ios.ts} (64%) diff --git a/app/utils/fileUpload/index.android.js b/app/utils/fileUpload/index.android.ts similarity index 69% rename from app/utils/fileUpload/index.android.js rename to app/utils/fileUpload/index.android.ts index 5c45c27bd31..cb0edf2bd84 100644 --- a/app/utils/fileUpload/index.android.js +++ b/app/utils/fileUpload/index.android.ts @@ -1,7 +1,9 @@ import RNFetchBlob from 'rn-fetch-blob'; +type Methods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put'; + class FileUpload { - fetch = (method, url, headers, data) => { + fetch = (method: Methods, url: string, headers: { [key: string]: string }, data: any[]) => { const formData = data.map(item => { if (item.uri) { return { diff --git a/app/utils/fileUpload/index.ios.js b/app/utils/fileUpload/index.ios.ts similarity index 64% rename from app/utils/fileUpload/index.ios.js rename to app/utils/fileUpload/index.ios.ts index a97640553cb..c1024659132 100644 --- a/app/utils/fileUpload/index.ios.js +++ b/app/utils/fileUpload/index.ios.ts @@ -1,19 +1,23 @@ class Upload { + xhr: XMLHttpRequest; + + formData: FormData; + constructor() { this.xhr = new XMLHttpRequest(); this.formData = new FormData(); } - then = callback => { + then = (callback: (arg0: { respInfo: XMLHttpRequest }) => any) => { this.xhr.onload = () => callback({ respInfo: this.xhr }); this.xhr.send(this.formData); }; - catch = callback => { + catch = (callback: ((this: XMLHttpRequest, ev: ProgressEvent) => any) | null) => { this.xhr.onerror = callback; }; - uploadProgress = callback => { + uploadProgress = (callback: (arg0: number, arg1: number) => any) => { this.xhr.upload.onprogress = ({ total, loaded }) => callback(loaded, total); }; @@ -23,8 +27,16 @@ class Upload { }; } +interface IData { + name: string; + uri?: string; + type: string; + filename: string; + data: any; +} + class FileUpload { - fetch = (method, url, headers, data) => { + fetch = (method: string, url: string, headers: { [x: string]: string }, data: IData[]) => { const upload = new Upload(); upload.xhr.open(method, url); @@ -35,6 +47,7 @@ class FileUpload { data.forEach(item => { if (item.uri) { upload.formData.append(item.name, { + // @ts-ignore uri: item.uri, type: item.type, name: item.filename From f8b992f6271963dbe47de8c5ccf884fc9202a81e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 22:21:58 -0300 Subject: [PATCH 13/28] eslint disable at sendFileMessage --- app/lib/methods/sendFileMessage.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/lib/methods/sendFileMessage.js b/app/lib/methods/sendFileMessage.js index 35d2815ca26..9699965a55f 100644 --- a/app/lib/methods/sendFileMessage.js +++ b/app/lib/methods/sendFileMessage.js @@ -1,6 +1,7 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; +// eslint-disable-next-line import/extensions, import/no-unresolved import FileUpload from '../../utils/fileUpload'; import database from '../database'; import log from '../../utils/log'; From ca64f94ea9b0b1c80d43dd1ae6d9f55272dd325e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 22:25:35 -0300 Subject: [PATCH 14/28] fix log lint's errors --- app/utils/log/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/utils/log/index.ts b/app/utils/log/index.ts index 9f0e0b2249e..d52bd0e94da 100644 --- a/app/utils/log/index.ts +++ b/app/utils/log/index.ts @@ -40,7 +40,7 @@ export const logServerVersion = (serverVersion: string): void => { }; }; -export const logEvent = (eventName: string, payload: { [key: string]: any }): void => { +export const logEvent = (eventName: string, payload?: { [key: string]: any }): void => { try { if (!isFDroidBuild) { analytics().logEvent(eventName, payload); @@ -68,7 +68,7 @@ export const toggleAnalyticsEventsReport = (value: boolean): boolean => { return (reportAnalyticsEvents = value); }; -export default (e: { message: string }): void => { +export default (e: any): void => { if (e instanceof Error && bugsnag && e.message !== 'Aborted' && !__DEV__) { bugsnag.notify(e, (event: { addMetadata: (arg0: string, arg1: {}) => void }) => { event.addMetadata('details', { ...metadata }); From ad9247224d366dbc59bb50ddcae30277e70e6828 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 8 Dec 2021 22:26:14 -0300 Subject: [PATCH 15/28] animation e conditional from navigation folder --- .../navigation/{animations.js => animations.ts} | 14 ++++++++------ .../navigation/{conditional.js => conditional.ts} | 6 +++++- 2 files changed, 13 insertions(+), 7 deletions(-) rename app/utils/navigation/{animations.js => animations.ts} (71%) rename app/utils/navigation/{conditional.js => conditional.ts} (87%) diff --git a/app/utils/navigation/animations.js b/app/utils/navigation/animations.ts similarity index 71% rename from app/utils/navigation/animations.js rename to app/utils/navigation/animations.ts index 9f99764c4fc..a9f18408812 100644 --- a/app/utils/navigation/animations.js +++ b/app/utils/navigation/animations.ts @@ -1,12 +1,14 @@ import { Animated, Easing } from 'react-native'; -import { HeaderStyleInterpolators, TransitionPresets } from '@react-navigation/stack'; +import { HeaderStyleInterpolators, TransitionPreset, TransitionPresets } from '@react-navigation/stack'; +// eslint-disable-next-line import/no-unresolved +import { StackCardStyleInterpolator, TransitionSpec } from '@react-navigation/stack/lib/typescript/src/types'; import { isAndroid } from '../deviceInfo'; import conditional from './conditional'; const { multiply } = Animated; -const forFadeFromCenter = ({ current, closing }) => { +const forFadeFromCenter: StackCardStyleInterpolator = ({ current, closing }) => { const opacity = conditional( closing, current.progress, @@ -23,7 +25,7 @@ const forFadeFromCenter = ({ current, closing }) => { }; }; -const FadeIn = { +const FadeIn: TransitionSpec = { animation: 'timing', config: { duration: 250, @@ -31,7 +33,7 @@ const FadeIn = { } }; -const FadeOut = { +const FadeOut: TransitionSpec = { animation: 'timing', config: { duration: 150, @@ -48,7 +50,7 @@ export const FadeFromCenterModal = { cardStyleInterpolator: forFadeFromCenter }; -const forStackAndroid = ({ current, inverted, layouts: { screen } }) => { +const forStackAndroid: StackCardStyleInterpolator = ({ current, inverted, layouts: { screen } }) => { const translateX = multiply( current.progress.interpolate({ inputRange: [0, 1], @@ -70,7 +72,7 @@ const forStackAndroid = ({ current, inverted, layouts: { screen } }) => { }; }; -const StackAndroid = { +const StackAndroid: TransitionPreset = { gestureDirection: 'horizontal', transitionSpec: { open: FadeIn, diff --git a/app/utils/navigation/conditional.js b/app/utils/navigation/conditional.ts similarity index 87% rename from app/utils/navigation/conditional.js rename to app/utils/navigation/conditional.ts index 015c52ae1b7..84c76d83ad4 100644 --- a/app/utils/navigation/conditional.js +++ b/app/utils/navigation/conditional.ts @@ -10,7 +10,11 @@ const { add, multiply } = Animated; * @param main Animated Node to use if the condition is `true` * @param fallback Animated Node to use if the condition is `false` */ -export default function conditional(condition, main, fallback) { +export default function conditional( + condition: Animated.AnimatedInterpolation, + main: Animated.Animated, + fallback: Animated.Animated +): Animated.AnimatedAddition { // To implement this behavior, we multiply the main node with the condition. // So if condition is 0, result will be 0, and if condition is 1, result will be main node. // Then we multiple reverse of the condition (0 if condition is 1) with the fallback. From 905de04d6b93ca287ec18ac46982513f3b1a2a3f Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 9 Dec 2021 14:24:08 -0300 Subject: [PATCH 16/28] make ts happy on actionsheet folder --- app/containers/ActionSheet/Button.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/containers/ActionSheet/Button.ts b/app/containers/ActionSheet/Button.ts index 5deb0f692d2..186cc68519b 100644 --- a/app/containers/ActionSheet/Button.ts +++ b/app/containers/ActionSheet/Button.ts @@ -1,7 +1,8 @@ +import React from 'react'; import { TouchableOpacity } from 'react-native'; import { isAndroid } from '../../utils/deviceInfo'; import Touch from '../../utils/touch'; // Taken from https://github.com/rgommezz/react-native-scroll-bottom-sheet#touchables -export const Button = isAndroid ? Touch : TouchableOpacity; +export const Button: typeof React.Component = isAndroid ? Touch : TouchableOpacity; From 039a203286b980fe287e5b862c66ff2fdd377f18 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 9 Dec 2021 15:13:26 -0300 Subject: [PATCH 17/28] minor tweaks --- app/share.tsx | 5 +++-- app/utils/events.ts | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/share.tsx b/app/share.tsx index 63db1fdad78..4902d9d1ae7 100644 --- a/app/share.tsx +++ b/app/share.tsx @@ -14,6 +14,7 @@ import { defaultHeader, getActiveRouteName, navigationTheme, themedHeader } from import RocketChat, { THEME_PREFERENCES_KEY } from './lib/rocketchat'; import { ThemeContext } from './theme'; import { localAuthenticate } from './utils/localAuthentication'; +import { IThemePreference } from './definitions/ITheme'; import ScreenLockedView from './views/ScreenLockedView'; // Outside Stack import WithoutServersView from './views/WithoutServersView'; @@ -132,10 +133,10 @@ class Root extends React.Component<{}, IState> { setCurrentScreen(currentRouteName); }; - setTheme = (newTheme: any = {}) => { + setTheme = (newTheme = {}) => { // change theme state this.setState( - prevState => newThemeState(prevState, newTheme), + prevState => newThemeState(prevState, newTheme as IThemePreference), () => { const { themePreferences } = this.state; // subscribe to Appearance changes diff --git a/app/utils/events.ts b/app/utils/events.ts index 10857dedd89..60ec722a20f 100644 --- a/app/utils/events.ts +++ b/app/utils/events.ts @@ -2,6 +2,7 @@ import log from './log'; class EventEmitter { private events: { [key: string]: any }; + constructor() { this.events = {}; } From 690b500a6af15ddd176f497a805f4d2326616904 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Fri, 10 Dec 2021 14:35:24 -0300 Subject: [PATCH 18/28] minor tweak --- app/utils/avatar.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/utils/avatar.ts b/app/utils/avatar.ts index 13a7ed1cbf5..219700cb9e0 100644 --- a/app/utils/avatar.ts +++ b/app/utils/avatar.ts @@ -7,7 +7,7 @@ interface IAvatarURL { type: string; text: string; size?: number; - user: { id: string; token: string }; + user: { id?: string; token?: string }; avatar?: string; server: string; avatarETag: string; @@ -20,7 +20,7 @@ export const avatarURL = ({ type, text, size = 25, - user, + user = {}, avatar, server, avatarETag, From 29ad0cf76e5837c1d7f350965ecf5e7f2cd2e077 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 23 Dec 2021 15:33:21 -0300 Subject: [PATCH 19/28] minor tweak --- app/definitions/IAttachment.ts | 15 +++++++++++++++ app/utils/base64-js/index.ts | 6 +++--- app/utils/fileUpload/index.android.ts | 6 ++++-- app/utils/fileUpload/index.ios.ts | 12 +++--------- app/utils/fileUpload/interfaces.ts | 7 +++++++ 5 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 app/utils/fileUpload/interfaces.ts diff --git a/app/definitions/IAttachment.ts b/app/definitions/IAttachment.ts index 168106177ff..4ff3aa8df31 100644 --- a/app/definitions/IAttachment.ts +++ b/app/definitions/IAttachment.ts @@ -1,4 +1,5 @@ export interface IAttachment { + ts: Date; title: string; type: string; description: string; @@ -7,4 +8,18 @@ export interface IAttachment { image_type?: string; video_url?: string; video_type?: string; + title_link_download?: boolean; + fields?: IAttachment[]; + image_dimensions?: { width?: number; height?: number }; + image_preview?: string; + image_size?: number; + author_name?: string; + author_icon?: string; + message_link?: string; + text?: string; + short?: boolean; + value?: string; + author_link?: string; + color?: string; + thumb_url?: string; } diff --git a/app/utils/base64-js/index.ts b/app/utils/base64-js/index.ts index 6d2936bc61b..71fac91ce72 100644 --- a/app/utils/base64-js/index.ts +++ b/app/utils/base64-js/index.ts @@ -1,7 +1,7 @@ /* eslint-disable no-bitwise */ // https://github.com/beatgammit/base64-js/blob/master/index.js -const lookup: any[] = []; +const lookup: string[] = []; const revLookup: number[] = []; const Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; @@ -16,7 +16,7 @@ for (let i = 0, len = code.length; i < len; i += 1) { revLookup['-'.charCodeAt(0)] = 62; revLookup['_'.charCodeAt(0)] = 63; -const getLens = (b64: string | string[]) => { +const getLens = (b64: string) => { const len = b64.length; // We're encoding some strings not multiple of 4, so, disable this check @@ -44,7 +44,7 @@ export const byteLength = (b64: string) => { return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen; }; -const _byteLength = (b64: any, validLen: number, placeHoldersLen: number) => +const _byteLength = (b64: string, validLen: number, placeHoldersLen: number) => ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen; export const toByteArray = (b64: string) => { diff --git a/app/utils/fileUpload/index.android.ts b/app/utils/fileUpload/index.android.ts index cb0edf2bd84..a37754062b5 100644 --- a/app/utils/fileUpload/index.android.ts +++ b/app/utils/fileUpload/index.android.ts @@ -1,9 +1,11 @@ import RNFetchBlob from 'rn-fetch-blob'; -type Methods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put'; +import { IFile } from './interfaces'; + +type TMethods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put'; class FileUpload { - fetch = (method: Methods, url: string, headers: { [key: string]: string }, data: any[]) => { + fetch = (method: TMethods, url: string, headers: { [key: string]: string }, data: IFile[]) => { const formData = data.map(item => { if (item.uri) { return { diff --git a/app/utils/fileUpload/index.ios.ts b/app/utils/fileUpload/index.ios.ts index c1024659132..2c9703f3836 100644 --- a/app/utils/fileUpload/index.ios.ts +++ b/app/utils/fileUpload/index.ios.ts @@ -1,3 +1,5 @@ +import { IFile } from './interfaces'; + class Upload { xhr: XMLHttpRequest; @@ -27,16 +29,8 @@ class Upload { }; } -interface IData { - name: string; - uri?: string; - type: string; - filename: string; - data: any; -} - class FileUpload { - fetch = (method: string, url: string, headers: { [x: string]: string }, data: IData[]) => { + fetch = (method: string, url: string, headers: { [x: string]: string }, data: IFile[]) => { const upload = new Upload(); upload.xhr.open(method, url); diff --git a/app/utils/fileUpload/interfaces.ts b/app/utils/fileUpload/interfaces.ts new file mode 100644 index 00000000000..6824f3b682f --- /dev/null +++ b/app/utils/fileUpload/interfaces.ts @@ -0,0 +1,7 @@ +export interface IFile { + name: string; + uri?: string; + type: string; + filename: string; + data: any; +} From 32f6498eef32d87b81e42088be3c4ca8a9bd4471 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 23 Dec 2021 17:56:48 -0300 Subject: [PATCH 20/28] tweaks --- app/containers/Avatar/Avatar.tsx | 12 +++--- app/containers/Avatar/index.tsx | 8 ++-- app/containers/Avatar/interfaces.ts | 40 +++++++++---------- app/containers/message/Reply.tsx | 28 +++---------- app/containers/message/Video.tsx | 10 +---- app/definitions/ITheme.ts | 4 +- app/index.tsx | 5 +-- app/lib/methods/sendFileMessage.js | 1 - app/share.tsx | 5 +-- app/theme.tsx | 7 ++-- app/utils/avatar.ts | 16 +------- app/utils/fileUpload/index.ios.ts | 8 ++-- .../fileUpload/{index.android.ts => index.ts} | 0 app/utils/isReadOnly.ts | 2 +- app/utils/openLink.ts | 2 +- app/utils/review.ts | 2 +- app/utils/room.ts | 12 +++--- app/utils/theme.ts | 6 +-- app/utils/twoFactor.ts | 9 ++--- 19 files changed, 69 insertions(+), 108 deletions(-) rename app/utils/fileUpload/{index.android.ts => index.ts} (100%) diff --git a/app/containers/Avatar/Avatar.tsx b/app/containers/Avatar/Avatar.tsx index da4cfd24047..a58e8650b28 100644 --- a/app/containers/Avatar/Avatar.tsx +++ b/app/containers/Avatar/Avatar.tsx @@ -29,7 +29,7 @@ const Avatar = React.memo( size = 25, borderRadius = 4, type = RoomType.DIRECT - }: Partial) => { + }: IAvatar) => { if ((!text && !avatar && !emoji && !rid) || !server) { return null; } @@ -57,15 +57,15 @@ const Avatar = React.memo( if (!isStatic) { uri = avatarURL({ type, - text: text!, + text, size, - user: user!, + user, avatar, server, - avatarETag: avatarETag!, - serverVersion: serverVersion!, + avatarETag, + serverVersion, rid, - blockUnauthenticatedAccess: blockUnauthenticatedAccess! + blockUnauthenticatedAccess }); } diff --git a/app/containers/Avatar/index.tsx b/app/containers/Avatar/index.tsx index 9c95db83902..196ced9534b 100644 --- a/app/containers/Avatar/index.tsx +++ b/app/containers/Avatar/index.tsx @@ -7,17 +7,17 @@ import { getUserSelector } from '../../selectors/login'; import Avatar from './Avatar'; import { IAvatar } from './interfaces'; -class AvatarContainer extends React.Component, any> { +class AvatarContainer extends React.Component { private mounted: boolean; - private subscription!: any; + private subscription: any; static defaultProps = { text: '', type: 'd' }; - constructor(props: Partial) { + constructor(props: IAvatar) { super(props); this.mounted = false; this.state = { avatarETag: '' }; @@ -82,7 +82,7 @@ class AvatarContainer extends React.Component, any> { render() { const { avatarETag } = this.state; const { serverVersion } = this.props; - return ; + return ; } } diff --git a/app/containers/Avatar/interfaces.ts b/app/containers/Avatar/interfaces.ts index ed7fd3b9ebf..21255c24ae0 100644 --- a/app/containers/Avatar/interfaces.ts +++ b/app/containers/Avatar/interfaces.ts @@ -1,23 +1,23 @@ export interface IAvatar { - server: string; - style: any; - text: string; - avatar: string; - emoji: string; - size: number; - borderRadius: number; - type: string; - children: JSX.Element; - user: { - id: string; - token: string; + server?: string; + style?: any; + text?: string; + avatar?: string; + emoji?: string; + size?: number; + borderRadius?: number; + type?: string; + children?: JSX.Element; + user?: { + id?: string; + token?: string; }; - theme: string; - onPress(): void; - getCustomEmoji(): any; - avatarETag: string; - isStatic: boolean | string; - rid: string; - blockUnauthenticatedAccess: boolean; - serverVersion: string; + theme?: string; + onPress?: () => void; + getCustomEmoji?: () => any; + avatarETag?: string; + isStatic?: boolean | string; + rid?: string; + blockUnauthenticatedAccess?: boolean; + serverVersion?: string; } diff --git a/app/containers/message/Reply.tsx b/app/containers/message/Reply.tsx index fbc8984fcb9..540ec64a640 100644 --- a/app/containers/message/Reply.tsx +++ b/app/containers/message/Reply.tsx @@ -13,6 +13,7 @@ import { themes } from '../../constants/colors'; import MessageContext from './Context'; import { fileDownloadAndPreview } from '../../utils/fileDownload'; import { formatAttachmentUrl } from '../../lib/utils'; +import { IAttachment } from '../../definitions/IAttachment'; import RCActivityIndicator from '../ActivityIndicator'; const styles = StyleSheet.create({ @@ -90,43 +91,26 @@ const styles = StyleSheet.create({ } }); -interface IMessageReplyAttachment { - author_name: string; - message_link: string; - ts: string; - text: string; - title: string; - short: boolean; - value: string; - title_link: string; - author_link: string; - type: string; - color: string; - description: string; - fields: IMessageReplyAttachment[]; - thumb_url: string; -} - interface IMessageTitle { - attachment: Partial; + attachment: Partial; timeFormat: string; theme: string; } interface IMessageDescription { - attachment: Partial; + attachment: Partial; getCustomEmoji: Function; theme: string; } interface IMessageFields { - attachment: Partial; + attachment: Partial; theme: string; getCustomEmoji: Function; } interface IMessageReply { - attachment: IMessageReplyAttachment; + attachment: IAttachment; timeFormat: string; index: number; theme: string; @@ -198,7 +182,7 @@ const Fields = React.memo( {field.title} {/* @ts-ignore*/} void; } diff --git a/app/utils/avatar.ts b/app/utils/avatar.ts index 219700cb9e0..20d374ddab0 100644 --- a/app/utils/avatar.ts +++ b/app/utils/avatar.ts @@ -1,21 +1,9 @@ import { compareServerVersion, methods } from '../lib/utils'; import { RoomType } from '../definitions/IRoom'; +import { IAvatar } from '../containers/Avatar/interfaces'; const formatUrl = (url: string, size: number, query: string) => `${url}?format=png&size=${size}${query}`; -interface IAvatarURL { - type: string; - text: string; - size?: number; - user: { id?: string; token?: string }; - avatar?: string; - server: string; - avatarETag: string; - rid?: string; - blockUnauthenticatedAccess: boolean; - serverVersion: string; -} - export const avatarURL = ({ type, text, @@ -27,7 +15,7 @@ export const avatarURL = ({ rid, blockUnauthenticatedAccess, serverVersion -}: IAvatarURL): string => { +}: IAvatar): string => { let room; if (type === RoomType.DIRECT) { room = text; diff --git a/app/utils/fileUpload/index.ios.ts b/app/utils/fileUpload/index.ios.ts index 2c9703f3836..4cd78e6eb7c 100644 --- a/app/utils/fileUpload/index.ios.ts +++ b/app/utils/fileUpload/index.ios.ts @@ -1,16 +1,16 @@ import { IFile } from './interfaces'; class Upload { - xhr: XMLHttpRequest; + public xhr: XMLHttpRequest; - formData: FormData; + public formData: FormData; constructor() { this.xhr = new XMLHttpRequest(); this.formData = new FormData(); } - then = (callback: (arg0: { respInfo: XMLHttpRequest }) => any) => { + then = (callback: (param: { respInfo: XMLHttpRequest }) => XMLHttpRequest) => { this.xhr.onload = () => callback({ respInfo: this.xhr }); this.xhr.send(this.formData); }; @@ -19,7 +19,7 @@ class Upload { this.xhr.onerror = callback; }; - uploadProgress = (callback: (arg0: number, arg1: number) => any) => { + uploadProgress = (callback: (param: number, arg1: number) => any) => { this.xhr.upload.onprogress = ({ total, loaded }) => callback(loaded, total); }; diff --git a/app/utils/fileUpload/index.android.ts b/app/utils/fileUpload/index.ts similarity index 100% rename from app/utils/fileUpload/index.android.ts rename to app/utils/fileUpload/index.ts diff --git a/app/utils/isReadOnly.ts b/app/utils/isReadOnly.ts index f9ec98523e6..a4777ee8282 100644 --- a/app/utils/isReadOnly.ts +++ b/app/utils/isReadOnly.ts @@ -9,7 +9,7 @@ const canPostReadOnly = async ({ rid }: { rid: string }) => { return permission[0]; }; -const isMuted = (room: IRoom, user: { username: any }) => +const isMuted = (room: IRoom, user: { username: string }) => room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username); export const isReadOnly = async (room: IRoom, user: { id?: string; username: string; token?: string }): Promise => { diff --git a/app/utils/openLink.ts b/app/utils/openLink.ts index f716519ae8f..4048b3add67 100644 --- a/app/utils/openLink.ts +++ b/app/utils/openLink.ts @@ -14,7 +14,7 @@ const scheme = { brave: 'brave:' }; -const appSchemeURL = (url: string, browser: string) => { +const appSchemeURL = (url: string, browser: string): string => { let schemeUrl = url; const parsedUrl = parse(url, true); const { protocol } = parsedUrl; diff --git a/app/utils/review.ts b/app/utils/review.ts index 326d40010ad..bbbb498bedc 100644 --- a/app/utils/review.ts +++ b/app/utils/review.ts @@ -15,7 +15,7 @@ const reviewDelay = 2000; const numberOfDays = 7; const numberOfPositiveEvent = 5; -const daysBetween = (date1: Date, date2: Date) => { +const daysBetween = (date1: Date, date2: Date): number => { const one_day = 1000 * 60 * 60 * 24; const date1_ms = date1.getTime(); const date2_ms = date2.getTime(); diff --git a/app/utils/room.ts b/app/utils/room.ts index 6520db65664..2625117745c 100644 --- a/app/utils/room.ts +++ b/app/utils/room.ts @@ -1,13 +1,14 @@ import moment from 'moment'; -import { IRoom } from '../definitions/IRoom'; +import { IRoom, RoomType } from '../definitions/IRoom'; import { themes } from '../constants/colors'; import I18n from '../i18n'; +import { IAttachment } from '../definitions/IAttachment'; export const isBlocked = (room: IRoom): boolean => { if (room) { const { t, blocked, blocker } = room; - if (t === 'd' && (blocked || blocker)) { + if (t === RoomType.DIRECT && (blocked || blocker)) { return true; } } @@ -42,10 +43,11 @@ export const getBadgeColor = ({ messageId, theme }: { + // TODO: Refactor when migrate model folder subscription: any; messageId: string; theme: string; -}): any => { +}): string | undefined => { if (subscription?.tunreadUser?.includes(messageId)) { return themes[theme].mentionMeColor; } @@ -57,7 +59,7 @@ export const getBadgeColor = ({ } }; -export const makeThreadName = (messageRecord: { id?: string | undefined; msg?: any; attachments?: any }): string => - messageRecord.msg || messageRecord?.attachments[0]?.title; +export const makeThreadName = (messageRecord: { id?: string; msg?: string; attachments?: IAttachment[] }): string | undefined => + messageRecord.msg || messageRecord.attachments![0].title; export const isTeamRoom = ({ teamId, joined }: { teamId: string; joined: boolean }): boolean => !!teamId && joined; diff --git a/app/utils/theme.ts b/app/utils/theme.ts index c94150198ad..0e9d8e05895 100644 --- a/app/utils/theme.ts +++ b/app/utils/theme.ts @@ -2,13 +2,13 @@ import { Appearance } from 'react-native-appearance'; import changeNavigationBarColor from 'react-native-navigation-bar-color'; import setRootViewColor from 'rn-root-view'; -import { IThemePreference } from '../definitions/ITheme'; +import { IThemePreference, TThemeMode } from '../definitions/ITheme'; import { themes } from '../constants/colors'; import { isAndroid } from './deviceInfo'; let themeListener: { remove: () => void } | null; -export const defaultTheme = (): string => { +export const defaultTheme = (): TThemeMode => { const systemTheme = Appearance.getColorScheme(); if (systemTheme && systemTheme !== 'no-preference') { return systemTheme; @@ -25,7 +25,7 @@ export const getTheme = (themePreferences: IThemePreference): string => { return theme === 'dark' ? darkLevel : 'light'; }; -export const newThemeState = (prevState: any, newTheme: IThemePreference) => { +export const newThemeState = (prevState: { themePreferences: IThemePreference }, newTheme: IThemePreference) => { // new theme preferences const themePreferences = { ...prevState.themePreferences, diff --git a/app/utils/twoFactor.ts b/app/utils/twoFactor.ts index d9a9ae50002..a52ff93fd25 100644 --- a/app/utils/twoFactor.ts +++ b/app/utils/twoFactor.ts @@ -3,13 +3,12 @@ import { settings } from '@rocket.chat/sdk'; import { TWO_FACTOR } from '../containers/TwoFactor'; import EventEmitter from './events'; -export const twoFactor = ({ - method, - invalid -}: { +interface ITwoFactor { method: string; invalid: boolean; -}): Promise<{ twoFactorCode: string; twoFactorMethod: string }> => +} + +export const twoFactor = ({ method, invalid }: ITwoFactor): Promise<{ twoFactorCode: string; twoFactorMethod: string }> => new Promise((resolve, reject) => { EventEmitter.emit(TWO_FACTOR, { method, From af186dfef96787b95e062701e4acd5f1e2d12520 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 23 Dec 2021 18:49:49 -0300 Subject: [PATCH 21/28] minor tweaks --- app/utils/events.ts | 6 +++--- app/utils/fetch.ts | 2 +- app/utils/goRoom.ts | 11 ++++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/utils/events.ts b/app/utils/events.ts index 60ec722a20f..3f87e3a79ff 100644 --- a/app/utils/events.ts +++ b/app/utils/events.ts @@ -7,7 +7,7 @@ class EventEmitter { this.events = {}; } - addEventListener(event: string, listener: any) { + addEventListener(event: string, listener: Function) { if (typeof this.events[event] !== 'object') { this.events[event] = []; } @@ -15,7 +15,7 @@ class EventEmitter { return listener; } - removeListener(event: string, listener: any) { + removeListener(event: string, listener: Function) { if (typeof this.events[event] === 'object') { const idx = this.events[event].indexOf(listener); if (idx > -1) { @@ -29,7 +29,7 @@ class EventEmitter { emit(event: string, ...args: any[]) { if (typeof this.events[event] === 'object') { - this.events[event].forEach((listener: any) => { + this.events[event].forEach((listener: Function) => { try { listener.apply(this, args); } catch (e) { diff --git a/app/utils/fetch.ts b/app/utils/fetch.ts index 5f257c7d972..9a4a2abfd14 100644 --- a/app/utils/fetch.ts +++ b/app/utils/fetch.ts @@ -29,7 +29,7 @@ export const BASIC_AUTH_KEY = 'BASIC_AUTH_KEY'; RocketChatSettings.customHeaders = headers; -export default (url: string, options: any = {}): Promise => { +export default (url: string, options: { headers?: Headers; signal?: AbortSignal } = {}): Promise => { let customOptions = { ...options, headers: RocketChatSettings.customHeaders }; if (options && options.headers) { customOptions = { ...customOptions, headers: { ...options.headers, ...customOptions.headers } }; diff --git a/app/utils/goRoom.ts b/app/utils/goRoom.ts index 36c46b85ab6..df903a925ce 100644 --- a/app/utils/goRoom.ts +++ b/app/utils/goRoom.ts @@ -1,8 +1,17 @@ +import { ChatsStackParamList } from '../stacks/types'; import { IRoom, RoomType } from '../definitions/IRoom'; import Navigation from '../lib/Navigation'; import RocketChat from '../lib/rocketchat'; -const navigate = ({ item, isMasterDetail, ...props }: { item: IItem; isMasterDetail: boolean; navigationMethod?: any }) => { +const navigate = ({ + item, + isMasterDetail, + ...props +}: { + item: IItem; + isMasterDetail: boolean; + navigationMethod?: () => ChatsStackParamList; +}) => { let navigationMethod = props.navigationMethod ?? Navigation.navigate; if (isMasterDetail) { From f6efc61cd5dc22831649a5ab6f7ce5bffbf9501e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Fri, 24 Dec 2021 16:01:38 -0300 Subject: [PATCH 22/28] minor tweak --- app/utils/fetch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/utils/fetch.ts b/app/utils/fetch.ts index 9a4a2abfd14..c8758da8b77 100644 --- a/app/utils/fetch.ts +++ b/app/utils/fetch.ts @@ -34,6 +34,7 @@ export default (url: string, options: { headers?: Headers; signal?: AbortSignal if (options && options.headers) { customOptions = { ...customOptions, headers: { ...options.headers, ...customOptions.headers } }; } + // TODO: Refactor when migrate rocketchat.js // @ts-ignore if (RocketChat.controller) { // @ts-ignore From 49536cb4864ee76a8f97a0aaf68c455915c7c439 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Fri, 24 Dec 2021 17:02:10 -0300 Subject: [PATCH 23/28] Event tweak --- app/definitions/ICommand.ts | 6 ++++++ app/index.tsx | 3 ++- app/utils/events.ts | 14 +++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 app/definitions/ICommand.ts diff --git a/app/definitions/ICommand.ts b/app/definitions/ICommand.ts new file mode 100644 index 00000000000..a0abeec265c --- /dev/null +++ b/app/definitions/ICommand.ts @@ -0,0 +1,6 @@ +export interface ICommand { + event: { + input: string; + modifierFlags: number; + }; +} diff --git a/app/index.tsx b/app/index.tsx index 94aeed3e41f..cc0a06a265e 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -31,6 +31,7 @@ import { ActionSheetProvider } from './containers/ActionSheet'; import debounce from './utils/debounce'; import { isFDroidBuild } from './constants/environment'; import { IThemePreference } from './definitions/ITheme'; +import { ICommand } from './definitions/ICommand'; RNScreens.enableScreens(); @@ -189,7 +190,7 @@ export default class Root extends React.Component<{}, IState> { initTablet = () => { const { width } = this.state; this.setMasterDetail(width); - this.onKeyCommands = KeyCommandsEmitter.addListener('onKeyCommand', (command: unknown) => { + this.onKeyCommands = KeyCommandsEmitter.addListener('onKeyCommand', (command: ICommand) => { EventEmitter.emit(KEY_COMMAND, { event: command }); }); }; diff --git a/app/utils/events.ts b/app/utils/events.ts index 3f87e3a79ff..fc0b975ad33 100644 --- a/app/utils/events.ts +++ b/app/utils/events.ts @@ -1,5 +1,17 @@ +import { ICommand } from '../definitions/ICommand'; import log from './log'; +type TEventEmitterEmmitArgs = + | { rid: string } + | { message: string } + | { method: string } + | { invalid: boolean } + | { force: boolean } + | { hasBiometry: boolean } + | { event: string | ICommand } + | { cancel: () => void } + | { submit: (param: string) => void }; + class EventEmitter { private events: { [key: string]: any }; @@ -27,7 +39,7 @@ class EventEmitter { } } - emit(event: string, ...args: any[]) { + emit(event: string, ...args: TEventEmitterEmmitArgs[]) { if (typeof this.events[event] === 'object') { this.events[event].forEach((listener: Function) => { try { From b9c544772c1e780d67b3557d9bb82f406ba3c39c Mon Sep 17 00:00:00 2001 From: AlexAlexandre Date: Tue, 28 Dec 2021 11:26:58 -0300 Subject: [PATCH 24/28] minor tweak --- app/containers/Avatar/index.tsx | 2 +- app/containers/Avatar/interfaces.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/containers/Avatar/index.tsx b/app/containers/Avatar/index.tsx index 196ced9534b..2ce066479ad 100644 --- a/app/containers/Avatar/index.tsx +++ b/app/containers/Avatar/index.tsx @@ -55,7 +55,7 @@ class AvatarContainer extends React.Component { try { if (this.isDirect) { const { text } = this.props; - const [user] = await usersCollection.query(Q.where('username', text!)).fetch(); + const [user] = await usersCollection.query(Q.where('username', text)).fetch(); record = user; } else { const { rid } = this.props; diff --git a/app/containers/Avatar/interfaces.ts b/app/containers/Avatar/interfaces.ts index 21255c24ae0..78152e522e6 100644 --- a/app/containers/Avatar/interfaces.ts +++ b/app/containers/Avatar/interfaces.ts @@ -1,7 +1,7 @@ export interface IAvatar { server?: string; style?: any; - text?: string; + text: string; avatar?: string; emoji?: string; size?: number; From de36f1ebc7bbb1c564dc36d8a17839a76095d88e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 28 Dec 2021 18:50:20 -0300 Subject: [PATCH 25/28] change some interface's name --- app/utils/fileUpload/index.ios.ts | 4 ++-- app/utils/fileUpload/index.ts | 4 ++-- app/utils/fileUpload/interfaces.ts | 2 +- app/views/ShareListView/index.tsx | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/utils/fileUpload/index.ios.ts b/app/utils/fileUpload/index.ios.ts index 4cd78e6eb7c..ae5cfabc228 100644 --- a/app/utils/fileUpload/index.ios.ts +++ b/app/utils/fileUpload/index.ios.ts @@ -1,4 +1,4 @@ -import { IFile } from './interfaces'; +import { IFileUpload } from './interfaces'; class Upload { public xhr: XMLHttpRequest; @@ -30,7 +30,7 @@ class Upload { } class FileUpload { - fetch = (method: string, url: string, headers: { [x: string]: string }, data: IFile[]) => { + fetch = (method: string, url: string, headers: { [x: string]: string }, data: IFileUpload[]) => { const upload = new Upload(); upload.xhr.open(method, url); diff --git a/app/utils/fileUpload/index.ts b/app/utils/fileUpload/index.ts index a37754062b5..1d2bdb31281 100644 --- a/app/utils/fileUpload/index.ts +++ b/app/utils/fileUpload/index.ts @@ -1,11 +1,11 @@ import RNFetchBlob from 'rn-fetch-blob'; -import { IFile } from './interfaces'; +import { IFileUpload } from './interfaces'; type TMethods = 'POST' | 'GET' | 'DELETE' | 'PUT' | 'post' | 'get' | 'delete' | 'put'; class FileUpload { - fetch = (method: TMethods, url: string, headers: { [key: string]: string }, data: IFile[]) => { + fetch = (method: TMethods, url: string, headers: { [key: string]: string }, data: IFileUpload[]) => { const formData = data.map(item => { if (item.uri) { return { diff --git a/app/utils/fileUpload/interfaces.ts b/app/utils/fileUpload/interfaces.ts index 6824f3b682f..a3002f72703 100644 --- a/app/utils/fileUpload/interfaces.ts +++ b/app/utils/fileUpload/interfaces.ts @@ -1,4 +1,4 @@ -export interface IFile { +export interface IFileUpload { name: string; uri?: string; type: string; diff --git a/app/views/ShareListView/index.tsx b/app/views/ShareListView/index.tsx index 1c9f0e415d6..e4294c60008 100644 --- a/app/views/ShareListView/index.tsx +++ b/app/views/ShareListView/index.tsx @@ -25,12 +25,12 @@ import { sanitizeLikeString } from '../../lib/database/utils'; import styles from './styles'; import ShareListHeader from './Header'; -interface IFile { +interface IDataFromShare { value: string; type: string; } -interface IAttachment { +interface IFileToShare { filename: string; description: string; size: number; @@ -61,7 +61,7 @@ interface IState { searchResults: IChat[]; chats: IChat[]; serversCount: number; - attachments: IAttachment[]; + attachments: IFileToShare[]; text: string; loading: boolean; serverInfo: IServerInfo; @@ -121,7 +121,7 @@ class ShareListView extends React.Component { async componentDidMount() { const { server } = this.props; try { - const data = (await ShareExtension.data()) as IFile[]; + const data = (await ShareExtension.data()) as IDataFromShare[]; if (isAndroid) { await this.askForPermission(data); } @@ -136,7 +136,7 @@ class ShareListView extends React.Component { size: file.size, mime: mime.lookup(file.uri), path: file.uri - })) as IAttachment[]; + })) as IFileToShare[]; const text = data.filter(item => item.type === 'text').reduce((acc, item) => `${item.value}\n${acc}`, ''); this.setState({ text, @@ -294,7 +294,7 @@ class ShareListView extends React.Component { } }; - askForPermission = async (data: IFile[]) => { + askForPermission = async (data: IDataFromShare[]) => { const mediaIndex = data.findIndex(item => item.type === 'media'); if (mediaIndex !== -1) { const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, permission); From e22051251ef763e5f5eb2eeeb612e664bc04da7e Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 28 Dec 2021 19:16:44 -0300 Subject: [PATCH 26/28] theme preferences --- app/definitions/ITheme.ts | 4 +++- app/views/ThemeView.tsx | 20 ++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/definitions/ITheme.ts b/app/definitions/ITheme.ts index a050947bf9f..208a0b2d2ed 100644 --- a/app/definitions/ITheme.ts +++ b/app/definitions/ITheme.ts @@ -1,6 +1,8 @@ export type TThemeMode = 'automatic' | 'light' | 'dark'; +export type TDarkLevel = 'black' | 'dark'; + export interface IThemePreference { currentTheme: TThemeMode; - darkLevel: string; + darkLevel: TDarkLevel; } diff --git a/app/views/ThemeView.tsx b/app/views/ThemeView.tsx index 8ab9010c474..636dec4876d 100644 --- a/app/views/ThemeView.tsx +++ b/app/views/ThemeView.tsx @@ -11,17 +11,18 @@ import { supportSystemTheme } from '../utils/deviceInfo'; import SafeAreaView from '../containers/SafeAreaView'; import UserPreferences from '../lib/userPreferences'; import { events, logEvent } from '../utils/log'; +import { IThemePreference, TThemeMode, TDarkLevel } from '../definitions/ITheme'; const THEME_GROUP = 'THEME_GROUP'; const DARK_GROUP = 'DARK_GROUP'; -const SYSTEM_THEME = { +const SYSTEM_THEME: ITheme = { label: 'Automatic', value: 'automatic', group: THEME_GROUP }; -const THEMES = [ +const THEMES: ITheme[] = [ { label: 'Light', value: 'light', @@ -53,15 +54,10 @@ const darkGroup = THEMES.filter(item => item.group === DARK_GROUP); interface ITheme { label: string; - value: string; + value: TThemeMode | TDarkLevel; group: string; } -interface IThemePreference { - currentTheme?: string; - darkLevel?: string; -} - interface IThemeViewProps { theme: string; themePreferences: IThemePreference; @@ -89,19 +85,19 @@ class ThemeView extends React.Component { const { themePreferences } = this.props; const { darkLevel, currentTheme } = themePreferences; const { value, group } = item; - let changes: IThemePreference = {}; + let changes: Partial = {}; if (group === THEME_GROUP && currentTheme !== value) { logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value }); - changes = { currentTheme: value }; + changes = { currentTheme: value as TThemeMode }; } if (group === DARK_GROUP && darkLevel !== value) { logEvent(events.THEME_SET_DARK_LEVEL, { dark_level: value }); - changes = { darkLevel: value }; + changes = { darkLevel: value as TDarkLevel }; } this.setTheme(changes); }; - setTheme = async (theme: IThemePreference) => { + setTheme = async (theme: Partial) => { const { setTheme, themePreferences } = this.props; const newTheme = { ...themePreferences, ...theme }; setTheme(newTheme); From d68f55abc5d10f01c0ee3deb720afcf73a097f61 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 28 Dec 2021 19:40:19 -0300 Subject: [PATCH 27/28] refactor tservermodel --- app/definitions/IServer.ts | 2 +- app/utils/localAuthentication.ts | 14 +++++++------- app/views/ScreenLockConfigView.tsx | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/definitions/IServer.ts b/app/definitions/IServer.ts index 4e21bef8e41..0c3bf57d3b7 100644 --- a/app/definitions/IServer.ts +++ b/app/definitions/IServer.ts @@ -17,4 +17,4 @@ export interface IServer { E2E_Enable: boolean; } -export interface IServerRecord extends IServer, Model {} +export type TServerModel = IServer & Model; diff --git a/app/utils/localAuthentication.ts b/app/utils/localAuthentication.ts index 89c1d602fa5..f4359963330 100644 --- a/app/utils/localAuthentication.ts +++ b/app/utils/localAuthentication.ts @@ -16,17 +16,17 @@ import { } from '../constants/localAuthentication'; import I18n from '../i18n'; import { setLocalAuthenticated } from '../actions/login'; -import { IServerRecord } from '../definitions/IServer'; +import { TServerModel } from '../definitions/IServer'; import EventEmitter from './events'; import { isIOS } from './deviceInfo'; -export const saveLastLocalAuthenticationSession = async (server: string, serverRecord?: IServerRecord): Promise => { +export const saveLastLocalAuthenticationSession = async (server: string, serverRecord?: TServerModel): Promise => { const serversDB = database.servers; const serversCollection = serversDB.get('servers'); await serversDB.write(async () => { try { if (!serverRecord) { - serverRecord = (await serversCollection.find(server)) as IServerRecord; + serverRecord = (await serversCollection.find(server)) as TServerModel; } await serverRecord.update(record => { record.lastLocalAuthenticatedSession = new Date(); @@ -72,7 +72,7 @@ export const biometryAuth = (force?: boolean): Promise { +const checkBiometry = async (serverRecord: TServerModel) => { const serversDB = database.servers; const result = await biometryAuth(true); @@ -92,7 +92,7 @@ export const checkHasPasscode = async ({ serverRecord }: { force?: boolean; - serverRecord: IServerRecord; + serverRecord: TServerModel; }): Promise<{ newPasscode?: boolean } | void> => { const storedPasscode = await UserPreferences.getStringAsync(PASSCODE_KEY); if (!storedPasscode) { @@ -107,9 +107,9 @@ export const localAuthenticate = async (server: string): Promise => { const serversDB = database.servers; const serversCollection = serversDB.get('servers'); - let serverRecord: IServerRecord; + let serverRecord: TServerModel; try { - serverRecord = (await serversCollection.find(server)) as IServerRecord; + serverRecord = (await serversCollection.find(server)) as TServerModel; } catch (error) { return Promise.reject(); } diff --git a/app/views/ScreenLockConfigView.tsx b/app/views/ScreenLockConfigView.tsx index add03a1ad3d..d6307f5e985 100644 --- a/app/views/ScreenLockConfigView.tsx +++ b/app/views/ScreenLockConfigView.tsx @@ -14,7 +14,7 @@ import { changePasscode, checkHasPasscode, supportedBiometryLabel } from '../uti import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; import { events, logEvent } from '../utils/log'; -import { IServerRecord } from '../definitions/IServer'; +import { TServerModel } from '../definitions/IServer'; const DEFAULT_BIOMETRY = false; @@ -39,7 +39,7 @@ interface IScreenLockConfigViewState { } class ScreenLockConfigView extends React.Component { - private serverRecord?: IServerRecord; + private serverRecord?: TServerModel; private observable?: Subscription; @@ -92,7 +92,7 @@ class ScreenLockConfigView extends React.Component Date: Tue, 11 Jan 2022 13:44:43 -0300 Subject: [PATCH 28/28] refactor: update new types and interfaces for use ISubscription --- app/containers/Avatar/Avatar.tsx | 4 ++-- app/definitions/ISubscription.ts | 2 ++ app/utils/avatar.ts | 4 ++-- app/utils/goRoom.ts | 8 ++++---- app/utils/isReadOnly.ts | 9 ++++++--- app/utils/room.ts | 6 +++--- app/views/CreateDiscussionView/SelectUsers.tsx | 4 ++-- app/views/CreateDiscussionView/interfaces.ts | 4 ++-- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/app/containers/Avatar/Avatar.tsx b/app/containers/Avatar/Avatar.tsx index a58e8650b28..0ad2634f212 100644 --- a/app/containers/Avatar/Avatar.tsx +++ b/app/containers/Avatar/Avatar.tsx @@ -5,7 +5,7 @@ import Touchable from 'react-native-platform-touchable'; import { settings as RocketChatSettings } from '@rocket.chat/sdk'; import { avatarURL } from '../../utils/avatar'; -import { RoomType } from '../../definitions/IRoom'; +import { SubscriptionType } from '../../definitions/ISubscription'; import Emoji from '../markdown/Emoji'; import { IAvatar } from './interfaces'; @@ -28,7 +28,7 @@ const Avatar = React.memo( text, size = 25, borderRadius = 4, - type = RoomType.DIRECT + type = SubscriptionType.DIRECT }: IAvatar) => { if ((!text && !avatar && !emoji && !rid) || !server) { return null; diff --git a/app/definitions/ISubscription.ts b/app/definitions/ISubscription.ts index 5f561edfb59..1f241599a12 100644 --- a/app/definitions/ISubscription.ts +++ b/app/definitions/ISubscription.ts @@ -79,6 +79,8 @@ export interface ISubscription { avatarETag?: string; teamId?: string; teamMain?: boolean; + search?: boolean; + username?: string; // https://nozbe.github.io/WatermelonDB/Relation.html#relation-api messages: Relation; threads: Relation; diff --git a/app/utils/avatar.ts b/app/utils/avatar.ts index 20d374ddab0..7e4b28195da 100644 --- a/app/utils/avatar.ts +++ b/app/utils/avatar.ts @@ -1,5 +1,5 @@ import { compareServerVersion, methods } from '../lib/utils'; -import { RoomType } from '../definitions/IRoom'; +import { SubscriptionType } from '../definitions/ISubscription'; import { IAvatar } from '../containers/Avatar/interfaces'; const formatUrl = (url: string, size: number, query: string) => `${url}?format=png&size=${size}${query}`; @@ -17,7 +17,7 @@ export const avatarURL = ({ serverVersion }: IAvatar): string => { let room; - if (type === RoomType.DIRECT) { + if (type === SubscriptionType.DIRECT) { room = text; } else if (rid && !compareServerVersion(serverVersion, '3.6.0', methods.lowerThan)) { room = `room/${rid}`; diff --git a/app/utils/goRoom.ts b/app/utils/goRoom.ts index df903a925ce..dc8a3188212 100644 --- a/app/utils/goRoom.ts +++ b/app/utils/goRoom.ts @@ -1,7 +1,7 @@ import { ChatsStackParamList } from '../stacks/types'; -import { IRoom, RoomType } from '../definitions/IRoom'; import Navigation from '../lib/Navigation'; import RocketChat from '../lib/rocketchat'; +import { ISubscription, SubscriptionType } from '../definitions/ISubscription'; const navigate = ({ item, @@ -30,10 +30,10 @@ const navigate = ({ }); }; -interface IItem extends Partial { +interface IItem extends Partial { rid: string; name: string; - t: RoomType; + t: SubscriptionType; } export const goRoom = async ({ @@ -56,7 +56,7 @@ export const goRoom = async ({ item: { rid: result.room._id, name: username!, - t: RoomType.DIRECT + t: SubscriptionType.DIRECT }, isMasterDetail, ...props diff --git a/app/utils/isReadOnly.ts b/app/utils/isReadOnly.ts index a4777ee8282..d94b73c4913 100644 --- a/app/utils/isReadOnly.ts +++ b/app/utils/isReadOnly.ts @@ -1,6 +1,6 @@ import RocketChat from '../lib/rocketchat'; import reduxStore from '../lib/createStore'; -import { IRoom } from '../definitions/IRoom'; +import { ISubscription } from '../definitions/ISubscription'; const canPostReadOnly = async ({ rid }: { rid: string }) => { // TODO: this is not reactive. If this permission changes, the component won't be updated @@ -9,10 +9,13 @@ const canPostReadOnly = async ({ rid }: { rid: string }) => { return permission[0]; }; -const isMuted = (room: IRoom, user: { username: string }) => +const isMuted = (room: ISubscription, user: { username: string }) => room && room.muted && room.muted.find && !!room.muted.find(m => m === user.username); -export const isReadOnly = async (room: IRoom, user: { id?: string; username: string; token?: string }): Promise => { +export const isReadOnly = async ( + room: ISubscription, + user: { id?: string; username: string; token?: string } +): Promise => { if (room.archived) { return true; } diff --git a/app/utils/room.ts b/app/utils/room.ts index 2625117745c..3e4e0ef4408 100644 --- a/app/utils/room.ts +++ b/app/utils/room.ts @@ -1,14 +1,14 @@ import moment from 'moment'; -import { IRoom, RoomType } from '../definitions/IRoom'; import { themes } from '../constants/colors'; import I18n from '../i18n'; import { IAttachment } from '../definitions/IAttachment'; +import { ISubscription, SubscriptionType } from '../definitions/ISubscription'; -export const isBlocked = (room: IRoom): boolean => { +export const isBlocked = (room: ISubscription): boolean => { if (room) { const { t, blocked, blocker } = room; - if (t === RoomType.DIRECT && (blocked || blocker)) { + if (t === SubscriptionType.DIRECT && (blocked || blocker)) { return true; } } diff --git a/app/views/CreateDiscussionView/SelectUsers.tsx b/app/views/CreateDiscussionView/SelectUsers.tsx index ed29ad392ee..d63c5ae6aad 100644 --- a/app/views/CreateDiscussionView/SelectUsers.tsx +++ b/app/views/CreateDiscussionView/SelectUsers.tsx @@ -10,9 +10,9 @@ import database from '../../lib/database'; import I18n from '../../i18n'; import { MultiSelect } from '../../containers/UIKit/MultiSelect'; import { themes } from '../../constants/colors'; -import { RoomType } from '../../definitions/IRoom'; import styles from './styles'; import { ICreateDiscussionViewSelectUsers } from './interfaces'; +import { SubscriptionType } from '../../definitions/ISubscription'; interface IUser { name: string; @@ -65,7 +65,7 @@ const SelectUsers = ({ const getAvatar = (item: any) => avatarURL({ text: RocketChat.getRoomAvatar(item), - type: RoomType.DIRECT, + type: SubscriptionType.DIRECT, user: { id: userId, token }, server, avatarETag: item.avatarETag, diff --git a/app/views/CreateDiscussionView/interfaces.ts b/app/views/CreateDiscussionView/interfaces.ts index 42cfdc73375..6009881c1e9 100644 --- a/app/views/CreateDiscussionView/interfaces.ts +++ b/app/views/CreateDiscussionView/interfaces.ts @@ -2,7 +2,7 @@ import { RouteProp } from '@react-navigation/core'; import { StackNavigationProp } from '@react-navigation/stack'; import { NewMessageStackParamList } from '../../stacks/types'; -import { RoomType } from '../../definitions/IRoom'; +import { SubscriptionType } from '../../definitions/ISubscription'; export interface ICreateChannelViewProps { navigation: StackNavigationProp; @@ -16,7 +16,7 @@ export interface ICreateChannelViewProps { loading: boolean; result: { rid: string; - t: RoomType; + t: SubscriptionType; prid: string; }; failure: boolean;