Unverified Commit a2b92f5e authored by Reinaldo Neto's avatar Reinaldo Neto Committed by GitHub
Browse files

Chore: Migrate Utils Folder to Typescript (#3544)


Co-authored-by: default avatarAlexAlexandre <alexalexandrejr@gmail.com>
parent f7418791
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;
......@@ -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 { SubscriptionType } from '../../definitions/ISubscription';
import Emoji from '../markdown/Emoji';
import { IAvatar } from './interfaces';
......@@ -27,8 +28,8 @@ const Avatar = React.memo(
text,
size = 25,
borderRadius = 4,
type = 'd'
}: Partial<IAvatar>) => {
type = SubscriptionType.DIRECT
}: IAvatar) => {
if ((!text && !avatar && !emoji && !rid) || !server) {
return null;
}
......
......@@ -7,17 +7,17 @@ import { getUserSelector } from '../../selectors/login';
import Avatar from './Avatar';
import { IAvatar } from './interfaces';
class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
class AvatarContainer extends React.Component<IAvatar, any> {
private mounted: boolean;
private subscription!: any;
private subscription: any;
static defaultProps = {
text: '',
type: 'd'
};
constructor(props: Partial<IAvatar>) {
constructor(props: IAvatar) {
super(props);
this.mounted = false;
this.state = { avatarETag: '' };
......@@ -55,7 +55,7 @@ class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
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;
......@@ -82,7 +82,7 @@ class AvatarContainer extends React.Component<Partial<IAvatar>, any> {
render() {
const { avatarETag } = this.state;
const { serverVersion } = this.props;
return <Avatar avatarETag={avatarETag} serverVersion={serverVersion} {...this.props} />;
return <Avatar {...this.props} avatarETag={avatarETag} serverVersion={serverVersion} />;
}
}
......
export interface IAvatar {
server: string;
style: any;
server?: string;
style?: any;
text: string;
avatar: string;
emoji: string;
size: number;
borderRadius: number;
type: string;
children: JSX.Element;
user: {
id: string;
token: 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;
}
......@@ -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'),
......
......@@ -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<IPasscodeButton>) => {
const press = () => onPress && onPress(text!);
const Button = React.memo(({ text, disabled, theme, onPress, icon }: IPasscodeButton) => {
const press = () => onPress && onPress(text);
return (
<Touch
style={[styles.buttonView, { backgroundColor: 'transparent' }]}
underlayColor={themes[theme!].passcodeButtonActive}
rippleColor={themes[theme!].passcodeButtonActive}
underlayColor={themes[theme].passcodeButtonActive}
rippleColor={themes[theme].passcodeButtonActive}
enabled={!disabled}
theme={theme}
onPress={press}>
{icon ? (
<CustomIcon name={icon} size={36} color={themes[theme!].passcodePrimary} />
<CustomIcon name={icon} size={36} color={themes[theme].passcodePrimary} />
) : (
<Text style={[styles.buttonText, { color: themes[theme!].passcodePrimary }]}>{text}</Text>
<Text style={[styles.buttonText, { color: themes[theme].passcodePrimary }]}>{text}</Text>
)}
</Touch>
);
......
......@@ -84,7 +84,7 @@ export interface IMessageContent {
export interface IMessageDiscussion {
msg: string;
dcount: number;
dlm: string;
dlm: Date;
theme: string;
}
......
export interface ICommand {
event: {
input: string;
modifierFlags: number;
};
}
......@@ -10,8 +10,8 @@ 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;
......
......@@ -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<TMessageModel>;
threads: Relation<TThreadModel>;
......
export type TThemeMode = 'automatic' | 'light' | 'dark';
export type TDarkLevel = 'black' | 'dark';
export interface IThemePreference {
currentTheme: TThemeMode;
darkLevel: TDarkLevel;
}
......@@ -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';
......@@ -30,6 +30,8 @@ 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';
import { ICommand } from './definitions/ICommand';
RNScreens.enableScreens();
......@@ -42,10 +44,7 @@ interface IDimensions {
interface IState {
theme: string;
themePreferences: {
currentTheme: 'automatic' | 'light';
darkLevel: string;
};
themePreferences: IThemePreference;
width: number;
height: number;
scale: number;
......@@ -175,7 +174,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
......@@ -191,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 });
});
};
......
......@@ -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';
......@@ -36,10 +37,7 @@ interface IDimensions {
interface IState {
theme: string;
themePreferences: {
currentTheme: 'automatic' | 'light';
darkLevel: string;
};
themePreferences: IThemePreference;
root: any;
width: number;
height: number;
......@@ -135,7 +133,7 @@ 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
......
import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import { IThemePreference } from './definitions/ITheme';
interface IThemeContextProps {
theme: string;
themePreferences?: {
currentTheme: 'automatic' | 'light';
darkLevel: string;
};
themePreferences?: IThemePreference;
setTheme?: (newTheme?: {}) => void;
}
......
......@@ -4,7 +4,7 @@ import { isIOS } from './deviceInfo';
const { AppGroup } = NativeModules;
const appGroup = {
const appGroup: { path: string } = {
path: isIOS ? AppGroup.path : ''
};
......
import { compareServerVersion, methods } from '../lib/utils';
import { SubscriptionType } from '../definitions/ISubscription';
import { IAvatar } from '../containers/Avatar/interfaces';
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}`;
export const avatarURL = ({
type,
......@@ -13,9 +15,9 @@ export const avatarURL = ({
rid,
blockUnauthenticatedAccess,
serverVersion
}) => {
}: IAvatar): string => {
let room;
if (type === 'd') {
if (type === SubscriptionType.DIRECT) {
room = text;
} else if (rid && !compareServerVersion(serverVersion, '3.6.0', methods.lowerThan)) {
room = `room/${rid}`;
......
/* eslint-disable no-bitwise */
// https://github.com/beatgammit/base64-js/blob/master/index.js
const lookup = [];
const revLookup = [];
const lookup: string[] = [];
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) => {
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: string, 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
......
export default function debounce(func, wait, immediate) {
let timeout;
function _debounce(...args) {
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;
......@@ -9,12 +11,12 @@ export default function debounce(func, wait, immediate) {
}
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
clearTimeout(timeout!);
timeout = setTimeout(later, wait);
if (callNow) {
func.apply(context, args);
}
}
_debounce.stop = () => clearTimeout(timeout);
_debounce.stop = () => clearTimeout(timeout!);
return _debounce;
}
......@@ -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);
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment