diff --git a/android/app/build.gradle b/android/app/build.gradle
index ca25e19bf..a44f99069 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -144,7 +144,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer
- versionName "4.27.0"
+ versionName "4.28.0"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 312cce983..40d363a85 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
\ No newline at end of file
diff --git a/app/actions/createDiscussion.ts b/app/actions/createDiscussion.ts
index bf64baaa6..d9d9690a5 100644
--- a/app/actions/createDiscussion.ts
+++ b/app/actions/createDiscussion.ts
@@ -2,8 +2,16 @@ import { Action } from 'redux';
import { CREATE_DISCUSSION } from './actionsTypes';
+export interface ICreateDiscussionRequestData {
+ prid: string;
+ pmid?: string;
+ t_name?: string;
+ reply?: string;
+ users: string[];
+ encrypted?: boolean;
+}
interface ICreateDiscussionRequest extends Action {
- data: any;
+ data: ICreateDiscussionRequestData;
}
interface ICreateDiscussionSuccess extends Action {
diff --git a/app/actions/customEmojis.ts b/app/actions/customEmojis.ts
index 261fbd241..a870d21fb 100644
--- a/app/actions/customEmojis.ts
+++ b/app/actions/customEmojis.ts
@@ -1,7 +1,7 @@
import { Action } from 'redux';
-import { ICustomEmojis } from '../reducers/customEmojis';
import { SET_CUSTOM_EMOJIS } from './actionsTypes';
+import { ICustomEmojis } from '../definitions';
export interface ISetCustomEmojis extends Action {
emojis: ICustomEmojis;
diff --git a/app/containers/ActionSheet/Item.tsx b/app/containers/ActionSheet/Item.tsx
index 8f6c8a4a9..5d033c58c 100644
--- a/app/containers/ActionSheet/Item.tsx
+++ b/app/containers/ActionSheet/Item.tsx
@@ -2,21 +2,15 @@ import React from 'react';
import { Text, View } from 'react-native';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
import { testProps } from '../../lib/methods/testProps';
+import { CustomIcon } from '../CustomIcon';
import { useTheme } from '../../theme';
import { Button } from './Button';
+import { TActionSheetOptionsItem } from './Provider';
import styles from './styles';
export interface IActionSheetItem {
- item: {
- title: string;
- icon: string;
- danger?: boolean;
- testID?: string;
- onPress: () => void;
- right?: Function;
- };
+ item: TActionSheetOptionsItem;
hide(): void;
}
diff --git a/app/containers/ActionSheet/Provider.tsx b/app/containers/ActionSheet/Provider.tsx
index 8ad0e7c27..8706dc95a 100644
--- a/app/containers/ActionSheet/Provider.tsx
+++ b/app/containers/ActionSheet/Provider.tsx
@@ -1,13 +1,21 @@
import React, { ForwardedRef, forwardRef, useContext, useRef } from 'react';
import ActionSheet from './ActionSheet';
+import { TIconsName } from '../CustomIcon';
-export type TActionSheetOptionsItem = { title: string; icon: string; onPress: () => void; danger?: boolean };
+export type TActionSheetOptionsItem = {
+ title: string;
+ icon: TIconsName;
+ danger?: boolean;
+ testID?: string;
+ onPress: () => void;
+ right?: () => React.ReactElement;
+};
export type TActionSheetOptions = {
options: TActionSheetOptionsItem[];
- headerHeight: number;
- customHeader: React.ReactElement | null;
+ headerHeight?: number;
+ customHeader?: React.ReactElement | null;
hasCancel?: boolean;
};
interface IActionSheetProvider {
diff --git a/app/containers/Check.tsx b/app/containers/Check.tsx
index 6a43cf9ad..a931fe678 100644
--- a/app/containers/Check.tsx
+++ b/app/containers/Check.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { StyleSheet } from 'react-native';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon } from './CustomIcon';
import { themes } from '../lib/constants';
import { useTheme } from '../theme';
diff --git a/app/containers/CustomIcon/index.tsx b/app/containers/CustomIcon/index.tsx
new file mode 100644
index 000000000..53690cefd
--- /dev/null
+++ b/app/containers/CustomIcon/index.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { createIconSetFromIcoMoon } from 'react-native-vector-icons';
+import { TextProps } from 'react-native';
+
+import { mappedIcons } from './mappedIcons';
+
+const icoMoonConfig = require('./selection.json');
+
+export const IconSet = createIconSetFromIcoMoon(icoMoonConfig, 'custom', 'custom.ttf');
+
+export type TIconsName = keyof typeof mappedIcons;
+
+interface ICustomIcon extends TextProps {
+ name: TIconsName;
+ size: number;
+ color: string;
+}
+
+const CustomIcon = ({ name, size, color, testID, ...props }: ICustomIcon) => (
+ // @ts-ignore TODO remove this after update @types/react-native to 0.65.0
+
+);
+export { CustomIcon };
diff --git a/app/containers/CustomIcon/mappedIcons.js b/app/containers/CustomIcon/mappedIcons.js
new file mode 100644
index 000000000..c5432c3c2
--- /dev/null
+++ b/app/containers/CustomIcon/mappedIcons.js
@@ -0,0 +1,202 @@
+export const mappedIcons = {
+ attach: 59676,
+ link: 59752,
+ 'status-away': 59741,
+ 'status-busy': 59742,
+ 'status-loading': 59743,
+ 'status-offline': 59744,
+ 'status-online': 59745,
+ 'teams-private': 59750,
+ 'channel-auto-join': 59746,
+ 'channel-move-to-team': 59747,
+ 'lock-filled': 59748,
+ locker: 59749,
+ teams: 59751,
+ shield: 59661,
+ ignore: 59740,
+ 'checkbox-unchecked': 59648,
+ 'checkbox-checked': 59649,
+ 'github-monochromatic': 59650,
+ 'gitlab-monochromatic': 59651,
+ 'google-monochromatic': 59652,
+ 'linkedin-monochromatic': 59653,
+ 'meteor-monochromatic': 59654,
+ 'twitter-monochromatic': 59655,
+ administration: 59657,
+ 'adobe-reader-monochromatic': 59658,
+ 'all-contacts-in-channels': 59659,
+ 'all-contacts-in-queue': 59660,
+ 'apple-monochromatic': 59662,
+ apps: 59663,
+ 'arrow-back': 59664,
+ 'arrow-collapse': 59665,
+ 'arrow-decrease': 59666,
+ 'arrow-down-box': 59667,
+ 'arrow-down-circle': 59668,
+ 'arrow-down': 59669,
+ 'arrow-expand': 59670,
+ 'arrow-increase': 59671,
+ 'arrow-looping': 59672,
+ 'arrow-return': 59673,
+ 'arrow-up-box': 59674,
+ 'arrow-up': 59675,
+ 'audio-disabled': 59677,
+ 'audio-unavailable': 59678,
+ audio: 59679,
+ auditing: 59680,
+ auth: 59681,
+ avatar: 59682,
+ backspace: 59683,
+ bold: 59684,
+ book: 59685,
+ business: 59686,
+ calendar: 59687,
+ 'camera-disabled': 59688,
+ 'camera-filled': 59689,
+ 'camera-photo': 59690,
+ 'camera-unavailable': 59691,
+ camera: 59692,
+ 'canned-response': 59693,
+ card: 59694,
+ 'channel-private': 59695,
+ 'channel-public': 59696,
+ 'chat-close': 59697,
+ 'chat-forward': 59698,
+ check: 59699,
+ 'chevron-down': 59700,
+ 'chevron-left-big': 59701,
+ 'chevron-left': 59702,
+ 'chevron-right': 59703,
+ 'chevron-up': 59704,
+ 'circle-check': 59705,
+ clipboard: 59706,
+ clock: 59707,
+ close: 59708,
+ 'cloud-connectivity': 59709,
+ code: 59710,
+ contacts: 59711,
+ copy: 59712,
+ create: 59713,
+ dashboard: 59714,
+ delete: 59715,
+ desktop: 59716,
+ dialpad: 59717,
+ 'directory-disabled': 59718,
+ directory: 59719,
+ discussions: 59720,
+ document: 59721,
+ donner: 59722,
+ download: 59723,
+ edit: 59724,
+ 'emoji-bad-mood': 59725,
+ 'emoji-neutral-mood': 59726,
+ emoji: 59727,
+ encrypted: 59728,
+ 'engagement-dashboard': 59729,
+ 'enterprise-feature': 59730,
+ 'facebook-monochromatic': 59731,
+ 'file-document': 59732,
+ 'file-sheet': 59733,
+ filter: 59734,
+ fingerprint: 59735,
+ flag: 59736,
+ folder: 59737,
+ game: 59738,
+ 'giphy-monochromatic': 59739,
+ 'google-drive-monochromatic': 59756,
+ 'group-by-type': 59757,
+ hamburguer: 59758,
+ history: 59759,
+ home: 59760,
+ image: 59761,
+ info: 59762,
+ 'input-clear': 59763,
+ instance: 59764,
+ italic: 59765,
+ 'jump-backward': 59766,
+ 'jump-forward': 59767,
+ 'jump-to-message': 59768,
+ kebab: 59769,
+ keyboard: 59770,
+ language: 59771,
+ 'live-streaming': 59773,
+ live: 59774,
+ 'livechat-monochromatic': 59775,
+ 'log-view': 59778,
+ login: 59779,
+ logout: 59780,
+ mail: 59781,
+ marketplace: 59782,
+ meatballs: 59783,
+ mention: 59784,
+ 'message-disabled': 59785,
+ message: 59786,
+ 'microphone-disabled': 59787,
+ microphone: 59788,
+ mobile: 59789,
+ moon: 59790,
+ 'move-to-the-queue': 59791,
+ 'musical-note': 59792,
+ 'new-window': 59793,
+ 'notification-disabled': 59794,
+ notification: 59795,
+ omnichannel: 59796,
+ order: 59797,
+ 'ordering-ascending': 59798,
+ 'ordering-descending': 59800,
+ 'pause-filled': 59802,
+ pause: 59803,
+ 'phone-disabled': 59804,
+ 'phone-end': 59805,
+ phone: 59806,
+ 'pin-map': 59807,
+ pin: 59808,
+ Pipe: 59809,
+ 'play-filled': 59810,
+ play: 59811,
+ prune: 59817,
+ queue: 59818,
+ quote: 59819,
+ 'reaction-add': 59820,
+ record: 59821,
+ refresh: 59822,
+ search: 59823,
+ 'send-filled': 59824,
+ send: 59825,
+ settings: 59826,
+ share: 59827,
+ 'shield-check': 59828,
+ 'shield-alt': 59829,
+ signal: 59830,
+ 'sort-az': 59831,
+ sort: 59832,
+ 'star-filled': 59833,
+ star: 59834,
+ strike: 59846,
+ sun: 59847,
+ support: 59848,
+ team: 59849,
+ threads: 59850,
+ total: 59851,
+ transcript: 59852,
+ underline: 59853,
+ undo: 59854,
+ Unlimited: 59855,
+ 'unread-on-top-disabled': 59856,
+ 'unread-on-top': 59857,
+ upload: 59858,
+ 'user-add': 59859,
+ 'user-forward': 59860,
+ user: 59861,
+ 'view-condensed': 59862,
+ 'view-extended': 59863,
+ 'view-medium': 59864,
+ 'waiting-on-me': 59865,
+ warning: 59866,
+ 'whatsapp-monochromatic': 59868,
+ 'wordpress-monochromatic': 59656,
+ workspaces: 59870,
+ zip: 59871,
+ add: 59872,
+ sms: 59753
+};
diff --git a/app/lib/selection.json b/app/containers/CustomIcon/selection.json
similarity index 100%
rename from app/lib/selection.json
rename to app/containers/CustomIcon/selection.json
diff --git a/app/containers/DirectoryItem/index.tsx b/app/containers/DirectoryItem/index.tsx
index d0c8fa1f5..2e78cabd6 100644
--- a/app/containers/DirectoryItem/index.tsx
+++ b/app/containers/DirectoryItem/index.tsx
@@ -18,8 +18,8 @@ interface IDirectoryItemLabel {
interface IDirectoryItem {
title: string;
- description: string;
- avatar: string;
+ description?: string;
+ avatar?: string;
type: string;
onPress(): void;
testID: string;
diff --git a/app/containers/EmojiPicker/CustomEmoji.tsx b/app/containers/EmojiPicker/CustomEmoji.tsx
index aeebbe21c..c96ee7ae5 100644
--- a/app/containers/EmojiPicker/CustomEmoji.tsx
+++ b/app/containers/EmojiPicker/CustomEmoji.tsx
@@ -8,7 +8,6 @@ const CustomEmoji = React.memo(
{
);
};
-class EmojiCategory extends React.Component> {
- renderItem(emoji: any) {
+class EmojiCategory extends React.Component {
+ renderItem(emoji: IEmoji) {
const { baseUrl, onEmojiSelected } = this.props;
return (
onEmojiSelected!(emoji)}
+ onPress={() => onEmojiSelected(emoji)}
{...testProps(`reaction-picker-${emoji && emoji.isCustom ? emoji.content : emoji}`)}>
- {renderEmoji(emoji, EMOJI_SIZE, baseUrl!)}
+ {renderEmoji(emoji, EMOJI_SIZE, baseUrl)}
);
}
@@ -52,7 +53,6 @@ class EmojiCategory extends React.Component> {
const marginHorizontal = (width - numColumns * EMOJI_SIZE) / 2;
return (
- // @ts-ignore
void;
+ activeTab?: number;
+ tabs?: string[];
+ tabEmojiStyle: StyleProp;
theme: TSupportedThemes;
}
-export default class TabBar extends React.Component> {
- shouldComponentUpdate(nextProps: any) {
+export default class TabBar extends React.Component {
+ shouldComponentUpdate(nextProps: ITabBarProps) {
const { activeTab, theme } = this.props;
if (nextProps.activeTab !== activeTab) {
return true;
@@ -31,16 +31,20 @@ export default class TabBar extends React.Component> {
return (
- {tabs!.map((tab, i) => (
+ {tabs?.map((tab, i) => (
goToPage!(i)}
+ onPress={() => {
+ if (goToPage) {
+ goToPage(i);
+ }
+ }}
style={styles.tab}
{...testProps(`reaction-picker-${tab}`)}>
{tab}
{activeTab === i ? (
-
+
) : (
)}
diff --git a/app/emojis.ts b/app/containers/EmojiPicker/emojis.ts
similarity index 99%
rename from app/emojis.ts
rename to app/containers/EmojiPicker/emojis.ts
index 172d15adf..b5ed98f52 100644
--- a/app/emojis.ts
+++ b/app/containers/EmojiPicker/emojis.ts
@@ -1,4 +1,4 @@
-export const emojisByCategory: any = {
+export const emojisByCategory = {
people: [
'grinning',
'grimacing',
diff --git a/app/containers/EmojiPicker/index.tsx b/app/containers/EmojiPicker/index.tsx
index 5884b12a1..08ef6a609 100644
--- a/app/containers/EmojiPicker/index.tsx
+++ b/app/containers/EmojiPicker/index.tsx
@@ -1,38 +1,34 @@
import React, { Component } from 'react';
-import { View } from 'react-native';
+import { StyleProp, TextStyle, View } from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import { dequal } from 'dequal';
import { connect } from 'react-redux';
import orderBy from 'lodash/orderBy';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
+import { ImageStyle } from '@rocket.chat/react-native-fast-image';
import TabBar from './TabBar';
import EmojiCategory from './EmojiCategory';
import styles from './styles';
import categories from './categories';
import database from '../../lib/database';
-import { emojisByCategory } from '../../emojis';
+import { emojisByCategory } from './emojis';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
import log from '../../utils/log';
import { themes } from '../../lib/constants';
import { TSupportedThemes, withTheme } from '../../theme';
-import { IEmoji } from '../../definitions/IEmoji';
-
-const scrollProps = {
- keyboardShouldPersistTaps: 'always',
- keyboardDismissMode: 'none'
-};
+import { IEmoji, TGetCustomEmoji, IApplicationState, ICustomEmojis, TFrequentlyUsedEmojiModel } from '../../definitions';
interface IEmojiPickerProps {
- isMessageContainsOnlyEmoji: boolean;
- getCustomEmoji?: Function;
+ isMessageContainsOnlyEmoji?: boolean;
+ getCustomEmoji?: TGetCustomEmoji;
baseUrl: string;
- customEmojis?: any;
- style: object;
+ customEmojis: ICustomEmojis;
+ style?: StyleProp;
theme: TSupportedThemes;
- onEmojiSelected?: ((emoji: any) => void) | ((keyboardId: any, params?: any) => void);
- tabEmojiStyle?: object;
+ onEmojiSelected: (emoji: string, shortname?: string) => void;
+ tabEmojiStyle?: StyleProp;
}
interface IEmojiPickerState {
@@ -65,7 +61,7 @@ class EmojiPicker extends Component {
this.setState({ show: true });
}
- shouldComponentUpdate(nextProps: any, nextState: any) {
+ shouldComponentUpdate(nextProps: IEmojiPickerProps, nextState: IEmojiPickerState) {
const { frequentlyUsed, show, width } = this.state;
const { theme } = this.props;
if (nextProps.theme !== theme) {
@@ -92,12 +88,12 @@ class EmojiPicker extends Component {
extension: emoji.extension,
isCustom: true
});
- onEmojiSelected!(`:${emoji.content}:`);
+ onEmojiSelected(`:${emoji.content}:`);
} else {
const content = emoji;
this._addFrequentlyUsed({ content, isCustom: false });
const shortname = `:${emoji}:`;
- onEmojiSelected!(shortnameToUnicode(shortname), shortname);
+ onEmojiSelected(shortnameToUnicode(shortname), shortname);
}
} catch (e) {
log(e);
@@ -107,9 +103,8 @@ class EmojiPicker extends Component {
_addFrequentlyUsed = protectedFunction(async (emoji: IEmoji) => {
const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis');
- let freqEmojiRecord: any;
+ let freqEmojiRecord: TFrequentlyUsedEmojiModel;
try {
- // @ts-ignore
freqEmojiRecord = await freqEmojiCollection.find(emoji.content);
} catch (error) {
// Do nothing
@@ -117,11 +112,13 @@ class EmojiPicker extends Component {
await db.write(async () => {
if (freqEmojiRecord) {
- await freqEmojiRecord.update((f: any) => {
- f.count += 1;
+ await freqEmojiRecord.update(f => {
+ if (f.count) {
+ f.count += 1;
+ }
});
} else {
- await freqEmojiCollection.create((f: any) => {
+ await freqEmojiCollection.create(f => {
f._raw = sanitizedRaw({ id: emoji.content }, freqEmojiCollection.schema);
Object.assign(f, emoji);
f.count = 1;
@@ -149,7 +146,7 @@ class EmojiPicker extends Component {
}
}: any) => this.setState({ width });
- renderCategory(category: any, i: number, label: string) {
+ renderCategory(category: keyof typeof emojisByCategory, i: number, label: string) {
const { frequentlyUsed, customEmojis, width } = this.state;
const { baseUrl } = this.props;
@@ -166,7 +163,7 @@ class EmojiPicker extends Component {
emojis={emojis}
onEmojiSelected={(emoji: IEmoji) => this.onEmojiSelected(emoji)}
style={styles.categoryContainer}
- width={width!}
+ width={width}
baseUrl={baseUrl}
tabLabel={label}
/>
@@ -184,10 +181,12 @@ class EmojiPicker extends Component {
}
- /* @ts-ignore*/
- contentProps={scrollProps}
+ contentProps={{
+ keyboardShouldPersistTaps: 'always',
+ keyboardDismissMode: 'none'
+ }}
style={{ backgroundColor: themes[theme].focusedBackground }}>
- {categories.tabs.map((tab, i) =>
+ {categories.tabs.map((tab: any, i) =>
i === 0 && frequentlyUsed.length === 0
? null // when no frequentlyUsed don't show the tab
: this.renderCategory(tab.category, i, tab.tabLabel)
@@ -198,9 +197,8 @@ class EmojiPicker extends Component {
}
}
-const mapStateToProps = (state: any) => ({
+const mapStateToProps = (state: IApplicationState) => ({
customEmojis: state.customEmojis
});
-// TODO - remove this as any, at the new PR to fix the HOC erros
-export default connect(mapStateToProps)(withTheme(EmojiPicker)) as any;
+export default connect(mapStateToProps)(withTheme(EmojiPicker));
diff --git a/app/containers/HeaderButton/HeaderButtonItem.tsx b/app/containers/HeaderButton/HeaderButtonItem.tsx
index 8c1d68e91..4d935bd82 100644
--- a/app/containers/HeaderButton/HeaderButtonItem.tsx
+++ b/app/containers/HeaderButton/HeaderButtonItem.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Platform, StyleSheet, Text } from 'react-native';
import Touchable from 'react-native-platform-touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../CustomIcon';
import { useTheme } from '../../theme';
import { themes } from '../../lib/constants';
import sharedStyles from '../../views/Styles';
@@ -10,7 +10,7 @@ import { testProps } from '../../lib/methods/testProps';
interface IHeaderButtonItem {
title?: string;
- iconName?: string;
+ iconName?: TIconsName;
onPress?: (arg: T) => void;
testID?: string;
badge?(): void;
diff --git a/app/containers/InAppNotification/NotifierComponent.tsx b/app/containers/InAppNotification/NotifierComponent.tsx
index 4e23db566..1862da6aa 100644
--- a/app/containers/InAppNotification/NotifierComponent.tsx
+++ b/app/containers/InAppNotification/NotifierComponent.tsx
@@ -6,7 +6,7 @@ import { Notifier } from 'react-native-notifier';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Avatar from '../Avatar';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
import { useTheme } from '../../theme';
@@ -136,7 +136,7 @@ const NotifierComponent = React.memo(({ notification, isMasterDetail }: INotifie
>
-
+
);
diff --git a/app/containers/List/ListIcon.tsx b/app/containers/List/ListIcon.tsx
index 65f8b4cf9..1c5e9d5d8 100644
--- a/app/containers/List/ListIcon.tsx
+++ b/app/containers/List/ListIcon.tsx
@@ -2,13 +2,13 @@ import React from 'react';
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
import { testProps } from '../../lib/methods/testProps';
+import { CustomIcon, TIconsName } from '../CustomIcon';
import { useTheme } from '../../theme';
import { ICON_SIZE } from './constants';
interface IListIcon {
- name: string;
+ name: TIconsName;
color?: string | null;
style?: StyleProp;
testID?: string;
diff --git a/app/containers/List/ListItem.tsx b/app/containers/List/ListItem.tsx
index 8b9a1529c..c503a1af3 100644
--- a/app/containers/List/ListItem.tsx
+++ b/app/containers/List/ListItem.tsx
@@ -9,8 +9,8 @@ import I18n from '../../i18n';
import { Icon } from '.';
import { BASE_HEIGHT, ICON_SIZE, PADDING_HORIZONTAL } from './constants';
import { useDimensions } from '../../dimensions';
-import { CustomIcon } from '../../lib/Icons';
import { testProps } from '../../lib/methods/testProps';
+import { CustomIcon } from '../CustomIcon';
const styles = StyleSheet.create({
container: {
@@ -97,7 +97,7 @@ const Content = React.memo(
{translateTitle && title ? I18n.t(title) : title}
{alert ? (
-
+
) : null}
{subtitle ? (
diff --git a/app/containers/Loading.tsx b/app/containers/Loading.tsx
index 0572afab5..73e52a02b 100644
--- a/app/containers/Loading.tsx
+++ b/app/containers/Loading.tsx
@@ -1,9 +1,18 @@
-import React from 'react';
-import { Animated, Modal, StyleSheet, View } from 'react-native';
+import React, { useEffect } from 'react';
+import { Animated, Modal, PixelRatio, StyleSheet, View } from 'react-native';
+import {
+ cancelAnimation,
+ Extrapolate,
+ interpolate,
+ useAnimatedStyle,
+ useSharedValue,
+ withRepeat,
+ withSequence,
+ withTiming
+} from 'react-native-reanimated';
-import { TSupportedThemes, withTheme } from '../theme';
-import { themes } from '../lib/constants';
import { testProps } from '../lib/methods/testProps';
+import { useTheme } from '../theme';
const styles = StyleSheet.create({
container: {
@@ -12,130 +21,54 @@ const styles = StyleSheet.create({
justifyContent: 'center'
},
image: {
- width: 100,
- height: 100,
+ width: PixelRatio.get() * 40,
+ height: PixelRatio.get() * 40,
resizeMode: 'contain'
}
});
interface ILoadingProps {
visible: boolean;
- theme?: TSupportedThemes;
}
-interface ILoadingState {
- scale: Animated.Value;
- opacity: Animated.Value;
-}
-
-class Loading extends React.PureComponent {
- state = {
- scale: new Animated.Value(1),
- opacity: new Animated.Value(0)
- };
-
- private opacityAnimation?: Animated.CompositeAnimation;
-
- private scaleAnimation?: Animated.CompositeAnimation;
-
- componentDidMount() {
- const { opacity, scale } = this.state;
- const { visible } = this.props;
-
- this.opacityAnimation = Animated.timing(opacity, {
- toValue: 1,
- duration: 200,
- useNativeDriver: true
- });
- this.scaleAnimation = Animated.loop(
- Animated.sequence([
- Animated.timing(scale, {
- toValue: 0,
- duration: 1000,
- useNativeDriver: true
- }),
- Animated.timing(scale, {
- toValue: 1,
- duration: 1000,
- useNativeDriver: true
- })
- ])
- );
+const Loading = ({ visible }: ILoadingProps): React.ReactElement => {
+ const opacity = useSharedValue(0);
+ const scale = useSharedValue(1);
+ const { colors } = useTheme();
+ useEffect(() => {
if (visible) {
- this.startAnimations();
+ opacity.value = withTiming(1, {
+ duration: 200
+ });
+ scale.value = withRepeat(withSequence(withTiming(0, { duration: 1000 }), withTiming(1, { duration: 1000 })), -1);
}
- }
+ return () => {
+ cancelAnimation(scale);
+ };
+ }, [opacity, scale, visible]);
- componentDidUpdate(prevProps: ILoadingProps) {
- const { visible } = this.props;
- if (visible && visible !== prevProps.visible) {
- this.startAnimations();
- }
- }
+ const animatedOpacity = useAnimatedStyle(() => ({
+ opacity: interpolate(opacity.value, [0, 1], [0, colors.backdropOpacity], Extrapolate.CLAMP)
+ }));
+ const animatedScale = useAnimatedStyle(() => ({ transform: [{ scale: interpolate(scale.value, [0, 0.5, 1], [1, 1.1, 1]) }] }));
- componentWillUnmount() {
- if (this.opacityAnimation && this.opacityAnimation.stop) {
- this.opacityAnimation.stop();
- }
- if (this.scaleAnimation && this.scaleAnimation.stop) {
- this.scaleAnimation.stop();
- }
- }
+ return (
+ {}}>
+
+
+
+
+
+ );
+};
- startAnimations() {
- if (this.opacityAnimation && this.opacityAnimation.start) {
- this.opacityAnimation.start();
- }
- if (this.scaleAnimation && this.scaleAnimation.start) {
- this.scaleAnimation.start();
- }
- }
-
- render() {
- const { opacity, scale } = this.state;
- const { visible, theme } = this.props;
-
- const scaleAnimation = scale.interpolate({
- inputRange: [0, 0.5, 1],
- outputRange: [1, 1.1, 1]
- });
-
- const opacityAnimation = opacity.interpolate({
- inputRange: [0, 1],
- outputRange: [0, themes[theme!].backdropOpacity],
- extrapolate: 'clamp'
- });
-
- return (
- {}}>
-
-
-
-
-
- );
- }
-}
-
-export default withTheme(Loading);
+export default Loading;
diff --git a/app/containers/LoginServices.tsx b/app/containers/LoginServices.tsx
index e10eeed47..e6feac63d 100644
--- a/app/containers/LoginServices.tsx
+++ b/app/containers/LoginServices.tsx
@@ -14,11 +14,11 @@ import Touch from '../utils/touch';
import I18n from '../i18n';
import random from '../utils/random';
import { events, logEvent } from '../utils/log';
-import RocketChat from '../lib/rocketchat';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon, TIconsName } from './CustomIcon';
import { IServices } from '../selectors/login';
import { OutsideParamList } from '../stacks/types';
import { IApplicationState } from '../definitions';
+import { Services } from '../lib/services';
const BUTTON_HEIGHT = 48;
const SERVICE_HEIGHT = 58;
@@ -248,7 +248,7 @@ class LoginServices extends React.PureComponent {};
diff --git a/app/containers/MessageActions/Header.tsx b/app/containers/MessageActions/Header.tsx
index 7b4c57bd8..3a7109cf8 100644
--- a/app/containers/MessageActions/Header.tsx
+++ b/app/containers/MessageActions/Header.tsx
@@ -3,17 +3,15 @@ import { FlatList, StyleSheet, Text, View } from 'react-native';
import { TSupportedThemes, useTheme } from '../../theme';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import shortnameToUnicode from '../../utils/shortnameToUnicode';
import CustomEmoji from '../EmojiPicker/CustomEmoji';
import database from '../../lib/database';
import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions';
import sharedStyles from '../../views/Styles';
-import { TFrequentlyUsedEmojiModel } from '../../definitions/IFrequentlyUsedEmoji';
-import { TAnyMessageModel } from '../../definitions';
-import { IEmoji } from '../../definitions/IEmoji';
import { testProps } from '../../lib/methods/testProps';
+import { TAnyMessageModel, TFrequentlyUsedEmojiModel } from '../../definitions';
type TItem = TFrequentlyUsedEmojiModel | string;
@@ -84,7 +82,7 @@ const HeaderItem = ({ item, onReaction, server, theme }: THeaderItem) => {
style={[styles.headerItem, { backgroundColor: themes[theme].auxiliaryBackground }]}
theme={theme}>
{emojiModel?.isCustom ? (
-
+
) : (
{shortnameToUnicode(`:${emoji}:`)}
)}
diff --git a/app/containers/MessageActions/index.tsx b/app/containers/MessageActions/index.tsx
index 904be75f2..1c7ca9536 100644
--- a/app/containers/MessageActions/index.tsx
+++ b/app/containers/MessageActions/index.tsx
@@ -4,7 +4,6 @@ import Clipboard from '@react-native-clipboard/clipboard';
import { connect } from 'react-redux';
import moment from 'moment';
-import RocketChat from '../../lib/rocketchat';
import database from '../../lib/database';
import I18n from '../../i18n';
import log, { logEvent } from '../../utils/log';
@@ -17,8 +16,10 @@ import { TActionSheetOptionsItem, useActionSheet } from '../ActionSheet';
import Header, { HEADER_HEIGHT, IHeader } from './Header';
import events from '../../utils/log/events';
import { IApplicationState, ILoggedUser, TAnyMessageModel, TSubscriptionModel } from '../../definitions';
+import { getPermalinkMessage, hasPermission } from '../../lib/methods';
+import { Services } from '../../lib/services';
-export interface IMessageActions {
+export interface IMessageActionsProps {
room: TSubscriptionModel;
tmid?: string;
user: Pick;
@@ -42,8 +43,12 @@ export interface IMessageActions {
pinMessagePermission?: string[];
}
+export interface IMessageActions {
+ showMessageActions: (message: TAnyMessageModel) => Promise;
+}
+
const MessageActions = React.memo(
- forwardRef(
+ forwardRef(
(
{
room,
@@ -67,7 +72,7 @@ const MessageActions = React.memo(
deleteMessagePermission,
forceDeleteMessagePermission,
pinMessagePermission
- }: IMessageActions,
+ },
ref
) => {
let permissions = {
@@ -81,7 +86,7 @@ const MessageActions = React.memo(
const getPermissions = async () => {
try {
const permission = [editMessagePermission, deleteMessagePermission, forceDeleteMessagePermission, pinMessagePermission];
- const result = await RocketChat.hasPermission(permission, room.rid);
+ const result = await hasPermission(permission, room.rid);
permissions = {
hasEditPermission: result[0],
hasDeletePermission: result[1],
@@ -150,7 +155,7 @@ const MessageActions = React.memo(
return true;
};
- const getPermalink = (message: TAnyMessageModel) => RocketChat.getPermalinkMessage(message);
+ const getPermalink = (message: TAnyMessageModel) => getPermalinkMessage(message);
const handleReply = (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_REPLY);
@@ -178,7 +183,7 @@ const MessageActions = React.memo(
const { rid } = room;
try {
const db = database.active;
- const result = await RocketChat.markAsUnread({ messageId });
+ const result = await Services.markAsUnread({ messageId });
if (result.success) {
const subCollection = db.get('subscriptions');
const subRecord = await subCollection.find(rid);
@@ -234,7 +239,7 @@ const MessageActions = React.memo(
const handleStar = async (message: TAnyMessageModel) => {
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
try {
- await RocketChat.toggleStarMessage(message.id, message.starred as boolean); // TODO: reevaluate `message.starred` type on IMessage
+ await Services.toggleStarMessage(message.id, message.starred as boolean); // TODO: reevaluate `message.starred` type on IMessage
EventEmitter.emit(LISTENER, { message: message.starred ? I18n.t('Message_unstarred') : I18n.t('Message_starred') });
} catch (e) {
logEvent(events.ROOM_MSG_ACTION_STAR_F);
@@ -245,7 +250,7 @@ const MessageActions = React.memo(
const handlePin = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_PIN);
try {
- await RocketChat.togglePinMessage(message.id, message.pinned as boolean); // TODO: reevaluate `message.pinned` type on IMessage
+ await Services.togglePinMessage(message.id, message.pinned as boolean); // TODO: reevaluate `message.pinned` type on IMessage
} catch (e) {
logEvent(events.ROOM_MSG_ACTION_PIN_F);
log(e);
@@ -292,7 +297,7 @@ const MessageActions = React.memo(
u: message.u,
msg: message.msg
};
- await RocketChat.translateMessage(m, room.autoTranslateLanguage);
+ await Services.translateMessage(m, room.autoTranslateLanguage);
}
} catch (e) {
log(e);
@@ -302,7 +307,7 @@ const MessageActions = React.memo(
const handleReport = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_REPORT);
try {
- await RocketChat.reportMessage(message.id);
+ await Services.reportMessage(message.id);
Alert.alert(I18n.t('Message_Reported'));
} catch (e) {
logEvent(events.ROOM_MSG_ACTION_REPORT_F);
@@ -317,7 +322,7 @@ const MessageActions = React.memo(
onPress: async () => {
try {
logEvent(events.ROOM_MSG_ACTION_DELETE);
- await RocketChat.deleteMessage(message.id, message.subscription ? message.subscription.id : '');
+ await Services.deleteMessage(message.id, message.subscription ? message.subscription.id : '');
} catch (e) {
logEvent(events.ROOM_MSG_ACTION_DELETE_F);
log(e);
diff --git a/app/containers/MessageBox/CommandsPreview/Item.tsx b/app/containers/MessageBox/CommandsPreview/Item.tsx
index 28bfac898..6069b72ab 100644
--- a/app/containers/MessageBox/CommandsPreview/Item.tsx
+++ b/app/containers/MessageBox/CommandsPreview/Item.tsx
@@ -3,8 +3,8 @@ import React, { useContext, useState } from 'react';
import { TouchableOpacity } from 'react-native';
import { themes } from '../../../lib/constants';
-import { CustomIcon } from '../../../lib/Icons';
import { testProps } from '../../../lib/methods/testProps';
+import { CustomIcon } from '../../CustomIcon';
import { useTheme } from '../../../theme';
import ActivityIndicator from '../../ActivityIndicator';
import MessageboxContext from '../Context';
diff --git a/app/containers/MessageBox/EmojiKeyboard.tsx b/app/containers/MessageBox/EmojiKeyboard.tsx
index 5de9a72c7..2f8f5b6f6 100644
--- a/app/containers/MessageBox/EmojiKeyboard.tsx
+++ b/app/containers/MessageBox/EmojiKeyboard.tsx
@@ -7,7 +7,6 @@ import EmojiPicker from '../EmojiPicker';
import styles from './styles';
import { themes } from '../../lib/constants';
import { TSupportedThemes, withTheme } from '../../theme';
-import { IEmoji } from '../../definitions/IEmoji';
import { testProps } from '../../lib/methods/testProps';
interface IMessageBoxEmojiKeyboard {
@@ -23,7 +22,7 @@ export default class EmojiKeyboard extends React.PureComponent {
+ onEmojiSelected = (emoji: string) => {
KeyboardRegistry.onItemSelected('EmojiKeyboard', { emoji });
};
@@ -33,7 +32,7 @@ export default class EmojiKeyboard extends React.PureComponent
-
+
);
}
diff --git a/app/containers/MessageBox/Mentions/MentionHeaderList.tsx b/app/containers/MessageBox/Mentions/MentionHeaderList.tsx
index d0a0284e4..33a13a89f 100644
--- a/app/containers/MessageBox/Mentions/MentionHeaderList.tsx
+++ b/app/containers/MessageBox/Mentions/MentionHeaderList.tsx
@@ -3,7 +3,7 @@ import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
import { themes } from '../../../lib/constants';
import I18n from '../../../i18n';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../CustomIcon';
import { useTheme } from '../../../theme';
import sharedStyles from '../../../views/Styles';
import MessageboxContext from '../Context';
diff --git a/app/containers/MessageBox/RecordAudio.tsx b/app/containers/MessageBox/RecordAudio.tsx
index 2cbae4734..d11a13c12 100644
--- a/app/containers/MessageBox/RecordAudio.tsx
+++ b/app/containers/MessageBox/RecordAudio.tsx
@@ -8,7 +8,7 @@ import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import styles from './styles';
import I18n from '../../i18n';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { events, logEvent } from '../../utils/log';
import { testProps } from '../../lib/methods/testProps';
import { TSupportedThemes } from '../../theme';
diff --git a/app/containers/MessageBox/ReplyPreview.tsx b/app/containers/MessageBox/ReplyPreview.tsx
index 7818b681e..a16e51cbc 100644
--- a/app/containers/MessageBox/ReplyPreview.tsx
+++ b/app/containers/MessageBox/ReplyPreview.tsx
@@ -4,7 +4,7 @@ import moment from 'moment';
import { connect } from 'react-redux';
import { MarkdownPreview } from '../markdown';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
import { IMessage } from '../../definitions/IMessage';
diff --git a/app/containers/MessageBox/buttons/BaseButton.tsx b/app/containers/MessageBox/buttons/BaseButton.tsx
index 158f9aa01..bc98f9a88 100644
--- a/app/containers/MessageBox/buttons/BaseButton.tsx
+++ b/app/containers/MessageBox/buttons/BaseButton.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import { View } from 'react-native';
import styles from '../styles';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../CustomIcon';
import { useTheme } from '../../../theme';
import { themes } from '../../../lib/constants';
import { testProps } from '../../../lib/methods/testProps';
@@ -13,11 +13,11 @@ interface IBaseButton {
onPress(): void;
testID: string;
accessibilityLabel: string;
- icon: string;
- color: string;
+ icon: TIconsName;
+ color?: string;
}
-const BaseButton = ({ accessibilityLabel, icon, color, ...props }: Partial) => {
+const BaseButton = ({ accessibilityLabel, icon, color, ...props }: IBaseButton) => {
const { theme } = useTheme();
return (
diff --git a/app/containers/MessageBox/index.tsx b/app/containers/MessageBox/index.tsx
index d860d2867..f05c8eb7c 100644
--- a/app/containers/MessageBox/index.tsx
+++ b/app/containers/MessageBox/index.tsx
@@ -11,10 +11,9 @@ import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
import { generateTriggerId } from '../../lib/methods/actions';
import TextInput, { IThemedTextInput } from '../../presentation/TextInput';
import { userTyping as userTypingAction } from '../../actions/room';
-import RocketChat from '../../lib/rocketchat';
import styles from './styles';
import database from '../../lib/database';
-import { emojis } from '../../emojis';
+import { emojis } from '../EmojiPicker/emojis';
import log, { events, logEvent } from '../../utils/log';
import RecordAudio from './RecordAudio';
import I18n from '../../i18n';
@@ -47,12 +46,14 @@ import { getUserSelector } from '../../selectors/login';
import Navigation from '../../lib/navigation/appNavigation';
import { withActionSheet } from '../ActionSheet';
import { sanitizeLikeString } from '../../lib/database/utils';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { IMessage } from '../../definitions/IMessage';
import { forceJpgExtension } from './forceJpgExtension';
-import { IBaseScreen, IPreviewItem, IUser, TSubscriptionModel, TThreadModel } from '../../definitions';
+import { IBaseScreen, IPreviewItem, IUser, TGetCustomEmoji, TSubscriptionModel, TThreadModel } from '../../definitions';
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
import { testProps } from '../../lib/methods/testProps';
+import { getPermalinkMessage, hasPermission, search, sendFileMessage } from '../../lib/methods';
+import { Services } from '../../lib/services';
import { TSupportedThemes } from '../../theme';
if (isAndroid) {
@@ -92,7 +93,7 @@ export interface IMessageBoxProps extends IBaseScreen {
- private text: string;
+ public text: string;
private selection: { start: number; end: number };
@@ -409,7 +410,7 @@ class MessageBox extends Component {
return;
}
- const permissionToUpload = await RocketChat.hasPermission([uploadFilePermission], rid);
+ const permissionToUpload = await hasPermission([uploadFilePermission], rid);
this.setState({ permissionToUpload: permissionToUpload[0] });
};
@@ -530,14 +531,14 @@ class MessageBox extends Component {
try {
const { appId } = command;
const triggerId = generateTriggerId(appId);
- RocketChat.executeCommandPreview(name, params, rid, item, triggerId, tmid || messageTmid);
+ Services.executeCommandPreview(name, params, rid, item, triggerId, tmid || messageTmid);
replyCancel();
} catch (e) {
log(e);
}
};
- onEmojiSelected = (keyboardId: any, params: any) => {
+ onEmojiSelected = (keyboardId: string, params: { emoji: string }) => {
const { text } = this;
const { emoji } = params;
let newText = '';
@@ -553,7 +554,7 @@ class MessageBox extends Component {
getPermalink = async (message: any) => {
try {
- return await RocketChat.getPermalinkMessage(message);
+ return await getPermalinkMessage(message);
} catch (error) {
return null;
}
@@ -571,13 +572,13 @@ class MessageBox extends Component {
};
getUsers = debounce(async (keyword: any) => {
- let res = await RocketChat.search({ text: keyword, filterRooms: false, filterUsers: true });
+ let res = await search({ text: keyword, filterRooms: false, filterUsers: true });
res = [...this.getFixedMentions(keyword), ...res];
this.setState({ mentions: res, mentionLoading: false });
}, 300);
getRooms = debounce(async (keyword = '') => {
- const res = await RocketChat.search({ text: keyword, filterRooms: true, filterUsers: false });
+ const res = await search({ text: keyword, filterRooms: true, filterUsers: false });
this.setState({ mentions: res, mentionLoading: false });
}, 300);
@@ -605,7 +606,7 @@ class MessageBox extends Component {
}, 300);
getCannedResponses = debounce(async (text?: string) => {
- const res = await RocketChat.getListCannedResponse({ text });
+ const res = await Services.getListCannedResponse({ text });
this.setState({ mentions: res.success ? res.cannedResponses : [], mentionLoading: false });
}, 500);
@@ -642,7 +643,7 @@ class MessageBox extends Component {
setCommandPreview = async (command: any, name: string, params: string) => {
const { rid } = this.props;
try {
- const response = await RocketChat.getCommandPreview(name, rid, params);
+ const response = await Services.getCommandPreview(name, rid, params);
if (response.success) {
return this.setState({ commandPreview: response.preview?.items || [], showCommandPreview: true, command });
}
@@ -837,7 +838,7 @@ class MessageBox extends Component {
if (fileInfo) {
try {
if (this.canUploadFile(fileInfo)) {
- await RocketChat.sendFileMessage(rid, fileInfo, tmid, server, user);
+ await sendFileMessage(rid, fileInfo, tmid, server, user);
}
} catch (e) {
log(e);
@@ -889,7 +890,7 @@ class MessageBox extends Component {
const messageWithoutCommand = message.replace(/([^\s]+)/, '').trim();
const [{ appId }] = slashCommand;
const triggerId = generateTriggerId(appId);
- await RocketChat.runSlashCommand(command, roomId, messageWithoutCommand, triggerId, tmid || messageTmid);
+ await Services.runSlashCommand(command, roomId, messageWithoutCommand, triggerId, tmid || messageTmid);
replyCancel();
} catch (e) {
logEvent(events.COMMAND_RUN_F);
@@ -1182,4 +1183,6 @@ const dispatchToProps = {
typing: (rid: any, status: any) => userTypingAction(rid, status)
};
-export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox)) as any;
+export type MessageBoxType = MessageBox;
+
+export default connect(mapStateToProps, dispatchToProps, null, { forwardRef: true })(withActionSheet(MessageBox));
diff --git a/app/containers/MessageErrorActions.tsx b/app/containers/MessageErrorActions.tsx
index b277adac6..de5829e9f 100644
--- a/app/containers/MessageErrorActions.tsx
+++ b/app/containers/MessageErrorActions.tsx
@@ -1,20 +1,23 @@
import { forwardRef, useImperativeHandle } from 'react';
import Model from '@nozbe/watermelondb/Model';
-import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
import protectedFunction from '../lib/methods/helpers/protectedFunction';
import { useActionSheet } from './ActionSheet';
import I18n from '../i18n';
import log from '../utils/log';
import { TMessageModel } from '../definitions';
+import { resendMessage } from '../lib/methods';
-const MessageErrorActions = forwardRef(({ tmid }: { tmid: string }, ref) => {
- // TODO - remove this any after merge ActionSheet evaluate
- const { showActionSheet }: any = useActionSheet();
+export interface IMessageErrorActions {
+ showMessageErrorActions: (message: TMessageModel) => void;
+}
+
+const MessageErrorActions = forwardRef(({ tmid }, ref) => {
+ const { showActionSheet } = useActionSheet();
const handleResend = protectedFunction(async (message: TMessageModel) => {
- await RocketChat.resendMessage(message, tmid);
+ await resendMessage(message, tmid);
});
const handleDelete = async (message: TMessageModel) => {
diff --git a/app/containers/Passcode/Base/Button.tsx b/app/containers/Passcode/Base/Button.tsx
index a60b1b23a..745e90957 100644
--- a/app/containers/Passcode/Base/Button.tsx
+++ b/app/containers/Passcode/Base/Button.tsx
@@ -4,12 +4,12 @@ import { Text } from 'react-native';
import styles from './styles';
import { themes } from '../../../lib/constants';
import Touch from '../../../utils/touch';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../CustomIcon';
import { useTheme } from '../../../theme';
interface IPasscodeButton {
text?: string;
- icon?: string;
+ icon?: TIconsName;
disabled?: boolean;
onPress?: Function;
}
diff --git a/app/containers/Passcode/Base/LockIcon.tsx b/app/containers/Passcode/Base/LockIcon.tsx
index 975124386..6c248d41c 100644
--- a/app/containers/Passcode/Base/LockIcon.tsx
+++ b/app/containers/Passcode/Base/LockIcon.tsx
@@ -4,7 +4,7 @@ import { Row } from 'react-native-easy-grid';
import styles from './styles';
import { themes } from '../../../lib/constants';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../CustomIcon';
import { useTheme } from '../../../theme';
const LockIcon = React.memo(() => {
diff --git a/app/containers/ReactionsModal.tsx b/app/containers/ReactionsModal.tsx
index 4c90d2045..b74707f04 100644
--- a/app/containers/ReactionsModal.tsx
+++ b/app/containers/ReactionsModal.tsx
@@ -5,7 +5,7 @@ import Touchable from 'react-native-platform-touchable';
import Emoji from './message/Emoji';
import I18n from '../i18n';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon } from './CustomIcon';
import sharedStyles from '../views/Styles';
import { themes } from '../lib/constants';
import { TSupportedThemes, useTheme, withTheme } from '../theme';
@@ -125,7 +125,7 @@ const ModalContent = React.memo(({ message, onClose, ...props }: IModalContent)
-
+
{I18n.t('Reactions')}
diff --git a/app/containers/RoomHeader/__snapshots__/RoomHeader.stories.storyshot b/app/containers/RoomHeader/__snapshots__/RoomHeader.stories.storyshot
index ee70ce65f..96507999c 100644
--- a/app/containers/RoomHeader/__snapshots__/RoomHeader.stories.storyshot
+++ b/app/containers/RoomHeader/__snapshots__/RoomHeader.stories.storyshot
@@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Storyshots RoomHeader icons 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"private channel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"private channel\\"},\\"children\\":[\\"private channel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"public channel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"public channel\\"},\\"children\\":[\\"public channel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"discussion\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"discussion\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"discussion\\"},\\"children\\":[\\"discussion\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"omnichannel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#cbced1\\"},[{\\"marginRight\\":4},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"omnichannel\\"},\\"children\\":[\\"omnichannel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"private team\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"private team\\"},\\"children\\":[\\"private team\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"public team\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"public team\\"},\\"children\\":[\\"public team\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"group dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"group dm\\"},\\"children\\":[\\"group dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"online dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#2de0a5\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#2de0a5\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"online dm\\"},\\"children\\":[\\"online dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"away dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#ffd21f\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#ffd21f\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"away dm\\"},\\"children\\":[\\"away dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"busy dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#f5455c\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#f5455c\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"busy dm\\"},\\"children\\":[\\"busy dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"loading dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#9ea2a8\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#9ea2a8\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"loading dm\\"},\\"children\\":[\\"loading dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"offline dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#cbced1\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#cbced1\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"offline dm\\"},\\"children\\":[\\"offline dm\\"]}]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader icons 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"private channel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"private channel\\"},\\"children\\":[\\"private channel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"public channel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"public channel\\"},\\"children\\":[\\"public channel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"discussion\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"discussion\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"discussion\\"},\\"children\\":[\\"discussion\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"omnichannel\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#cbced1\\"},[{\\"marginRight\\":4},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"omnichannel\\"},\\"children\\":[\\"omnichannel\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"private team\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"private team\\"},\\"children\\":[\\"private team\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"public team\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"public team\\"},\\"children\\":[\\"public team\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"group dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"group dm\\"},\\"children\\":[\\"group dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"online dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#2de0a5\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#2de0a5\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"online dm\\"},\\"children\\":[\\"online dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"away dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#ffd21f\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#ffd21f\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"away dm\\"},\\"children\\":[\\"away dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"busy dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#f5455c\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#f5455c\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"busy dm\\"},\\"children\\":[\\"busy dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"loading dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#9ea2a8\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#9ea2a8\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"loading dm\\"},\\"children\\":[\\"loading dm\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"offline dm\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#cbced1\\"},[{\\"width\\":16,\\"height\\":16,\\"textAlignVertical\\":\\"center\\"},[[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"color\\":\\"#cbced1\\"}]],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"offline dm\\"},\\"children\\":[\\"offline dm\\"]}]}]}]}]}]}]"`;
-exports[`Storyshots RoomHeader landscape 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":12.8,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":9.600000000000001,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":12.8,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":9.600000000000001,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader landscape 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":12.8,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":9.600000000000001,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":12.8,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":9.600000000000001,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]"`;
-exports[`Storyshots RoomHeader themes 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#0b182c\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#2F3A4B\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#0b182c\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#f9f9f9\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#cbced1\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9297a2\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#0d0d0d\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#323232\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#0d0d0d\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#f9f9f9\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#cbced1\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#b2b8c6\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader themes 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#0b182c\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#2F3A4B\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#0b182c\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#f9f9f9\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#cbced1\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9297a2\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#0d0d0d\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#323232\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#0d0d0d\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#f9f9f9\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#f9f9f9\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#cbced1\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#b2b8c6\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]}]"`;
-exports[`Storyshots RoomHeader thread 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"title\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"parent title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"markdown\\\\npreview\\\\n#3\\\\n4\\\\n5\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"markdown preview #3 4 5\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"markdown\\\\npreview\\\\n#3\\\\n4\\\\n5\\"},\\"children\\":[\\"markdown preview #3 4 5\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader thread 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"title\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"parent title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"markdown\\\\npreview\\\\n#3\\\\n4\\\\n5\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"markdown preview #3 4 5\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"markdown\\\\npreview\\\\n#3\\\\n4\\\\n5\\"},\\"children\\":[\\"markdown preview #3 4 5\\"]}]},{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]}]"`;
-exports[`Storyshots RoomHeader title and subtitle 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"title\\"},\\"children\\":[\\"title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader title and subtitle 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"title\\"},\\"children\\":[\\"title\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"subtitle\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"subtitle\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1,\\"testID\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"accessibilityLabel\\":\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\",\\"style\\":[{\\"fontSize\\":16,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"color\\":\\"#2f343d\\"},{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries\\"]}]}]}]}]}]"`;
-exports[`Storyshots RoomHeader typing 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1\\",\\" \\"]},\\"is typing\\",\\"...\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1 and user 2\\",\\" \\"]},\\"are typing\\",\\"...\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1, user 2, user 3, user 4, user 5\\",\\" \\"]},\\"are typing\\",\\"...\\"]}]}]}]}]}]"`;
+exports[`Storyshots RoomHeader typing 1`] = `"[{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1\\",\\" \\"]},\\"is typing\\",\\"...\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1 and user 2\\",\\" \\"]},\\"are typing\\",\\"...\\"]}]}]}]}]},{\\"type\\":\\"RNCSafeAreaView\\",\\"props\\":{\\"style\\":{\\"backgroundColor\\":\\"#EEEFF1\\"},\\"edges\\":[\\"top\\",\\"left\\",\\"right\\"]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":[{\\"height\\":44,\\"flexDirection\\":\\"row\\",\\"justifyContent\\":\\"center\\",\\"elevation\\":4},{\\"borderBottomWidth\\":0.5,\\"borderBottomColor\\":\\"#B2B2B2\\",\\"elevation\\":0,\\"backgroundColor\\":\\"#EEEFF1\\"}]},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"flex\\":1,\\"paddingHorizontal\\":12}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"accessible\\":true,\\"accessibilityLabel\\":\\"title\\",\\"testID\\":\\"room-header\\",\\"hitSlop\\":{\\"top\\":5,\\"right\\":5,\\"bottom\\":5,\\"left\\":5},\\"focusable\\":true,\\"style\\":{\\"flex\\":1,\\"justifyContent\\":\\"center\\",\\"opacity\\":1}},\\"children\\":[{\\"type\\":\\"View\\",\\"props\\":{\\"style\\":{\\"alignItems\\":\\"center\\",\\"flexDirection\\":\\"row\\"}},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"allowFontScaling\\":false,\\"style\\":[{\\"fontSize\\":16,\\"color\\":\\"#0d0e12\\"},[{\\"marginRight\\":4},{\\"color\\":\\"#0d0e12\\"},null],{\\"fontFamily\\":\\"custom\\",\\"fontWeight\\":\\"normal\\",\\"fontStyle\\":\\"normal\\"},{}]},\\"children\\":[\\"\\"]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"},{\\"fontSize\\":16,\\"color\\":\\"#0C0D0F\\"}],\\"numberOfLines\\":1},\\"children\\":[\\"title\\"]}]},{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":[{\\"flexShrink\\":1,\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"400\\"},{\\"fontSize\\":12,\\"color\\":\\"#9ca2a8\\"}],\\"numberOfLines\\":1},\\"children\\":[{\\"type\\":\\"Text\\",\\"props\\":{\\"style\\":{\\"textAlign\\":\\"left\\",\\"backgroundColor\\":\\"transparent\\",\\"fontFamily\\":\\"System\\",\\"fontWeight\\":\\"600\\"}},\\"children\\":[\\"user 1, user 2, user 3, user 4, user 5\\",\\" \\"]},\\"are typing\\",\\"...\\"]}]}]}]}]}]"`;
diff --git a/app/containers/RoomItem/Actions.tsx b/app/containers/RoomItem/Actions.tsx
index e21c2c56e..f60e78131 100644
--- a/app/containers/RoomItem/Actions.tsx
+++ b/app/containers/RoomItem/Actions.tsx
@@ -3,7 +3,7 @@ import { Animated, View } from 'react-native';
import { RectButton } from 'react-native-gesture-handler';
import { isRTL } from '../../i18n';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { DisplayMode, themes } from '../../lib/constants';
import styles, { ACTION_WIDTH, LONG_SWIPE, ROW_HEIGHT_CONDENSED } from './styles';
import { ILeftActionsProps, IRightActionsProps } from './interfaces';
diff --git a/app/containers/RoomItem/TypeIcon.tsx b/app/containers/RoomItem/TypeIcon.tsx
index b6ed33268..7be29c587 100644
--- a/app/containers/RoomItem/TypeIcon.tsx
+++ b/app/containers/RoomItem/TypeIcon.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import RoomTypeIcon from '../RoomTypeIcon';
import { ITypeIconProps } from './interfaces';
-const TypeIcon = React.memo(({ type, prid, status, isGroupChat, teamMain, size, style }: ITypeIconProps) => (
+const TypeIcon = React.memo(({ type, prid, status, isGroupChat, teamMain, size, style, sourceType }: ITypeIconProps) => (
));
diff --git a/app/containers/RoomTypeIcon/OmnichannelRoomIcon.tsx b/app/containers/RoomTypeIcon/OmnichannelRoomIcon.tsx
index 59c0f3b58..864a55155 100644
--- a/app/containers/RoomTypeIcon/OmnichannelRoomIcon.tsx
+++ b/app/containers/RoomTypeIcon/OmnichannelRoomIcon.tsx
@@ -5,9 +5,13 @@ import { useSelector } from 'react-redux';
import { OmnichannelSourceType, IApplicationState, IOmnichannelSource } from '../../definitions';
import { STATUS_COLORS } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../CustomIcon';
-const iconMap = {
+interface IIconMap {
+ [key: string]: TIconsName;
+}
+
+const iconMap: IIconMap = {
widget: 'livechat-monochromatic',
email: 'mail',
sms: 'sms',
diff --git a/app/containers/RoomTypeIcon/index.tsx b/app/containers/RoomTypeIcon/index.tsx
index f45f9616f..e2cd5e777 100644
--- a/app/containers/RoomTypeIcon/index.tsx
+++ b/app/containers/RoomTypeIcon/index.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { StyleSheet, ViewStyle } from 'react-native';
import { OmnichannelRoomIcon } from './OmnichannelRoomIcon';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../CustomIcon';
import { STATUS_COLORS, themes } from '../../lib/constants';
import Status from '../Status/Status';
import { useTheme } from '../../theme';
@@ -46,7 +46,7 @@ const RoomTypeIcon = React.memo(({ type, isGroupChat, status, style, teamMain, s
}
// TODO: move this to a separate function
- let icon = 'channel-private';
+ let icon: TIconsName = 'channel-private';
if (teamMain) {
icon = `teams${type === 'p' ? '-private' : ''}`;
} else if (type === 'discussion') {
@@ -61,7 +61,7 @@ const RoomTypeIcon = React.memo(({ type, isGroupChat, status, style, teamMain, s
}
}
- return ;
+ return ;
});
export default RoomTypeIcon;
diff --git a/app/containers/SearchBox.tsx b/app/containers/SearchBox.tsx
index 2dbda29cd..75174e474 100644
--- a/app/containers/SearchBox.tsx
+++ b/app/containers/SearchBox.tsx
@@ -4,7 +4,7 @@ import Touchable from 'react-native-platform-touchable';
import { themes } from '../lib/constants';
import I18n from '../i18n';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon } from './CustomIcon';
import TextInput from '../presentation/TextInput';
import { useTheme } from '../theme';
import { isIOS } from '../utils/deviceInfo';
diff --git a/app/containers/Status/Status.tsx b/app/containers/Status/Status.tsx
index b23b01dd9..b076fc849 100644
--- a/app/containers/Status/Status.tsx
+++ b/app/containers/Status/Status.tsx
@@ -1,13 +1,13 @@
import React from 'react';
import { StyleProp, TextStyle } from 'react-native';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, IconSet, TIconsName } from '../CustomIcon';
import { STATUS_COLORS } from '../../lib/constants';
import { IStatus } from './definition';
const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: Omit) => {
- const name = `status-${status}`;
- const isNameValid = CustomIcon.hasIcon(name);
+ const name: TIconsName = `status-${status}`;
+ const isNameValid = IconSet.hasIcon(name);
const iconName = isNameValid ? name : 'status-offline';
const calculatedStyle: StyleProp = [
{
diff --git a/app/containers/TextInput.tsx b/app/containers/TextInput.tsx
index 9e8d1524a..4a58e98d8 100644
--- a/app/containers/TextInput.tsx
+++ b/app/containers/TextInput.tsx
@@ -5,7 +5,7 @@ import Touchable from 'react-native-platform-touchable';
import sharedStyles from '../views/Styles';
import TextInput from '../presentation/TextInput';
import { themes } from '../lib/constants';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon, TIconsName } from './CustomIcon';
import ActivityIndicator from './ActivityIndicator';
import { testProps } from '../lib/methods/testProps';
import { TSupportedThemes } from '../theme';
@@ -60,8 +60,8 @@ export interface IRCTextInputProps extends TextInputProps {
inputStyle?: StyleProp;
inputRef?: React.Ref;
testID?: string;
- iconLeft?: string;
- iconRight?: string;
+ iconLeft?: TIconsName;
+ iconRight?: TIconsName;
left?: JSX.Element;
onIconRightPress?(): void;
theme: TSupportedThemes;
@@ -83,23 +83,24 @@ export default class RCTextInput extends React.PureComponent
- );
+ ) : null;
}
get iconRight() {
const { iconRight, onIconRightPress, theme } = this.props;
- return (
+ return iconRight ? (
-
+
- );
+ ) : null;
}
get iconPassword() {
@@ -112,6 +113,7 @@ export default class RCTextInput extends React.PureComponent
);
diff --git a/app/containers/ThreadDetails.tsx b/app/containers/ThreadDetails.tsx
index 64a65d42a..714e8035c 100644
--- a/app/containers/ThreadDetails.tsx
+++ b/app/containers/ThreadDetails.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { StyleSheet, Text, View, ViewStyle } from 'react-native';
import Touchable from 'react-native-platform-touchable';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon } from './CustomIcon';
import { themes } from '../lib/constants';
import sharedStyles from '../views/Styles';
import { useTheme } from '../theme';
diff --git a/app/containers/TwoFactor/index.tsx b/app/containers/TwoFactor/index.tsx
index 6509f57d3..a83af6c26 100644
--- a/app/containers/TwoFactor/index.tsx
+++ b/app/containers/TwoFactor/index.tsx
@@ -13,9 +13,9 @@ import { useTheme } from '../../theme';
import { themes } from '../../lib/constants';
import Button from '../Button';
import sharedStyles from '../../views/Styles';
-import RocketChat from '../../lib/rocketchat';
import styles from './styles';
import { IApplicationState } from '../../definitions';
+import { Services } from '../../lib/services';
export const TWO_FACTOR = 'TWO_FACTOR';
@@ -63,7 +63,7 @@ const TwoFactor = React.memo(({ isMasterDetail }: { isMasterDetail: boolean }) =
const method = data.method ? methods[data.method] : null;
const isEmail = data.method === 'email';
- const sendEmail = () => RocketChat.sendEmailCode();
+ const sendEmail = () => Services.sendEmailCode();
useDeepCompareEffect(() => {
if (!isEmpty(data)) {
diff --git a/app/containers/UIKit/DatePicker.tsx b/app/containers/UIKit/DatePicker.tsx
index 59fb576f1..8e674996f 100644
--- a/app/containers/UIKit/DatePicker.tsx
+++ b/app/containers/UIKit/DatePicker.tsx
@@ -9,7 +9,7 @@ import Button from '../Button';
import { textParser } from './utils';
import { themes } from '../../lib/constants';
import sharedStyles from '../../views/Styles';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { isAndroid } from '../../utils/deviceInfo';
import { useTheme } from '../../theme';
import ActivityIndicator from '../ActivityIndicator';
diff --git a/app/containers/UIKit/MultiSelect/Chips.tsx b/app/containers/UIKit/MultiSelect/Chips.tsx
index 8bd43f8f9..72604f66c 100644
--- a/app/containers/UIKit/MultiSelect/Chips.tsx
+++ b/app/containers/UIKit/MultiSelect/Chips.tsx
@@ -5,7 +5,7 @@ import FastImage from '@rocket.chat/react-native-fast-image';
import { themes } from '../../../lib/constants';
import { textParser } from '../utils';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../CustomIcon';
import styles from './styles';
import { IItemData } from '.';
import { TSupportedThemes } from '../../../theme';
diff --git a/app/containers/UIKit/MultiSelect/Input.tsx b/app/containers/UIKit/MultiSelect/Input.tsx
index 3de171636..e1b1e9fb2 100644
--- a/app/containers/UIKit/MultiSelect/Input.tsx
+++ b/app/containers/UIKit/MultiSelect/Input.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../CustomIcon';
import { themes } from '../../../lib/constants';
import ActivityIndicator from '../../ActivityIndicator';
import styles from './styles';
diff --git a/app/containers/UIKit/Overflow.tsx b/app/containers/UIKit/Overflow.tsx
index e3041370c..dfb49b6c1 100644
--- a/app/containers/UIKit/Overflow.tsx
+++ b/app/containers/UIKit/Overflow.tsx
@@ -3,7 +3,7 @@ import { FlatList, StyleSheet, Text } from 'react-native';
import Popover from 'react-native-popover-view';
import Touchable from 'react-native-platform-touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import ActivityIndicator from '../ActivityIndicator';
import { themes } from '../../lib/constants';
import { useTheme } from '../../theme';
diff --git a/app/containers/UIKit/Select.tsx b/app/containers/UIKit/Select.tsx
index 1e00ecc8b..4fe9500ea 100644
--- a/app/containers/UIKit/Select.tsx
+++ b/app/containers/UIKit/Select.tsx
@@ -4,7 +4,7 @@ import RNPickerSelect from 'react-native-picker-select';
import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { textParser } from './utils';
import { isAndroid, isIOS } from '../../utils/deviceInfo';
import ActivityIndicator from '../ActivityIndicator';
diff --git a/app/containers/UserItem.tsx b/app/containers/UserItem.tsx
index 6921e5ce0..952ea7928 100644
--- a/app/containers/UserItem.tsx
+++ b/app/containers/UserItem.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Pressable, StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native';
import Avatar from './Avatar';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon, TIconsName } from './CustomIcon';
import sharedStyles from '../views/Styles';
import { themes } from '../lib/constants';
import { isIOS } from '../utils/deviceInfo';
@@ -46,7 +46,7 @@ interface IUserItem {
testID: string;
onLongPress?: () => void;
style?: StyleProp;
- icon?: string | null;
+ icon?: TIconsName | null;
theme: TSupportedThemes;
}
@@ -71,7 +71,7 @@ const UserItem = ({ name, username, onPress, testID, onLongPress, style, icon, t
@{username}
- {icon ? : null}
+ {icon ? : null}
);
diff --git a/app/containers/message/Audio.tsx b/app/containers/message/Audio.tsx
index cec73b651..d356b7c9c 100644
--- a/app/containers/message/Audio.tsx
+++ b/app/containers/message/Audio.tsx
@@ -9,7 +9,7 @@ import { Sound } from 'expo-av/build/Audio/Sound';
import Touchable from './Touchable';
import Markdown from '../markdown';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
import { isAndroid, isIOS } from '../../utils/deviceInfo';
diff --git a/app/containers/message/Broadcast.tsx b/app/containers/message/Broadcast.tsx
index c2e08bf94..72c8d7beb 100644
--- a/app/containers/message/Broadcast.tsx
+++ b/app/containers/message/Broadcast.tsx
@@ -2,7 +2,7 @@ import React, { useContext } from 'react';
import { Text, View } from 'react-native';
import Touchable from './Touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import styles from './styles';
import { BUTTON_HIT_SLOP } from './utils';
import I18n from '../../i18n';
diff --git a/app/containers/message/CallButton.tsx b/app/containers/message/CallButton.tsx
index 240e56189..1223a7bc7 100644
--- a/app/containers/message/CallButton.tsx
+++ b/app/containers/message/CallButton.tsx
@@ -5,7 +5,7 @@ import Touchable from './Touchable';
import { BUTTON_HIT_SLOP } from './utils';
import styles from './styles';
import I18n from '../../i18n';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { themes } from '../../lib/constants';
import { IMessageCallButton } from './interfaces';
import { useTheme } from '../../theme';
diff --git a/app/containers/message/Components/CollapsibleQuote/index.tsx b/app/containers/message/Components/CollapsibleQuote/index.tsx
index 5d47e47dd..523beca9f 100644
--- a/app/containers/message/Components/CollapsibleQuote/index.tsx
+++ b/app/containers/message/Components/CollapsibleQuote/index.tsx
@@ -6,7 +6,7 @@ import { StyleSheet, Text, View } from 'react-native';
import { themes } from '../../../../lib/constants';
import { IAttachment } from '../../../../definitions/IAttachment';
import { TGetCustomEmoji } from '../../../../definitions/IEmoji';
-import { CustomIcon } from '../../../../lib/Icons';
+import { CustomIcon } from '../../../CustomIcon';
import { useTheme } from '../../../../theme';
import sharedStyles from '../../../../views/Styles';
import Markdown from '../../../markdown';
diff --git a/app/containers/message/Discussion.tsx b/app/containers/message/Discussion.tsx
index 1e6e9ed55..a466cf045 100644
--- a/app/containers/message/Discussion.tsx
+++ b/app/containers/message/Discussion.tsx
@@ -5,7 +5,7 @@ import Touchable from './Touchable';
import { BUTTON_HIT_SLOP, formatMessageCount } from './utils';
import styles from './styles';
import I18n from '../../i18n';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { DISCUSSION } from './constants';
import { themes } from '../../lib/constants';
import MessageContext from './Context';
diff --git a/app/containers/message/Encrypted.tsx b/app/containers/message/Encrypted.tsx
index adfa54487..18840726d 100644
--- a/app/containers/message/Encrypted.tsx
+++ b/app/containers/message/Encrypted.tsx
@@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import Touchable from './Touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { BUTTON_HIT_SLOP } from './utils';
import MessageContext from './Context';
import styles from './styles';
diff --git a/app/containers/message/MessageError.tsx b/app/containers/message/MessageError.tsx
index b420405e3..d63ec572c 100644
--- a/app/containers/message/MessageError.tsx
+++ b/app/containers/message/MessageError.tsx
@@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import Touchable from './Touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import styles from './styles';
import { BUTTON_HIT_SLOP } from './utils';
import { themes } from '../../lib/constants';
diff --git a/app/containers/message/Reactions.tsx b/app/containers/message/Reactions.tsx
index 008ee7b4e..bfc653939 100644
--- a/app/containers/message/Reactions.tsx
+++ b/app/containers/message/Reactions.tsx
@@ -2,7 +2,7 @@ import React, { useContext } from 'react';
import { Text, View } from 'react-native';
import Touchable from './Touchable';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import styles from './styles';
import Emoji from './Emoji';
import { BUTTON_HIT_SLOP } from './utils';
diff --git a/app/containers/message/ReadReceipt.tsx b/app/containers/message/ReadReceipt.tsx
index 5556b781f..d26004839 100644
--- a/app/containers/message/ReadReceipt.tsx
+++ b/app/containers/message/ReadReceipt.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import styles from './styles';
import { useTheme } from '../../theme';
diff --git a/app/containers/message/RepliedThread.tsx b/app/containers/message/RepliedThread.tsx
index b6d4f5939..502cb7c41 100644
--- a/app/containers/message/RepliedThread.tsx
+++ b/app/containers/message/RepliedThread.tsx
@@ -1,7 +1,7 @@
import React, { memo, useEffect, useState } from 'react';
import { View } from 'react-native';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import styles from './styles';
import { themes } from '../../lib/constants';
import I18n from '../../i18n';
diff --git a/app/containers/message/Video.tsx b/app/containers/message/Video.tsx
index 69870c7eb..52d85d720 100644
--- a/app/containers/message/Video.tsx
+++ b/app/containers/message/Video.tsx
@@ -5,7 +5,7 @@ import { dequal } from 'dequal';
import Touchable from './Touchable';
import Markdown from '../markdown';
import { isIOS } from '../../utils/deviceInfo';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../CustomIcon';
import { themes } from '../../lib/constants';
import MessageContext from './Context';
import { fileDownload } from '../../utils/fileDownload';
diff --git a/app/containers/message/index.tsx b/app/containers/message/index.tsx
index 4facaf9e5..a389d3127 100644
--- a/app/containers/message/index.tsx
+++ b/app/containers/message/index.tsx
@@ -5,11 +5,10 @@ import { Subscription } from 'rxjs';
import Message from './Message';
import MessageContext from './Context';
import debounce from '../../utils/debounce';
-import { SYSTEM_MESSAGES, getMessageTranslation } from './utils';
+import { getMessageTranslation } from './utils';
import { TSupportedThemes, withTheme } from '../../theme';
import openLink from '../../utils/openLink';
-import { TGetCustomEmoji } from '../../definitions/IEmoji';
-import { IAttachment, TAnyMessageModel } from '../../definitions';
+import { IAttachment, TAnyMessageModel, TGetCustomEmoji } from '../../definitions';
import { IRoomInfoParam } from '../../views/SearchMessagesView';
import { E2E_MESSAGE_TYPE, E2E_STATUS, messagesStatus } from '../../lib/constants';
@@ -31,6 +30,7 @@ interface IMessageContainerProps {
Message_GroupingPeriod?: number;
isReadReceiptEnabled?: boolean;
isThreadRoom: boolean;
+ isSystemMessage?: boolean;
useRealName?: boolean;
autoTranslateRoom?: boolean;
autoTranslateLanguage?: string;
@@ -254,9 +254,12 @@ class MessageContainer extends React.Component {
const { username } = author;
+
if (type === 'rm') {
return I18n.t('Message_removed');
}
@@ -198,13 +231,37 @@ export const getInfoMessage = ({ type, role, msg, author, comment }: TInfoMessag
if (type === 'user-removed-room-from-team') {
return I18n.t('Removed__roomName__from_this_team', { roomName: msg });
}
+ if (type === 'room-disallowed-reacting') {
+ return I18n.t('Room_disallowed_reacting', { userBy: username });
+ }
+ if (type === 'room-allowed-reacting') {
+ return I18n.t('Room_allowed_reacting', { userBy: username });
+ }
+ if (type === 'room-set-read-only') {
+ return I18n.t('Room_set_read_only', { userBy: username });
+ }
+ if (type === 'room-removed-read-only') {
+ return I18n.t('Room_removed_read_only', { userBy: username });
+ }
if (type === 'omnichannel_placed_chat_on_hold') {
return I18n.t('Omnichannel_placed_chat_on_hold', { comment });
}
if (type === 'omnichannel_on_hold_chat_resumed') {
return I18n.t('Omnichannel_on_hold_chat_resumed', { comment });
}
- return '';
+ if (type === 'command') {
+ return I18n.t('Livechat_transfer_return_to_the_queue');
+ }
+ if (type === 'livechat-started') {
+ return I18n.t('Chat_started');
+ }
+ if (type === 'livechat-close') {
+ return I18n.t('Conversation_closed');
+ }
+ if (type === 'livechat_transfer_history') {
+ return I18n.t('New_chat_transfer', { agent: username });
+ }
+ return I18n.t('Unsupported_system_message');
};
export const getMessageTranslation = (message: TMessageModel, autoTranslateLanguage: string) => {
diff --git a/app/definitions/IAssetsFavicon512.ts b/app/definitions/IAssetsFavicon512.ts
new file mode 100644
index 000000000..553160ecd
--- /dev/null
+++ b/app/definitions/IAssetsFavicon512.ts
@@ -0,0 +1,4 @@
+export interface IAssetsFavicon512 {
+ url?: string;
+ defaultUrl: string;
+}
diff --git a/app/definitions/ICannedResponse.ts b/app/definitions/ICannedResponse.ts
index fcf531c0c..d7d9fd347 100644
--- a/app/definitions/ICannedResponse.ts
+++ b/app/definitions/ICannedResponse.ts
@@ -1,23 +1,3 @@
-export interface IDepartment {
- _id: string;
- enabled: boolean;
- name: string;
- description: string;
- showOnRegistration: boolean;
- showOnOfflineForm: boolean;
- requestTagBeforeClosingChat: boolean;
- email: string;
- chatClosingTags: string[];
- offlineMessageChannelName: string;
- maxNumberSimultaneousChat: number;
- abandonedRoomsCloseCustomMessage: string;
- waitingQueueMessage: string;
- departmentsAllowedToForward: string;
- _updatedAt: Date;
- numAgents: number;
- ancestors: string[];
-}
-
export interface ICannedResponse {
_id: string;
shortcut: string;
diff --git a/app/definitions/ICustomEmoji.ts b/app/definitions/ICustomEmoji.ts
deleted file mode 100644
index 348e66098..000000000
--- a/app/definitions/ICustomEmoji.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import Model from '@nozbe/watermelondb/Model';
-
-export interface ICustomEmoji {
- _id: string;
- name?: string;
- aliases?: string[];
- extension: string;
- _updatedAt: Date;
-}
-
-export type TCustomEmojiModel = ICustomEmoji & Model;
diff --git a/app/definitions/IDataSelect.ts b/app/definitions/IDataSelect.ts
new file mode 100644
index 000000000..44d381cb8
--- /dev/null
+++ b/app/definitions/IDataSelect.ts
@@ -0,0 +1,4 @@
+import { TSubscriptionModel } from './ISubscription';
+
+export type TDataSelect = Pick &
+ Partial>;
diff --git a/app/definitions/IEmoji.ts b/app/definitions/IEmoji.ts
index 3896aa5e2..38bbf2351 100644
--- a/app/definitions/IEmoji.ts
+++ b/app/definitions/IEmoji.ts
@@ -1,31 +1,43 @@
-// TODO: evaluate unification with IEmoji
+import Model from '@nozbe/watermelondb/Model';
+import { StyleProp } from 'react-native';
+import { ImageStyle } from '@rocket.chat/react-native-fast-image';
+
export interface IEmoji {
- content?: string;
- name?: string;
- extension?: string;
- isCustom?: boolean;
+ content: string;
+ name: string;
+ extension: string;
+ isCustom: boolean;
+ count?: number;
+}
+
+export interface ICustomEmojis {
+ [key: string]: Pick;
}
export interface ICustomEmoji {
baseUrl?: string;
emoji: IEmoji;
- style: any;
+ style: StyleProp;
+}
+
+export interface ICustomEmojiModel {
+ _id: string;
+ name?: string;
+ aliases?: string[];
+ extension: string;
+ _updatedAt: Date;
}
export interface IEmojiCategory {
baseUrl: string;
emojis: IEmoji[];
- onEmojiSelected: Function;
- emojisPerRow: number;
- width: number;
- style: any;
+ onEmojiSelected: (emoji: IEmoji) => void;
+ width: number | null;
+ style: StyleProp;
tabLabel: string;
}
-// TODO: copied from reducers/customEmojis. We can unify later.
-export interface IReduxEmoji {
- name: string;
- extension: any;
-}
-
export type TGetCustomEmoji = (name: string) => any;
+
+export type TFrequentlyUsedEmojiModel = IEmoji & Model;
+export type TCustomEmojiModel = ICustomEmojiModel & Model;
diff --git a/app/definitions/IFrequentlyUsedEmoji.ts b/app/definitions/IFrequentlyUsedEmoji.ts
deleted file mode 100644
index 2602466ce..000000000
--- a/app/definitions/IFrequentlyUsedEmoji.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import Model from '@nozbe/watermelondb/Model';
-
-// TODO: evaluate unification with IEmoji
-export interface IFrequentlyUsedEmoji {
- content?: string;
- extension?: string;
- isCustom: boolean;
- count: number;
-}
-
-export type TFrequentlyUsedEmojiModel = IFrequentlyUsedEmoji & Model;
diff --git a/app/definitions/ILivechatDepartment.ts b/app/definitions/ILivechatDepartment.ts
index a3e67e9f2..beb54bfb0 100644
--- a/app/definitions/ILivechatDepartment.ts
+++ b/app/definitions/ILivechatDepartment.ts
@@ -13,6 +13,11 @@ export interface ILivechatDepartment {
_updatedAt?: Date;
businessHourId?: string;
fallbackForwardDepartment?: string;
+ maxNumberSimultaneousChat: number;
+ abandonedRoomsCloseCustomMessage: string;
+ waitingQueueMessage: string;
+ departmentsAllowedToForward: string;
+ ancestors: string[];
// extra optional fields
[k: string]: any;
}
diff --git a/app/definitions/IProfile.ts b/app/definitions/IProfile.ts
new file mode 100644
index 000000000..f75885c09
--- /dev/null
+++ b/app/definitions/IProfile.ts
@@ -0,0 +1,31 @@
+import React from 'react';
+
+export interface IProfileParams {
+ name: string;
+ username: string;
+ email: string | null;
+ newPassword: string;
+ currentPassword: string;
+}
+
+export interface IAvatarButton {
+ key: string;
+ child: React.ReactNode;
+ onPress: () => void;
+ disabled: boolean;
+}
+
+export interface IAvatar {
+ data: {} | string | null;
+ url?: string;
+ contentType?: string;
+ service?: any;
+}
+
+export interface IAvatarSuggestion {
+ [service: string]: {
+ url: string;
+ blob: string;
+ contentType: string;
+ };
+}
diff --git a/app/definitions/IProfileViewInterfaces.ts b/app/definitions/IProfileViewInterfaces.ts
deleted file mode 100644
index ce41a1e9e..000000000
--- a/app/definitions/IProfileViewInterfaces.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { StackNavigationProp } from '@react-navigation/stack';
-import React from 'react';
-
-import { TSupportedThemes } from '../theme';
-import { ProfileStackParamList } from '../stacks/types';
-import { IUser } from './IUser';
-
-export interface IParams {
- name: string;
- username: string;
- email: string | null;
- newPassword: string;
- currentPassword: string;
-}
-
-export interface IAvatarButton {
- key: string;
- child: React.ReactNode;
- onPress: () => void;
- disabled: boolean;
-}
-
-export interface INavigationOptions {
- navigation: StackNavigationProp;
- isMasterDetail?: boolean;
-}
-
-export interface IProfileViewProps {
- user: IUser;
- baseUrl: string;
- Accounts_AllowEmailChange: boolean;
- Accounts_AllowPasswordChange: boolean;
- Accounts_AllowRealNameChange: boolean;
- Accounts_AllowUserAvatarChange: boolean;
- Accounts_AllowUsernameChange: boolean;
- Accounts_CustomFields: string;
- setUser: Function;
- theme: TSupportedThemes;
-}
-
-export interface IAvatar {
- data: {} | string | null;
- url?: string;
- contentType?: string;
- service?: any;
-}
-
-export interface IAvatarSuggestion {
- [service: string]: {
- url: string;
- blob: string;
- contentType: string;
- };
-}
-
-export interface IProfileViewState {
- saving: boolean;
- name: string;
- username: string;
- email: string | null;
- newPassword: string | null;
- currentPassword: string | null;
- avatarUrl: string | null;
- avatar: IAvatar;
- avatarSuggestions: IAvatarSuggestion;
- customFields: {
- [key: string | number]: string;
- };
-}
diff --git a/app/definitions/IRoom.ts b/app/definitions/IRoom.ts
index ed6f3d2b0..40f9b290f 100644
--- a/app/definitions/IRoom.ts
+++ b/app/definitions/IRoom.ts
@@ -142,6 +142,11 @@ export interface IServerRoom extends IRocketChatRecord {
encrypted?: boolean;
topic?: any;
+ username?: string;
+ nickname?: string;
+ federation?: any;
+ roomsCount?: number;
+
u: Pick;
uids: Array;
@@ -205,9 +210,12 @@ export interface IServerRoom extends IRocketChatRecord {
departmentId?: string;
livechatData?: any;
tags?: string[];
+
+ isLastOwner?: boolean;
}
export interface IRoomNotifications {
+ [key: string]: any;
disableNotifications?: boolean;
muteGroupMentions?: boolean;
hideUnreadStatus?: boolean;
@@ -216,3 +224,5 @@ export interface IRoomNotifications {
mobilePushNotifications?: TNotifications;
emailNotifications?: TNotifications;
}
+
+export type TRoomNotificationsModel = IRoomNotifications & Model;
diff --git a/app/definitions/ISearch.ts b/app/definitions/ISearch.ts
index e4ef9de62..35cc4bd15 100644
--- a/app/definitions/ISearch.ts
+++ b/app/definitions/ISearch.ts
@@ -6,7 +6,7 @@ export interface ISearchLocal {
name: string;
t: string;
fname: string;
- encrypted: boolean | null;
+ encrypted: boolean;
lastMessage?: ILastMessage;
}
diff --git a/app/definitions/index.ts b/app/definitions/index.ts
index 9064babf4..a0d9d3ea9 100644
--- a/app/definitions/index.ts
+++ b/app/definitions/index.ts
@@ -12,8 +12,7 @@ export * from './IRoom';
export * from './IMessage';
export * from './IThread';
export * from './IThreadMessage';
-export * from './ICustomEmoji';
-export * from './IFrequentlyUsedEmoji';
+export * from './IEmoji';
export * from './IUpload';
export * from './ISettings';
export * from './IRole';
@@ -29,6 +28,7 @@ export * from './IUrl';
export * from './ICredentials';
export * from './ISearch';
export * from './TUserStatus';
+export * from './IProfile';
export interface IBaseScreen, S extends string> {
navigation: StackNavigationProp;
diff --git a/app/definitions/navigationTypes.ts b/app/definitions/navigationTypes.ts
index 6e2020943..960b35b5d 100644
--- a/app/definitions/navigationTypes.ts
+++ b/app/definitions/navigationTypes.ts
@@ -1,8 +1,8 @@
import { NavigatorScreenParams } from '@react-navigation/core';
import { StackNavigationOptions } from '@react-navigation/stack';
-import { ISubscription } from './ISubscription';
-import { IServer } from './IServer';
+import { TSubscriptionModel } from './ISubscription';
+import { TServerModel } from './IServer';
import { IAttachment } from './IAttachment';
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
import { OutsideParamList, InsideStackParamList } from '../stacks/types';
@@ -37,10 +37,10 @@ export type ShareInsideStackParamList = {
attachments: IAttachment[];
isShareView?: boolean;
isShareExtension: boolean;
- serverInfo: IServer;
+ serverInfo: TServerModel;
text: string;
- room: ISubscription;
- thread: any; // TODO: Change
+ room: TSubscriptionModel;
+ thread?: any; // TODO: Change
};
SelectServerView: undefined;
};
diff --git a/app/definitions/rest/v1/users.ts b/app/definitions/rest/v1/users.ts
index 898799102..9015fd349 100644
--- a/app/definitions/rest/v1/users.ts
+++ b/app/definitions/rest/v1/users.ts
@@ -1,4 +1,4 @@
-import { IParams } from '../../IProfileViewInterfaces';
+import { IProfileParams } from '../../IProfile';
import type { ITeam } from '../../ITeam';
import type { IUser } from '../../IUser';
import { INotificationPreferences, IUserPreferences, IUserRegistered } from '../../IUser';
@@ -39,7 +39,10 @@ export type UsersEndpoints = {
POST: (params: { status: string; message: string }) => {};
};
'users.updateOwnBasicInfo': {
- POST: (params: { data: IParams | Pick; customFields?: { [key: string | number]: string } }) => {
+ POST: (params: {
+ data: IProfileParams | Pick;
+ customFields?: { [key: string | number]: string };
+ }) => {
user: IUser;
};
};
diff --git a/app/ee/omnichannel/containers/OmnichannelHeader/OmnichannelQueue.tsx b/app/ee/omnichannel/containers/OmnichannelHeader/OmnichannelQueue.tsx
index b1bbe98cc..7ce8b2320 100644
--- a/app/ee/omnichannel/containers/OmnichannelHeader/OmnichannelQueue.tsx
+++ b/app/ee/omnichannel/containers/OmnichannelHeader/OmnichannelQueue.tsx
@@ -3,7 +3,7 @@ import { View, Text } from 'react-native';
import { useTheme } from '../../../../theme';
import { themes } from '../../../../lib/constants';
-import { CustomIcon } from '../../../../lib/Icons';
+import { CustomIcon } from '../../../../containers/CustomIcon';
import * as List from '../../../../containers/List';
import styles from './styles';
import UnreadBadge from '../../../../containers/UnreadBadge';
diff --git a/app/ee/omnichannel/containers/OmnichannelHeader/index.tsx b/app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
index d0496c855..eed3f478a 100644
--- a/app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
+++ b/app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
@@ -5,12 +5,12 @@ import * as List from '../../../../containers/List';
import styles from './styles';
import { SWITCH_TRACK_COLOR, themes } from '../../../../lib/constants';
import { useTheme } from '../../../../theme';
-import RocketChat from '../../../../lib/rocketchat';
import { IUser } from '../../../../definitions/IUser';
import { showConfirmationAlert } from '../../../../utils/info';
import I18n from '../../../../i18n';
import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../lib';
import OmnichannelQueue from './OmnichannelQueue';
+import { isOmnichannelModuleAvailable } from '../../../../lib/methods';
interface IOmnichannelStatus {
searching: boolean;
@@ -28,7 +28,7 @@ const OmnichannelStatus = memo(({ searching, goQueue, queueSize, user }: IOmnich
setStatus(isOmnichannelStatusAvailable(user));
}, [user.statusLivechat]);
- if (searching || !(RocketChat.isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) {
+ if (searching || !(isOmnichannelModuleAvailable() && user?.roles?.includes('livechat-agent'))) {
return null;
}
diff --git a/app/ee/omnichannel/lib/subscriptions/inquiry.ts b/app/ee/omnichannel/lib/subscriptions/inquiry.ts
index e9358133e..a918e48eb 100644
--- a/app/ee/omnichannel/lib/subscriptions/inquiry.ts
+++ b/app/ee/omnichannel/lib/subscriptions/inquiry.ts
@@ -1,9 +1,10 @@
import log from '../../../../utils/log';
import { store } from '../../../../lib/store/auxStore';
-import RocketChat from '../../../../lib/rocketchat';
import { inquiryQueueAdd, inquiryQueueRemove, inquiryQueueUpdate, inquiryRequest } from '../../actions/inquiry';
import sdk from '../../../../lib/services/sdk';
import { IOmnichannelRoom } from '../../../../definitions';
+import { hasRole } from '../../../../lib/methods';
+import { Services } from '../../../../lib/services';
interface IArgsQueueOmnichannel extends IOmnichannelRoom {
type: string;
@@ -81,11 +82,11 @@ export default function subscribeInquiry() {
throw new Error('inquiry: @subscribeInquiry user.id not found');
}
- RocketChat.getAgentDepartments(user.id).then(result => {
+ Services.getAgentDepartments(user.id).then(result => {
if (result.success) {
const { departments } = result;
- if (!departments.length || RocketChat.hasRole('livechat-manager')) {
+ if (!departments.length || hasRole('livechat-manager')) {
sdk.subscribe(streamTopic, 'public').catch((e: unknown) => console.log(e));
}
diff --git a/app/ee/omnichannel/sagas/inquiry.js b/app/ee/omnichannel/sagas/inquiry.js
index b9bec6b41..ec728e537 100644
--- a/app/ee/omnichannel/sagas/inquiry.js
+++ b/app/ee/omnichannel/sagas/inquiry.js
@@ -1,14 +1,14 @@
import { put, select, takeLatest } from 'redux-saga/effects';
import * as types from '../../../actions/actionsTypes';
-import RocketChat from '../../../lib/rocketchat';
+import { Services } from '../../../lib/services';
import EventEmitter from '../../../utils/events';
import { inquiryFailure, inquirySetEnabled, inquirySuccess } from '../actions/inquiry';
import { getInquiriesQueued, isOmnichannelStatusAvailable } from '../lib';
const handleRequest = function* handleRequest() {
try {
- const routingConfig = yield RocketChat.getRoutingConfig();
+ const routingConfig = yield Services.getRoutingConfig();
const user = yield select(state => state.login.user);
// if routingConfig showQueue is enabled and omnichannel is enabled
const showQueue = routingConfig.showQueue && isOmnichannelStatusAvailable(user);
diff --git a/app/ee/omnichannel/views/QueueListView.tsx b/app/ee/omnichannel/views/QueueListView.tsx
index 6b60b59a1..9d6eab96a 100644
--- a/app/ee/omnichannel/views/QueueListView.tsx
+++ b/app/ee/omnichannel/views/QueueListView.tsx
@@ -15,7 +15,6 @@ import SafeAreaView from '../../../containers/SafeAreaView';
import StatusBar from '../../../containers/StatusBar';
import { goRoom } from '../../../utils/goRoom';
import * as HeaderButton from '../../../containers/HeaderButton';
-import RocketChat from '../../../lib/rocketchat';
import { events, logEvent } from '../../../utils/log';
import { getInquiryQueueSelector } from '../selectors/inquiry';
import { IOmnichannelRoom, IApplicationState } from '../../../definitions';
@@ -23,6 +22,7 @@ import { DisplayMode, MAX_SIDEBAR_WIDTH, themes } from '../../../lib/constants';
import { ChatsStackParamList } from '../../../stacks/types';
import { MasterDetailInsideStackParamList } from '../../../stacks/MasterDetailStack/types';
import { TSettingsValues } from '../../../reducers/settings';
+import { getRoomAvatar, getRoomTitle, getUidDirectMessage } from '../../../lib/methods';
interface INavigationOptions {
isMasterDetail: boolean;
@@ -98,12 +98,6 @@ class QueueListView extends React.Component {
});
};
- getRoomTitle = (item: IOmnichannelRoom) => RocketChat.getRoomTitle(item);
-
- getRoomAvatar = (item: IOmnichannelRoom) => RocketChat.getRoomAvatar(item);
-
- getUidDirectMessage = (room: IOmnichannelRoom) => RocketChat.getUidDirectMessage(room);
-
renderItem: ListRenderItem = ({ item }) => {
const {
user: { id: userId, username, token },
@@ -115,7 +109,7 @@ class QueueListView extends React.Component {
showAvatar,
displayMode
} = this.props;
- const id = this.getUidDirectMessage(item);
+ const id = getUidDirectMessage(item);
return (
{
testID={`queue-list-view-item-${item.name}`}
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
useRealName={useRealName}
- getRoomTitle={this.getRoomTitle}
- getRoomAvatar={this.getRoomAvatar}
+ getRoomTitle={getRoomTitle}
+ getRoomAvatar={getRoomAvatar}
visitor={item.v}
swipeEnabled={false}
showAvatar={showAvatar}
diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json
index c06a4ef00..a89c45e31 100644
--- a/app/i18n/locales/en.json
+++ b/app/i18n/locales/en.json
@@ -132,6 +132,7 @@
"Channel_Name": "Channel Name",
"Channels": "Channels",
"Chats": "Chats",
+ "Chat_started": "Chat started",
"Call_already_ended": "Call already ended!",
"Clear_cookies_alert": "Do you want to clear all cookies?",
"Clear_cookies_desc": "This action will clear all login cookies, allowing you to login into other accounts.",
@@ -149,6 +150,7 @@
"Choose_where_you_want_links_be_opened": "Choose where you want links be opened",
"Code": "Code",
"Code_or_password_invalid": "Code or password invalid",
+ "Conversation_closed": "Conversation closed",
"Collaborative": "Collaborative",
"Confirm": "Confirm",
"Connect": "Connect",
@@ -301,6 +303,7 @@
"License": "License",
"Livechat": "Livechat",
"Livechat_edit": "Livechat edit",
+ "Livechat_transfer_return_to_the_queue": "returned the chat to the queue",
"Login": "Login",
"Login_error": "Your credentials were rejected! Please try again.",
"Login_with": "Login with",
@@ -334,6 +337,7 @@
"N_channels": "{{n}} channels",
"Name": "Name",
"Never": "Never",
+ "New_chat_transfer": "New Chat Transfer: {{agent}} returned the chat to the queue",
"New_Message": "New Message",
"New_Password": "New Password",
"New_Server": "New Server",
@@ -449,6 +453,10 @@
"Room_Info": "Room Info",
"Room_Members": "Room Members",
"Room_name_changed": "Room name changed to: {{name}} by {{userBy}}",
+ "Room_disallowed_reacting": "Room disallowed reacting by {{userBy}}",
+ "Room_allowed_reacting": "Room allowed reacting by {{userBy}}",
+ "Room_set_read_only": "Room set read only by {{userBy}}",
+ "Room_removed_read_only": "Room removed read only by {{userBy}}",
"SAVE": "SAVE",
"Save_Changes": "Save Changes",
"Save": "Save",
@@ -547,6 +555,7 @@
"Unread": "Unread",
"Unread_on_top": "Unread on top",
"Unstar": "Unstar",
+ "Unsupported_system_message": "Unsupported system message",
"Updating": "Updating...",
"Uploading": "Uploading",
"Upload_file_question_mark": "Upload file?",
diff --git a/app/index.tsx b/app/index.tsx
index 1dd42188c..920db27fe 100644
--- a/app/index.tsx
+++ b/app/index.tsx
@@ -1,36 +1,36 @@
import React from 'react';
import { Dimensions, Linking } from 'react-native';
import { AppearanceProvider } from 'react-native-appearance';
-import { Provider } from 'react-redux';
import { KeyCommandsEmitter } from 'react-native-keycommands';
+import { initialWindowMetrics, SafeAreaProvider } from 'react-native-safe-area-context';
import RNScreens from 'react-native-screens';
-import { SafeAreaProvider, initialWindowMetrics } from 'react-native-safe-area-context';
+import { Provider } from 'react-redux';
-import { getTheme, initialTheme, newThemeState, subscribeTheme, unsubscribeTheme } from './utils/theme';
-import EventEmitter from './utils/events';
import { appInit, appInitLocalSettings, setMasterDetail as setMasterDetailAction } from './actions/app';
import { deepLinkingOpen } from './actions/deepLinking';
+import AppContainer from './AppContainer';
+import { KEY_COMMAND } from './commands';
+import { ActionSheetProvider } from './containers/ActionSheet';
+import InAppNotification from './containers/InAppNotification';
+import Toast from './containers/Toast';
+import TwoFactor from './containers/TwoFactor';
+import { ICommand } from './definitions/ICommand';
+import { IThemePreference } from './definitions/ITheme';
+import { DimensionsContext } from './dimensions';
+import { colors, isFDroidBuild, MIN_WIDTH_MASTER_DETAIL_LAYOUT, themes } from './lib/constants';
+import { getAllowAnalyticsEvents, getAllowCrashReport } from './lib/methods';
import parseQuery from './lib/methods/helpers/parseQuery';
import { initializePushNotifications, onNotification } from './lib/notifications';
-import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './utils/log';
-import { ThemeContext, TSupportedThemes } from './theme';
-import { DimensionsContext } from './dimensions';
-import RocketChat from './lib/rocketchat';
-import { isTablet } from './utils/deviceInfo';
-import { KEY_COMMAND } from './commands';
-import AppContainer from './AppContainer';
-import TwoFactor from './containers/TwoFactor';
-import ScreenLockedView from './views/ScreenLockedView';
-import ChangePasscodeView from './views/ChangePasscodeView';
-import Toast from './containers/Toast';
-import InAppNotification from './containers/InAppNotification';
-import { ActionSheetProvider } from './containers/ActionSheet';
-import debounce from './utils/debounce';
-import { isFDroidBuild, MIN_WIDTH_MASTER_DETAIL_LAYOUT, colors, themes } from './lib/constants';
-import { IThemePreference } from './definitions/ITheme';
-import { ICommand } from './definitions/ICommand';
import store from './lib/store';
import { initStore } from './lib/store/auxStore';
+import { ThemeContext, TSupportedThemes } from './theme';
+import debounce from './utils/debounce';
+import { isTablet } from './utils/deviceInfo';
+import EventEmitter from './utils/events';
+import { toggleAnalyticsEventsReport, toggleCrashErrorsReport } from './utils/log';
+import { getTheme, initialTheme, newThemeState, subscribeTheme, unsubscribeTheme } from './utils/theme';
+import ChangePasscodeView from './views/ChangePasscodeView';
+import ScreenLockedView from './views/ScreenLockedView';
RNScreens.enableScreens();
initStore(store);
@@ -193,10 +193,10 @@ export default class Root extends React.Component<{}, IState> {
};
initCrashReport = () => {
- RocketChat.getAllowCrashReport().then(allowCrashReport => {
+ getAllowCrashReport().then(allowCrashReport => {
toggleCrashErrorsReport(allowCrashReport);
});
- RocketChat.getAllowAnalyticsEvents().then(allowAnalyticsEvents => {
+ getAllowAnalyticsEvents().then(allowAnalyticsEvents => {
toggleAnalyticsEventsReport(allowAnalyticsEvents);
});
};
diff --git a/app/lib/Icons.js b/app/lib/Icons.js
deleted file mode 100644
index 839ccca87..000000000
--- a/app/lib/Icons.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { createIconSetFromIcoMoon } from 'react-native-vector-icons';
-
-import icoMoonConfig from './selection.json';
-
-const CustomIcon = createIconSetFromIcoMoon(icoMoonConfig, 'custom', 'custom.ttf');
-
-export { CustomIcon };
diff --git a/app/lib/constants/keys.ts b/app/lib/constants/keys.ts
index ff48f2a05..7c41e0242 100644
--- a/app/lib/constants/keys.ts
+++ b/app/lib/constants/keys.ts
@@ -19,3 +19,6 @@ export const THEME_PREFERENCES_KEY = 'RC_THEME_PREFERENCES_KEY';
export const CRASH_REPORT_KEY = 'RC_CRASH_REPORT_KEY';
export const ANALYTICS_EVENTS_KEY = 'RC_ANALYTICS_EVENTS_KEY';
export const MIN_ROCKETCHAT_VERSION = '0.70.0';
+export const TOKEN_KEY = 'reactnativemeteor_usertoken';
+export const CURRENT_SERVER = 'currentServer';
+export const CERTIFICATE_KEY = 'RC_CERTIFICATE_KEY';
diff --git a/app/lib/encryption/encryption.ts b/app/lib/encryption/encryption.ts
index 4d0cd68fa..f24e483e7 100644
--- a/app/lib/encryption/encryption.ts
+++ b/app/lib/encryption/encryption.ts
@@ -3,7 +3,6 @@ import SimpleCrypto from 'react-native-simple-crypto';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import { Q, Model } from '@nozbe/watermelondb';
-import RocketChat from '../rocketchat';
import UserPreferences from '../methods/userPreferences';
import database from '../database';
import protectedFunction from '../methods/helpers/protectedFunction';
@@ -21,6 +20,7 @@ import {
E2E_RANDOM_PASSWORD_KEY,
E2E_STATUS
} from '../constants';
+import { Services } from '../services';
class Encryption {
ready: boolean;
@@ -141,10 +141,10 @@ class Encryption {
const encodedPrivateKey = await this.encodePrivateKey(EJSON.stringify(privateKey), password, userId);
// Send the new keys to the server
- await RocketChat.e2eSetUserPublicAndPrivateKeys(EJSON.stringify(publicKey), encodedPrivateKey);
+ await Services.e2eSetUserPublicAndPrivateKeys(EJSON.stringify(publicKey), encodedPrivateKey);
// Request e2e keys of all encrypted rooms
- await RocketChat.e2eRequestSubscriptionKeys();
+ await Services.e2eRequestSubscriptionKeys();
};
// Encode a private key before send it to the server
@@ -197,7 +197,7 @@ class Encryption {
const publicKey = UserPreferences.getString(`${server}-${E2E_PUBLIC_KEY}`);
// Send the new keys to the server
- await RocketChat.e2eSetUserPublicAndPrivateKeys(EJSON.stringify(publicKey), encodedPrivateKey);
+ await Services.e2eSetUserPublicAndPrivateKeys(EJSON.stringify(publicKey), encodedPrivateKey);
};
// get a encryption room instance
diff --git a/app/lib/encryption/room.ts b/app/lib/encryption/room.ts
index f2ed355d9..db8233445 100644
--- a/app/lib/encryption/room.ts
+++ b/app/lib/encryption/room.ts
@@ -4,7 +4,6 @@ import SimpleCrypto from 'react-native-simple-crypto';
import ByteBuffer from 'bytebuffer';
import { IMessage } from '../../definitions';
-import RocketChat from '../rocketchat';
import Deferred from '../../utils/deferred';
import debounce from '../../utils/debounce';
import database from '../database';
@@ -22,6 +21,7 @@ import {
import { Encryption } from './index';
import { IUser } from '../../definitions/IUser';
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../constants';
+import { Services } from '../services';
export default class EncryptionRoom {
ready: boolean;
@@ -134,7 +134,7 @@ export default class EncryptionRoom {
this.sessionKeyExportedString = EJSON.stringify(sessionKeyExported);
this.keyID = Base64.encode(this.sessionKeyExportedString).slice(0, 12);
- await RocketChat.e2eSetRoomKeyID(this.roomId, this.keyID);
+ await Services.e2eSetRoomKeyID(this.roomId, this.keyID);
await this.encryptRoomKey();
};
@@ -147,7 +147,7 @@ export default class EncryptionRoom {
// this will be called again and run once in 5 seconds
requestRoomKey = debounce(
async (e2eKeyId: string) => {
- await RocketChat.e2eRequestRoomKey(this.roomId, e2eKeyId);
+ await Services.e2eRequestRoomKey(this.roomId, e2eKeyId);
},
5000,
true
@@ -155,7 +155,7 @@ export default class EncryptionRoom {
// Create an encrypted key for this room based on users
encryptRoomKey = async () => {
- const result = await RocketChat.e2eGetUsersOfRoomWithoutKey(this.roomId);
+ const result = await Services.e2eGetUsersOfRoomWithoutKey(this.roomId);
if (result.success) {
const { users } = result;
await Promise.all(users.map(user => this.encryptRoomKeyForUser(user)));
@@ -168,7 +168,7 @@ export default class EncryptionRoom {
const { public_key: publicKey } = user.e2e;
const userKey = await SimpleCrypto.RSA.importKey(EJSON.parse(publicKey));
const encryptedUserKey = await SimpleCrypto.RSA.encrypt(this.sessionKeyExportedString as string, userKey);
- await RocketChat.e2eUpdateGroupKey(user?._id, this.roomId, this.keyID + encryptedUserKey);
+ await Services.e2eUpdateGroupKey(user?._id, this.roomId, this.keyID + encryptedUserKey);
}
};
diff --git a/app/lib/methods/actions.ts b/app/lib/methods/actions.ts
index 5425f49c8..edf63fc44 100644
--- a/app/lib/methods/actions.ts
+++ b/app/lib/methods/actions.ts
@@ -1,5 +1,4 @@
import { ITriggerAction, IUserInteraction, ModalActions } from '../../containers/UIKit/interfaces';
-import { TRocketChat } from '../../definitions/IRocketChat';
import EventEmitter from '../../utils/events';
import fetch from '../../utils/fetch';
import random from '../../utils/random';
@@ -82,10 +81,7 @@ export const handlePayloadUserInteraction = (
return ModalActions.CLOSE;
};
-export function triggerAction(
- this: TRocketChat,
- { type, actionId, appId, rid, mid, viewId, container, ...rest }: ITriggerAction
-) {
+export function triggerAction({ type, actionId, appId, rid, mid, viewId, container, ...rest }: ITriggerAction) {
return new Promise(async (resolve, reject) => {
const triggerId = generateTriggerId(appId);
diff --git a/app/lib/methods/canOpenRoom.ts b/app/lib/methods/canOpenRoom.ts
index 46c041537..6cd389909 100644
--- a/app/lib/methods/canOpenRoom.ts
+++ b/app/lib/methods/canOpenRoom.ts
@@ -1,8 +1,8 @@
import { ERoomTypes } from '../../definitions';
import { store } from '../store/auxStore';
import database from '../database';
-import RocketChat from '../rocketchat';
import sdk from '../services/sdk';
+import { Services } from '../services';
const restTypes = {
channel: 'channels',
@@ -17,7 +17,7 @@ async function open({ type, rid, name }: { type: ERoomTypes; rid: string; name:
// if it's a direct link without rid we'll create a new dm
// if the dm already exists it'll return the existent
if (type === ERoomTypes.DIRECT && !rid) {
- const result = await RocketChat.createDirectMessage(name);
+ const result = await Services.createDirectMessage(name);
if (result.success) {
const { room } = result;
return {
@@ -63,7 +63,7 @@ async function open({ type, rid, name }: { type: ERoomTypes; rid: string; name:
}
}
-export default async function canOpenRoom({ rid, path, isCall }: { rid: string; isCall: boolean; path: string }): Promise {
+export async function canOpenRoom({ rid, path, isCall }: { rid: string; isCall: boolean; path: string }): Promise {
try {
const db = database.active;
const subsCollection = db.get('subscriptions');
diff --git a/app/lib/methods/clearCache.ts b/app/lib/methods/clearCache.ts
index eeb5a97b2..51fd9e052 100644
--- a/app/lib/methods/clearCache.ts
+++ b/app/lib/methods/clearCache.ts
@@ -1,6 +1,6 @@
import database from '../database';
-export default async function clearCache({ server }: { server: string }): Promise {
+export async function clearCache({ server }: { server: string }): Promise {
try {
const serversDB = database.servers;
await serversDB.write(async () => {
diff --git a/app/lib/methods/crashReport.ts b/app/lib/methods/crashReport.ts
new file mode 100644
index 000000000..acb229db5
--- /dev/null
+++ b/app/lib/methods/crashReport.ts
@@ -0,0 +1,19 @@
+import AsyncStorage from '@react-native-community/async-storage';
+
+import { ANALYTICS_EVENTS_KEY, CRASH_REPORT_KEY } from '../constants';
+
+export async function getAllowCrashReport() {
+ const allowCrashReport = await AsyncStorage.getItem(CRASH_REPORT_KEY);
+ if (allowCrashReport === null) {
+ return true;
+ }
+ return JSON.parse(allowCrashReport);
+}
+
+export async function getAllowAnalyticsEvents() {
+ const allowAnalyticsEvents = await AsyncStorage.getItem(ANALYTICS_EVENTS_KEY);
+ if (allowAnalyticsEvents === null) {
+ return true;
+ }
+ return JSON.parse(allowAnalyticsEvents);
+}
diff --git a/app/lib/methods/enterpriseModules.ts b/app/lib/methods/enterpriseModules.ts
index e33cd7dcf..b5ce4e74a 100644
--- a/app/lib/methods/enterpriseModules.ts
+++ b/app/lib/methods/enterpriseModules.ts
@@ -57,11 +57,6 @@ export function getEnterpriseModules() {
});
}
-export function hasLicense(module: string) {
- const { enterpriseModules } = reduxStore.getState();
- return enterpriseModules.includes(module);
-}
-
export function isOmnichannelModuleAvailable() {
const { enterpriseModules } = reduxStore.getState();
return [LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE, LICENSE_LIVECHAT_ENTERPRISE].some(module => enterpriseModules.includes(module));
diff --git a/app/lib/methods/getCustomEmojis.ts b/app/lib/methods/getCustomEmojis.ts
index 4f664efaa..c2a431105 100644
--- a/app/lib/methods/getCustomEmojis.ts
+++ b/app/lib/methods/getCustomEmojis.ts
@@ -1,12 +1,11 @@
import orderBy from 'lodash/orderBy';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
-import { ICustomEmojis } from '../../reducers/customEmojis';
import { store as reduxStore } from '../store/auxStore';
import database from '../database';
import log from '../../utils/log';
import { setCustomEmojis as setCustomEmojisAction } from '../../actions/customEmojis';
-import { ICustomEmoji, TCustomEmojiModel } from '../../definitions';
+import { ICustomEmojiModel, TCustomEmojiModel, ICustomEmojis } from '../../definitions';
import sdk from '../services/sdk';
import { compareServerVersion } from './helpers/compareServerVersion';
@@ -16,7 +15,7 @@ interface IUpdateEmojis {
allRecords: TCustomEmojiModel[];
}
-const getUpdatedSince = (allEmojis: ICustomEmoji[]) => {
+const getUpdatedSince = (allEmojis: ICustomEmojiModel[]) => {
if (!allEmojis.length) {
return null;
}
diff --git a/app/lib/methods/getPermalinks.ts b/app/lib/methods/getPermalinks.ts
index 29ec4d2bd..f244b9871 100644
--- a/app/lib/methods/getPermalinks.ts
+++ b/app/lib/methods/getPermalinks.ts
@@ -2,7 +2,7 @@ import log from '../../utils/log';
import { TMessageModel, TSubscriptionModel } from '../../definitions';
import { store } from '../store/auxStore';
import { isGroupChat } from './helpers';
-import getRoom from './getRoom';
+import { getRoom } from './getRoom';
type TRoomType = 'p' | 'c' | 'd';
diff --git a/app/lib/methods/getRoom.ts b/app/lib/methods/getRoom.ts
index 35842e4f3..5dd66b81a 100644
--- a/app/lib/methods/getRoom.ts
+++ b/app/lib/methods/getRoom.ts
@@ -1,7 +1,7 @@
import { TSubscriptionModel } from '../../definitions';
import database from '../database';
-export default async function getRoom(rid: string): Promise {
+export async function getRoom(rid: string): Promise {
try {
const db = database.active;
const room = await db.get('subscriptions').find(rid);
diff --git a/app/lib/methods/getRoomInfo.ts b/app/lib/methods/getRoomInfo.ts
index 142d59177..67125bb3d 100644
--- a/app/lib/methods/getRoomInfo.ts
+++ b/app/lib/methods/getRoomInfo.ts
@@ -1,6 +1,6 @@
import { IServerSubscription, RoomType } from '../../definitions';
import { getSubscriptionByRoomId } from '../database/services/Subscription';
-import RocketChat from '../rocketchat';
+import { Services } from '../services';
export interface IRoomInfoResult {
rid: IServerSubscription['rid'];
@@ -21,7 +21,7 @@ const getRoomInfo = async (rid: string): Promise => {
};
}
- result = await RocketChat.getRoomInfo(rid);
+ result = await Services.getRoomInfo(rid);
if (result?.success) {
return {
rid,
diff --git a/app/lib/methods/getRooms.ts b/app/lib/methods/getRooms.ts
index cc7a37d77..0c2899531 100644
--- a/app/lib/methods/getRooms.ts
+++ b/app/lib/methods/getRooms.ts
@@ -1,6 +1,6 @@
import sdk from '../services/sdk';
-export default function (updatedSince: Date) {
+export function getRooms(updatedSince: Date) {
// subscriptions.get: Since RC 0.60.0
// rooms.get: Since RC 0.62.0
if (updatedSince) {
diff --git a/app/lib/methods/getSettings.ts b/app/lib/methods/getSettings.ts
index 8c53f6faa..76f10aa41 100644
--- a/app/lib/methods/getSettings.ts
+++ b/app/lib/methods/getSettings.ts
@@ -9,8 +9,8 @@ import log from '../../utils/log';
import { store as reduxStore } from '../store/auxStore';
import database from '../database';
import sdk from '../services/sdk';
-import { parseSettings, _prepareSettings } from './helpers';
import protectedFunction from './helpers/protectedFunction';
+import { parseSettings, _prepareSettings } from './parseSettings';
const serverInfoKeys = [
'Site_Name',
diff --git a/app/lib/methods/getSingleMessage.ts b/app/lib/methods/getSingleMessage.ts
index cc153e2f4..9b6ee2d1f 100644
--- a/app/lib/methods/getSingleMessage.ts
+++ b/app/lib/methods/getSingleMessage.ts
@@ -1,10 +1,10 @@
-import RocketChat from '../rocketchat';
import { IMessage } from '../../definitions';
+import { Services } from '../services';
const getSingleMessage = (messageId: string): Promise =>
new Promise(async (resolve, reject) => {
try {
- const result = await RocketChat.getSingleMessage(messageId);
+ const result = await Services.getSingleMessage(messageId);
if (result.success) {
return resolve(result.message);
}
diff --git a/app/lib/methods/getSlashCommands.ts b/app/lib/methods/getSlashCommands.ts
index d2fbe2a7b..2c197227c 100644
--- a/app/lib/methods/getSlashCommands.ts
+++ b/app/lib/methods/getSlashCommands.ts
@@ -6,7 +6,7 @@ import protectedFunction from './helpers/protectedFunction';
import { ISlashCommandResult, TSlashCommandModel } from '../../definitions';
import sdk from '../services/sdk';
-export default function getSlashCommands() {
+export function getSlashCommands() {
const db = database.active;
return new Promise(async resolve => {
try {
diff --git a/app/lib/methods/getUsersPresence.ts b/app/lib/methods/getUsersPresence.ts
index b8587e43a..a416d11bf 100644
--- a/app/lib/methods/getUsersPresence.ts
+++ b/app/lib/methods/getUsersPresence.ts
@@ -34,7 +34,7 @@ export function subscribeUsersPresence(this: IRocketChat) {
let usersBatch: string[] = [];
-export default async function getUsersPresence(usersParams: string[]) {
+export async function getUsersPresence(usersParams: string[]) {
const serverVersion = reduxStore.getState().server.version as string;
const { user: loggedUser } = reduxStore.getState().login;
@@ -106,6 +106,7 @@ export default async function getUsersPresence(usersParams: string[]) {
}
let usersTimer: ReturnType | null = null;
+
export function getUserPresence(uid: string) {
if (!usersTimer) {
usersTimer = setTimeout(() => {
diff --git a/app/lib/methods/helpers.ts b/app/lib/methods/helpers.ts
index c4c360234..695b4a82b 100644
--- a/app/lib/methods/helpers.ts
+++ b/app/lib/methods/helpers.ts
@@ -1,11 +1,7 @@
// @ts-nocheck - TEMP
-import AsyncStorage from '@react-native-community/async-storage';
-
import log from '../../utils/log';
import { store as reduxStore } from '../store/auxStore';
import database from '../database';
-import subscribeRoomsTmp from './subscriptions/rooms';
-import { ANALYTICS_EVENTS_KEY, CRASH_REPORT_KEY, defaultSettings } from '../constants';
export function isGroupChat(room): boolean {
return ((room.uids && room.uids.length > 2) || (room.usernames && room.usernames.length > 2)) ?? false;
@@ -89,64 +85,7 @@ export function hasRole(role): boolean {
return userRoles.indexOf(role) > -1;
}
-// AsyncStorage
-export async function getAllowCrashReport() {
- const allowCrashReport = await AsyncStorage.getItem(CRASH_REPORT_KEY);
- if (allowCrashReport === null) {
- return true;
- }
- return JSON.parse(allowCrashReport);
-}
-
-export async function getAllowAnalyticsEvents() {
- const allowAnalyticsEvents = await AsyncStorage.getItem(ANALYTICS_EVENTS_KEY);
- if (allowAnalyticsEvents === null) {
- return true;
- }
- return JSON.parse(allowAnalyticsEvents);
-}
-
-// TODO: remove this
-export async function subscribeRooms(this: any) {
- if (!this.roomsSub) {
- try {
- // TODO: We need to change this naming. Maybe move this logic to the SDK?
- this.roomsSub = await subscribeRoomsTmp.call(this);
- } catch (e) {
- log(e);
- }
- }
-}
-
-// TODO: remove this
-export function unsubscribeRooms(this: any) {
- if (this.roomsSub) {
- this.roomsSub.stop();
- this.roomsSub = null;
- }
-}
-
-export function parseSettings(settings) {
- return settings.reduce((ret, item) => {
- ret[item._id] = defaultSettings[item._id] && item[defaultSettings[item._id].type];
- if (item._id === 'Hide_System_Messages') {
- ret[item._id] = ret[item._id].reduce(
- (array, value) => [...array, ...(value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value])],
- []
- );
- }
- return ret;
- });
-}
-
-export function _prepareSettings(settings) {
- return settings.map(setting => {
- setting[defaultSettings[setting._id].type] = setting.value;
- return setting;
- });
-}
-
-export async function hasPermission(permissions, rid?: any) {
+export async function hasPermission(permissions, rid?: any): boolean[] {
let roomRoles = [];
if (rid) {
const db = database.active;
diff --git a/app/lib/methods/index.ts b/app/lib/methods/index.ts
new file mode 100644
index 000000000..f90a2f085
--- /dev/null
+++ b/app/lib/methods/index.ts
@@ -0,0 +1,36 @@
+export * from './actions';
+export * from './callJitsi';
+export * from './canOpenRoom';
+export * from './clearCache';
+export * from './enterpriseModules';
+export * from './getCustomEmojis';
+export * from './getPermalinks';
+export * from './getPermissions';
+export * from './getRoles';
+// export * from './getRoom'; only used inside methods folder
+export * from './getRoomInfo';
+export * from './getRooms';
+export * from './getSettings';
+export * from './getSingleMessage';
+export * from './getSlashCommands';
+export * from './getThreadName';
+export * from './getUsersPresence';
+export * from './helpers';
+export * from './loadMessagesForRoom';
+export * from './loadMissedMessages';
+export * from './loadNextMessages';
+export * from './loadSurroundingMessages';
+export * from './loadThreadMessages';
+export * from './logout';
+export * from './readMessages';
+export * from './roomTypeToApiType';
+export * from './search';
+export * from './sendFileMessage';
+export * from './sendMessage';
+export * from './setUser';
+export * from './triggerActions';
+export * from './updateMessages';
+export * from './userPreferences';
+export * from './userPreferencesMethods';
+export * from './crashReport';
+export * from './parseSettings';
diff --git a/app/lib/methods/loadMessagesForRoom.ts b/app/lib/methods/loadMessagesForRoom.ts
index 87ec9919b..d1e55ed67 100644
--- a/app/lib/methods/loadMessagesForRoom.ts
+++ b/app/lib/methods/loadMessagesForRoom.ts
@@ -4,7 +4,7 @@ import { MessageTypeLoad } from '../constants';
import { IMessage, TMessageModel } from '../../definitions';
import log from '../../utils/log';
import { getMessageById } from '../database/services/Message';
-import roomTypeToApiType, { RoomTypes } from './roomTypeToApiType';
+import { RoomTypes, roomTypeToApiType } from './roomTypeToApiType';
import sdk from '../services/sdk';
import updateMessages from './updateMessages';
import { generateLoadMoreId } from './helpers/generateLoadMoreId';
@@ -30,7 +30,7 @@ async function load({ rid: roomId, latest, t }: { rid: string; latest?: Date; t:
return data.messages;
}
-export default function loadMessagesForRoom(args: {
+export function loadMessagesForRoom(args: {
rid: string;
t: RoomTypes;
latest?: Date;
diff --git a/app/lib/methods/loadMissedMessages.ts b/app/lib/methods/loadMissedMessages.ts
index cb5e0712d..aff5e1530 100644
--- a/app/lib/methods/loadMissedMessages.ts
+++ b/app/lib/methods/loadMissedMessages.ts
@@ -29,7 +29,7 @@ async function load({ rid: roomId, lastOpen }: { rid: string; lastOpen?: Date })
return result;
}
-export default function loadMissedMessages(args: { rid: string; lastOpen?: Date }): Promise {
+export function loadMissedMessages(args: { rid: string; lastOpen?: Date }): Promise {
return new Promise(async (resolve, reject) => {
try {
const data = await load({ rid: args.rid, lastOpen: args.lastOpen });
diff --git a/app/lib/methods/loadNextMessages.ts b/app/lib/methods/loadNextMessages.ts
index 533059cdb..055d34f89 100644
--- a/app/lib/methods/loadNextMessages.ts
+++ b/app/lib/methods/loadNextMessages.ts
@@ -19,7 +19,7 @@ interface ILoadNextMessages {
loaderItem: TMessageModel;
}
-export default function loadNextMessages(args: ILoadNextMessages): Promise {
+export function loadNextMessages(args: ILoadNextMessages): Promise {
return new Promise(async (resolve, reject) => {
try {
const data = await sdk.methodCallWrapper('loadNextMessages', args.rid, args.ts, COUNT);
diff --git a/app/lib/methods/loadSurroundingMessages.ts b/app/lib/methods/loadSurroundingMessages.ts
index 35abf4083..973bd05cd 100644
--- a/app/lib/methods/loadSurroundingMessages.ts
+++ b/app/lib/methods/loadSurroundingMessages.ts
@@ -12,7 +12,7 @@ import { generateLoadMoreId } from './helpers/generateLoadMoreId';
const COUNT = 50;
-export default function loadSurroundingMessages({ messageId, rid }: { messageId: string; rid: string }) {
+export function loadSurroundingMessages({ messageId, rid }: { messageId: string; rid: string }) {
return new Promise(async (resolve, reject) => {
try {
const data = await sdk.methodCallWrapper('loadSurroundingMessages', { _id: messageId, rid }, COUNT);
diff --git a/app/lib/methods/loadThreadMessages.ts b/app/lib/methods/loadThreadMessages.ts
index 82beeeeac..2dc49b14e 100644
--- a/app/lib/methods/loadThreadMessages.ts
+++ b/app/lib/methods/loadThreadMessages.ts
@@ -24,7 +24,7 @@ async function load({ tmid }: { tmid: string }) {
}
}
-export default function loadThreadMessages({ tmid, rid }: { tmid: string; rid: string }) {
+export function loadThreadMessages({ tmid, rid }: { tmid: string; rid: string }) {
return new Promise(async (resolve, reject) => {
try {
let data = await load({ tmid });
diff --git a/app/lib/methods/logout.ts b/app/lib/methods/logout.ts
index 4cd3469b6..4a84b6421 100644
--- a/app/lib/methods/logout.ts
+++ b/app/lib/methods/logout.ts
@@ -10,14 +10,14 @@ import { isSsl } from '../../utils/url';
import log from '../../utils/log';
import { ICertificate, IRocketChat } from '../../definitions';
import sdk from '../services/sdk';
-import { E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY } from '../constants';
+import { CURRENT_SERVER, E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY, TOKEN_KEY } from '../constants';
import UserPreferences from './userPreferences';
-import RocketChat from '../rocketchat';
+import { Services } from '../services';
function removeServerKeys({ server, userId }: { server: string; userId?: string | null }) {
- UserPreferences.removeItem(`${RocketChat.TOKEN_KEY}-${server}`);
+ UserPreferences.removeItem(`${TOKEN_KEY}-${server}`);
if (userId) {
- UserPreferences.removeItem(`${RocketChat.TOKEN_KEY}-${userId}`);
+ UserPreferences.removeItem(`${TOKEN_KEY}-${userId}`);
}
UserPreferences.removeItem(`${BASIC_AUTH_KEY}-${server}`);
UserPreferences.removeItem(`${server}-${E2E_PUBLIC_KEY}`);
@@ -42,7 +42,7 @@ async function removeServerData({ server }: { server: string }) {
try {
const batch: Model[] = [];
const serversDB = database.servers;
- const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
+ const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
const usersCollection = serversDB.get('users');
if (userId) {
@@ -62,7 +62,7 @@ async function removeServerData({ server }: { server: string }) {
}
function removeCurrentServer() {
- UserPreferences.removeItem(RocketChat.CURRENT_SERVER);
+ UserPreferences.removeItem(CURRENT_SERVER);
}
async function removeServerDatabase({ server }: { server: string }) {
@@ -76,9 +76,9 @@ async function removeServerDatabase({ server }: { server: string }) {
export async function removeServer({ server }: { server: string }): Promise {
try {
- const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
+ const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
if (userId) {
- const resume = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${userId}`);
+ const resume = UserPreferences.getString(`${TOKEN_KEY}-${userId}`);
const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: isSsl(server) });
await sdk.login({ resume });
@@ -110,7 +110,7 @@ export async function logout(this: IRocketChat, { server }: { server: string }):
}
try {
- await this.removePushToken();
+ await Services.removePushToken();
} catch (e) {
log(e);
}
diff --git a/app/lib/methods/parseSettings.ts b/app/lib/methods/parseSettings.ts
new file mode 100644
index 000000000..a59e725ce
--- /dev/null
+++ b/app/lib/methods/parseSettings.ts
@@ -0,0 +1,23 @@
+import { defaultSettings } from '../constants';
+
+export function parseSettings(settings: any) {
+ return settings.reduce((ret: any, item: any) => {
+ // @ts-ignore
+ ret[item._id] = defaultSettings[item._id] && item[defaultSettings[item._id].type];
+ if (item._id === 'Hide_System_Messages') {
+ ret[item._id] = ret[item._id].reduce(
+ (array: any, value: any) => [...array, ...(value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value])],
+ []
+ );
+ }
+ return ret;
+ });
+}
+
+export function _prepareSettings(settings: any) {
+ return settings.map((setting: any) => {
+ // @ts-ignore
+ setting[defaultSettings[setting._id].type] = setting.value;
+ return setting;
+ });
+}
diff --git a/app/lib/methods/readMessages.ts b/app/lib/methods/readMessages.ts
index 27f4808bb..36f6dfbd0 100644
--- a/app/lib/methods/readMessages.ts
+++ b/app/lib/methods/readMessages.ts
@@ -3,7 +3,7 @@ import log from '../../utils/log';
import { TSubscriptionModel } from '../../definitions';
import sdk from '../services/sdk';
-export default async function readMessages(rid: string, ls: Date, updateLastOpen = false): Promise {
+export async function readMessages(rid: string, ls: Date, updateLastOpen = false): Promise {
try {
const db = database.active;
const subscription = await db.get('subscriptions').find(rid);
diff --git a/app/lib/methods/roomTypeToApiType.ts b/app/lib/methods/roomTypeToApiType.ts
index 4473c5d38..dc081fdd5 100644
--- a/app/lib/methods/roomTypeToApiType.ts
+++ b/app/lib/methods/roomTypeToApiType.ts
@@ -23,6 +23,4 @@ export const types: { [K in RoomTypes]: ApiTypes } = {
l: ETypes.Channels
};
-const roomTypeToApiType = (t: T) => types[t];
-
-export default roomTypeToApiType;
+export const roomTypeToApiType = (t: T) => types[t];
diff --git a/app/lib/methods/sendMessage.ts b/app/lib/methods/sendMessage.ts
index 06738a470..0d14c849e 100644
--- a/app/lib/methods/sendMessage.ts
+++ b/app/lib/methods/sendMessage.ts
@@ -47,7 +47,7 @@ const changeMessageStatus = async (id: string, status: number, tmid?: string, me
}
};
-export async function sendMessageCall(message: any) {
+async function sendMessageCall(message: any) {
const { _id, tmid } = message;
try {
// RC 0.60.0
diff --git a/app/lib/services/shareExtension.ts b/app/lib/methods/shareExtension.ts
similarity index 80%
rename from app/lib/services/shareExtension.ts
rename to app/lib/methods/shareExtension.ts
index 4970ab105..028748bce 100644
--- a/app/lib/services/shareExtension.ts
+++ b/app/lib/methods/shareExtension.ts
@@ -4,18 +4,21 @@ import { shareSetSettings, shareSelectServer, shareSetUser } from '../../actions
import SSLPinning from '../../utils/sslPinning';
import log from '../../utils/log';
import { IShareServer, IShareUser } from '../../reducers/share';
-import UserPreferences from '../methods/userPreferences';
+import UserPreferences from './userPreferences';
import database from '../database';
-import RocketChat from '../rocketchat';
import { encryptionInit } from '../../actions/encryption';
import { store } from '../store/auxStore';
-import sdk from './sdk';
+import sdk from '../services/sdk';
+import { CERTIFICATE_KEY, TOKEN_KEY } from '../constants';
+import { setCustomEmojis } from './getCustomEmojis';
+import { Services } from '../services';
+import { parseSettings } from './parseSettings';
export async function shareExtensionInit(server: string) {
database.setShareDB(server);
try {
- const certificate = UserPreferences.getString(`${RocketChat.CERTIFICATE_KEY}-${server}`);
+ const certificate = UserPreferences.getString(`${CERTIFICATE_KEY}-${server}`);
if (SSLPinning && certificate) {
await SSLPinning.setCertificate(certificate, server);
}
@@ -41,7 +44,7 @@ export async function shareExtensionInit(server: string) {
}
store.dispatch(shareSelectServer(currentServer));
- RocketChat.setCustomEmojis();
+ setCustomEmojis();
try {
// set Settings
@@ -57,10 +60,10 @@ export async function shareExtensionInit(server: string) {
valueAsArray: item.valueAsArray,
_updatedAt: item._updatedAt
}));
- store.dispatch(shareSetSettings(RocketChat.parseSettings(parsed)));
+ store.dispatch(shareSetSettings(parseSettings(parsed)));
// set User info
- const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
+ const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
const userCollections = serversDB.get('users');
let user = null;
if (userId) {
@@ -74,7 +77,7 @@ export async function shareExtensionInit(server: string) {
}
store.dispatch(shareSetUser(user as IShareUser));
if (user) {
- await RocketChat.login({ resume: user.token });
+ await Services.login({ resume: user.token });
}
store.dispatch(encryptionInit());
} catch (e) {
diff --git a/app/lib/methods/subscribeRooms.ts b/app/lib/methods/subscribeRooms.ts
new file mode 100644
index 000000000..8d34195fa
--- /dev/null
+++ b/app/lib/methods/subscribeRooms.ts
@@ -0,0 +1,22 @@
+import log from '../../utils/log';
+import subscribeRoomsTmp from './subscriptions/rooms';
+
+// TODO: remove this
+export async function subscribeRooms(this: any) {
+ if (!this.roomsSub) {
+ try {
+ // TODO: We need to change this naming. Maybe move this logic to the SDK?
+ this.roomsSub = await subscribeRoomsTmp.call(this);
+ } catch (e) {
+ log(e);
+ }
+ }
+}
+
+// TODO: remove this
+export function unsubscribeRooms(this: any) {
+ if (this.roomsSub) {
+ this.roomsSub.stop();
+ this.roomsSub = null;
+ }
+}
diff --git a/app/lib/methods/subscriptions/room.ts b/app/lib/methods/subscriptions/room.ts
index 8685fc3aa..bf60bae1c 100644
--- a/app/lib/methods/subscriptions/room.ts
+++ b/app/lib/methods/subscriptions/room.ts
@@ -12,12 +12,13 @@ import { getThreadMessageById } from '../../database/services/ThreadMessage';
import { store as reduxStore } from '../../store/auxStore';
import { addUserTyping, clearUserTyping, removeUserTyping } from '../../../actions/usersTyping';
import debounce from '../../../utils/debounce';
-import RocketChat from '../../rocketchat';
import { subscribeRoom, unsubscribeRoom } from '../../../actions/room';
import { Encryption } from '../../encryption';
import { IMessage, TMessageModel, TSubscriptionModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
import { IDDPMessage } from '../../../definitions/IDDPMessage';
import sdk from '../../services/sdk';
+import { readMessages } from '../readMessages';
+import { loadMissedMessages } from '../loadMissedMessages';
const WINDOW_TIME = 1000;
@@ -107,7 +108,7 @@ export default class RoomSubscription {
handleConnection = async () => {
try {
reduxStore.dispatch(clearUserTyping());
- await RocketChat.loadMissedMessages({ rid: this.rid });
+ await loadMissedMessages({ rid: this.rid });
const _lastOpen = new Date();
this.read(_lastOpen);
this.lastOpen = _lastOpen;
@@ -185,7 +186,7 @@ export default class RoomSubscription {
});
read = debounce((lastOpen: Date) => {
- RocketChat.readMessages(this.rid, lastOpen);
+ readMessages(this.rid, lastOpen);
}, 300);
updateMessage = (message: IMessage): Promise =>
diff --git a/app/lib/methods/subscriptions/rooms.ts b/app/lib/methods/subscriptions/rooms.ts
index aa73b09d5..001e07d42 100644
--- a/app/lib/methods/subscriptions/rooms.ts
+++ b/app/lib/methods/subscriptions/rooms.ts
@@ -11,7 +11,6 @@ import random from '../../../utils/random';
import { store } from '../../store/auxStore';
import { handlePayloadUserInteraction } from '../actions';
import buildMessage from '../helpers/buildMessage';
-import RocketChat from '../../rocketchat';
import EventEmitter from '../../../utils/events';
import { removedRoom } from '../../../actions/room';
import { setUser } from '../../../actions/login';
@@ -34,6 +33,8 @@ import { IDDPMessage } from '../../../definitions/IDDPMessage';
import { getSubscriptionByRoomId } from '../../database/services/Subscription';
import { getMessageById } from '../../database/services/Message';
import { E2E_MESSAGE_TYPE } from '../../constants';
+import { getRoom } from '../getRoom';
+import { getRoomAvatar, getRoomTitle, getSenderName } from '../helpers';
const removeListener = (listener: { stop: () => void }) => listener.stop();
@@ -358,9 +359,9 @@ export default function subscribeRooms() {
const {
payload: { rid, message, sender }
} = notification;
- const room = await RocketChat.getRoom(rid);
- notification.title = RocketChat.getRoomTitle(room);
- notification.avatar = RocketChat.getRoomAvatar(room);
+ const room = await getRoom(rid);
+ notification.title = getRoomTitle(room);
+ notification.avatar = getRoomAvatar(room);
// If it's from a encrypted room
if (message?.t === E2E_MESSAGE_TYPE) {
@@ -371,7 +372,7 @@ export default function subscribeRooms() {
notification.text = msg;
// If it's a private group we should add the sender name
} else {
- notification.text = `${RocketChat.getSenderName(sender)}: ${msg}`;
+ notification.text = `${getSenderName(sender)}: ${msg}`;
}
}
} catch (e) {
diff --git a/app/lib/methods/triggerActions.ts b/app/lib/methods/triggerActions.ts
index 8815ac6db..bd43a681c 100644
--- a/app/lib/methods/triggerActions.ts
+++ b/app/lib/methods/triggerActions.ts
@@ -5,21 +5,20 @@ import {
ITriggerSubmitView,
ModalActions
} from '../../containers/UIKit/interfaces';
-import { TRocketChat } from '../../definitions';
import Navigation from '../navigation/appNavigation';
import { triggerAction } from './actions';
-export function triggerBlockAction(this: TRocketChat, options: ITriggerBlockAction) {
- return triggerAction.call(this, { type: ActionTypes.ACTION, ...options });
-}
-
-export async function triggerSubmitView(this: TRocketChat, { viewId, ...options }: ITriggerSubmitView) {
- const result = await triggerAction.call(this, { type: ActionTypes.SUBMIT, viewId, ...options });
+export async function triggerSubmitView({ viewId, ...options }: ITriggerSubmitView) {
+ const result = await triggerAction({ type: ActionTypes.SUBMIT, viewId, ...options });
if (!result || ModalActions.CLOSE === result) {
Navigation.back();
}
}
-export function triggerCancel(this: TRocketChat, { view, ...options }: ITriggerCancel) {
- return triggerAction.call(this, { type: ActionTypes.CLOSED, view, ...options });
+export function triggerCancel({ view, ...options }: ITriggerCancel) {
+ return triggerAction({ type: ActionTypes.CLOSED, view, ...options });
+}
+
+export function triggerBlockAction(options: ITriggerBlockAction) {
+ return triggerAction({ type: ActionTypes.ACTION, ...options });
}
diff --git a/app/lib/methods/useServer.ts b/app/lib/methods/useServer.ts
new file mode 100644
index 000000000..c282a5cf6
--- /dev/null
+++ b/app/lib/methods/useServer.ts
@@ -0,0 +1,29 @@
+import { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+
+import { IApplicationState, TServerModel } from '../../definitions';
+import database from '../database';
+
+export default function useServer() {
+ const [server, setServer] = useState(null);
+ const shareServer = useSelector((state: IApplicationState) => state.share.server.server);
+ const appServer = useSelector((state: IApplicationState) => state.server.server);
+
+ useEffect(() => {
+ async function init() {
+ const serversDB = database.servers;
+ const serversCollection = serversDB.get('servers');
+ let serverInfo = null;
+ try {
+ serverInfo = await serversCollection.find(shareServer || appServer);
+ setServer(serverInfo);
+ } catch {
+ setServer(serverInfo);
+ }
+ }
+
+ init();
+ }, []);
+
+ return [server];
+}
diff --git a/app/lib/notifications/push.ts b/app/lib/notifications/push.ts
index 436506a2e..a6c06c630 100644
--- a/app/lib/notifications/push.ts
+++ b/app/lib/notifications/push.ts
@@ -73,8 +73,8 @@ class PushNotification {
return this.deviceToken;
}
- setBadgeCount = (count?: number) => {
- if (isIOS && count) {
+ setBadgeCount = (count = 0) => {
+ if (isIOS) {
Notifications.ios.setBadgeCount(count);
}
};
diff --git a/app/lib/rocketchat.ts b/app/lib/rocketchat.ts
index 15daa9663..e5fd4900d 100644
--- a/app/lib/rocketchat.ts
+++ b/app/lib/rocketchat.ts
@@ -1,77 +1,16 @@
-// Methods
-import canOpenRoom from './methods/canOpenRoom';
-import clearCache from './methods/clearCache';
-import getRoom from './methods/getRoom';
-import getRooms from './methods/getRooms';
-import getSlashCommands from './methods/getSlashCommands';
-import loadMessagesForRoom from './methods/loadMessagesForRoom';
-import loadMissedMessages from './methods/loadMissedMessages';
-import loadNextMessages from './methods/loadNextMessages';
-import loadSurroundingMessages from './methods/loadSurroundingMessages';
-import loadThreadMessages from './methods/loadThreadMessages';
-import readMessages from './methods/readMessages';
-import roomTypeToApiType from './methods/roomTypeToApiType';
-// Spread Methods
-import * as sendMessage from './methods/sendMessage';
-import * as callJitsi from './methods/callJitsi';
-import * as enterpriseModules from './methods/enterpriseModules';
-import * as getCustomEmojis from './methods/getCustomEmojis';
-import * as getPermalinks from './methods/getPermalinks';
-import * as getPermissions from './methods/getPermissions';
-import * as getRoles from './methods/getRoles';
-import * as getSettings from './methods/getSettings';
-import * as getUsersPresence from './methods/getUsersPresence';
-import * as helpers from './methods/helpers';
-import * as logout from './methods/logout';
-import * as search from './methods/search';
-import * as sendFileMessage from './methods/sendFileMessage';
-import * as setUser from './methods/setUser';
-import * as triggerActions from './methods/triggerActions';
-import * as userPreferencesMethods from './methods/userPreferencesMethods';
-import * as connect from './services/connect';
-import * as restApis from './services/restApi';
-import * as shareExtension from './services/shareExtension';
-
-const TOKEN_KEY = 'reactnativemeteor_usertoken';
-const CURRENT_SERVER = 'currentServer';
-const CERTIFICATE_KEY = 'RC_CERTIFICATE_KEY';
+import { _setUser } from './methods/setUser';
+import { logout } from './methods/logout';
+import { subscribeRooms, unsubscribeRooms } from './methods/subscribeRooms';
+import { subscribeUsersPresence } from './methods/getUsersPresence';
+import { connect } from './services/connect';
const RocketChat = {
- TOKEN_KEY,
- CURRENT_SERVER,
- CERTIFICATE_KEY,
- ...restApis,
- ...search,
- ...getPermalinks,
- ...connect,
- ...enterpriseModules,
- ...sendMessage,
- ...shareExtension,
- ...sendFileMessage,
- ...logout,
- ...getUsersPresence,
- ...getSettings,
- ...getRoles,
- ...getPermissions,
- ...triggerActions,
- ...callJitsi,
- ...getCustomEmojis,
- ...helpers,
- ...userPreferencesMethods,
- ...setUser,
-
- canOpenRoom,
- clearCache,
- loadMissedMessages,
- loadMessagesForRoom,
- loadSurroundingMessages,
- loadNextMessages,
- loadThreadMessages,
- getRooms,
- readMessages,
- getSlashCommands,
- getRoom,
- roomTypeToApiType
+ logout,
+ subscribeRooms,
+ unsubscribeRooms,
+ _setUser,
+ subscribeUsersPresence,
+ connect
};
export default RocketChat;
diff --git a/app/lib/services/connect.ts b/app/lib/services/connect.ts
index 6575a5bcd..875e0844b 100644
--- a/app/lib/services/connect.ts
+++ b/app/lib/services/connect.ts
@@ -24,6 +24,7 @@ import { updateSettings } from '../../actions/settings';
import { defaultSettings, MIN_ROCKETCHAT_VERSION } from '../constants';
import { compareServerVersion } from '../methods/helpers/compareServerVersion';
import { onRolesChanged } from '../methods/getRoles';
+import { getSettings } from '../methods';
interface IServices {
[index: string]: string | boolean;
@@ -85,7 +86,7 @@ function connect(
EventEmitter.emit('INQUIRY_UNSUBSCRIBE');
sdk.initialize(server);
- this.getSettings();
+ getSettings();
sdk.current
.connect()
diff --git a/app/lib/services/index.ts b/app/lib/services/index.ts
new file mode 100644
index 000000000..1a80e18f6
--- /dev/null
+++ b/app/lib/services/index.ts
@@ -0,0 +1,7 @@
+import * as connect from './connect';
+import * as restApi from './restApi';
+
+export const Services = {
+ ...connect,
+ ...restApi
+};
diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts
index 2b18d8706..502220e9d 100644
--- a/app/lib/services/restApi.ts
+++ b/app/lib/services/restApi.ts
@@ -6,9 +6,9 @@ import {
IRoomNotifications,
SubscriptionType,
IUser,
- TRocketChat
+ IAvatarSuggestion,
+ IProfileParams
} from '../../definitions';
-import { IAvatarSuggestion, IParams } from '../../definitions/IProfileViewInterfaces';
import { ISpotlight } from '../../definitions/ISpotlight';
import { TEAM_TYPE } from '../../definitions/ITeam';
import { Encryption } from '../encryption';
@@ -16,9 +16,10 @@ import { TParams } from '../../definitions/ILivechatEditView';
import { store as reduxStore } from '../store/auxStore';
import { getDeviceToken } from '../notifications';
import { getBundleId, isIOS } from '../../utils/deviceInfo';
-import roomTypeToApiType, { RoomTypes } from '../methods/roomTypeToApiType';
+import { RoomTypes, roomTypeToApiType } from '../methods';
import sdk from './sdk';
import { compareServerVersion } from '../methods/helpers/compareServerVersion';
+import RocketChat from '../rocketchat';
export const createChannel = ({
name,
@@ -561,7 +562,10 @@ export const saveRoomSettings = (
// RC 0.55.0
sdk.methodCallWrapper('saveRoomSettings', rid, params);
-export const saveUserProfile = (data: IParams | Pick, customFields?: { [key: string | number]: string }) =>
+export const saveUserProfile = (
+ data: IProfileParams | Pick,
+ customFields?: { [key: string | number]: string }
+) =>
// RC 0.62.2
sdk.post('users.updateOwnBasicInfo', { data, customFields });
@@ -801,10 +805,9 @@ export const emitTyping = (room: IRoom, typing = true) => {
return sdk.methodCall('stream-notify-room', `${room}/typing`, name, typing);
};
-export function e2eResetOwnKey(this: TRocketChat): Promise {
+export function e2eResetOwnKey(): Promise {
// {} when TOTP is enabled
- // TODO: remove this
- this.unsubscribeRooms();
+ RocketChat.unsubscribeRooms();
// RC 0.72.0
return sdk.methodCallWrapper('e2e.resetOwnE2EKey');
diff --git a/app/presentation/RoomItem/TypeIcon.tsx b/app/presentation/RoomItem/TypeIcon.tsx
deleted file mode 100644
index d8bebb2e5..000000000
--- a/app/presentation/RoomItem/TypeIcon.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-
-import { TUserStatus, IOmnichannelSource } from '../../definitions';
-import RoomTypeIcon from '../../containers/RoomTypeIcon';
-
-interface ITypeIcon {
- type: string;
- status: TUserStatus;
- prid: string;
- isGroupChat: boolean;
- teamMain: boolean;
- size?: number;
- style?: object;
- sourceType?: IOmnichannelSource;
-}
-
-const TypeIcon = React.memo(({ type, prid, status, isGroupChat, teamMain, size, style, sourceType }: ITypeIcon) => (
-
-));
-
-export default TypeIcon;
diff --git a/app/reducers/createChannel.ts b/app/reducers/createChannel.ts
index 713a59f4e..fd2cbdcc2 100644
--- a/app/reducers/createChannel.ts
+++ b/app/reducers/createChannel.ts
@@ -4,7 +4,7 @@ import { CREATE_CHANNEL } from '../actions/actionsTypes';
interface ICreateChannelResult {
name: string;
users: string[];
- teamId: string;
+ teamId?: string;
type: boolean;
readOnly: boolean;
encrypted: boolean;
diff --git a/app/reducers/customEmojis.test.ts b/app/reducers/customEmojis.test.ts
index 3f507f04c..b45e79b9b 100644
--- a/app/reducers/customEmojis.test.ts
+++ b/app/reducers/customEmojis.test.ts
@@ -1,6 +1,7 @@
import { setCustomEmojis } from '../actions/customEmojis';
-import { ICustomEmojis, initialState } from './customEmojis';
+import { initialState } from './customEmojis';
import { mockedStore } from './mockedStore';
+import { ICustomEmojis } from '../definitions';
describe('test reducer', () => {
it('should return initial state', () => {
diff --git a/app/reducers/customEmojis.ts b/app/reducers/customEmojis.ts
index 859d634d4..b462dd5a2 100644
--- a/app/reducers/customEmojis.ts
+++ b/app/reducers/customEmojis.ts
@@ -1,15 +1,5 @@
import { SET_CUSTOM_EMOJIS } from '../actions/actionsTypes';
-import { TApplicationActions } from '../definitions';
-
-// There are at least three interfaces for emoji, but none of them includes only this data.
-interface IEmoji {
- name: string;
- extension: string;
-}
-
-export interface ICustomEmojis {
- [key: string]: IEmoji;
-}
+import { ICustomEmojis, TApplicationActions } from '../definitions';
export const initialState: ICustomEmojis = {};
diff --git a/app/reducers/settings.ts b/app/reducers/settings.ts
index a8ea96a9d..087c49f5a 100644
--- a/app/reducers/settings.ts
+++ b/app/reducers/settings.ts
@@ -1,9 +1,10 @@
import { IActionSettings } from '../actions/settings';
import { SETTINGS } from '../actions/actionsTypes';
import { defaultSettings } from '../lib/constants';
+import { IAssetsFavicon512 } from '../definitions/IAssetsFavicon512';
export type TSupportedSettings = keyof typeof defaultSettings;
-export type TSettingsValues = string | number | boolean | string[];
+export type TSettingsValues = string | number | boolean | string[] | IAssetsFavicon512;
export type TSettingsState = {
[K in TSupportedSettings]?: TSettingsValues;
diff --git a/app/sagas/createChannel.js b/app/sagas/createChannel.js
index f540e3226..444f442eb 100644
--- a/app/sagas/createChannel.js
+++ b/app/sagas/createChannel.js
@@ -4,24 +4,12 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import { CREATE_CHANNEL, LOGIN } from '../actions/actionsTypes';
import { createChannelFailure, createChannelSuccess } from '../actions/createChannel';
import { showErrorAlert } from '../utils/info';
-import RocketChat from '../lib/rocketchat';
import Navigation from '../lib/navigation/appNavigation';
import database from '../lib/database';
import I18n from '../i18n';
import { events, logEvent } from '../utils/log';
import { goRoom } from '../utils/goRoom';
-
-const createChannel = function createChannel(data) {
- return RocketChat.createChannel(data);
-};
-
-const createGroupChat = function createGroupChat() {
- return RocketChat.createGroupChat();
-};
-
-const createTeam = function createTeam(data) {
- return RocketChat.createTeam(data);
-};
+import { Services } from '../lib/services';
const handleRequest = function* handleRequest({ data }) {
try {
@@ -39,7 +27,7 @@ const handleRequest = function* handleRequest({ data }) {
broadcast: `${broadcast}`,
encrypted: `${encrypted}`
});
- const result = yield call(createTeam, data);
+ const result = yield Services.createTeam(data);
sub = {
rid: result?.team?.roomId,
...result.team,
@@ -47,7 +35,7 @@ const handleRequest = function* handleRequest({ data }) {
};
} else if (data.group) {
logEvent(events.SELECTED_USERS_CREATE_GROUP);
- const result = yield call(createGroupChat);
+ const result = yield Services.createGroupChat();
if (result.success) {
sub = {
rid: result.room?._id,
@@ -62,7 +50,7 @@ const handleRequest = function* handleRequest({ data }) {
broadcast,
encrypted
});
- const result = yield call(createChannel, data);
+ const result = yield Services.createChannel(data);
sub = {
rid: result?.channel?._id || result?.group?._id,
...result?.channel,
diff --git a/app/sagas/createDiscussion.js b/app/sagas/createDiscussion.js
index 6009fe8b2..9afccc7cf 100644
--- a/app/sagas/createDiscussion.js
+++ b/app/sagas/createDiscussion.js
@@ -3,13 +3,9 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import { CREATE_DISCUSSION, LOGIN } from '../actions/actionsTypes';
import { createDiscussionFailure, createDiscussionSuccess } from '../actions/createDiscussion';
-import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
import { events, logEvent } from '../utils/log';
-
-const create = function* create(data) {
- return yield RocketChat.createDiscussion(data);
-};
+import { Services } from '../lib/services';
const handleRequest = function* handleRequest({ data }) {
logEvent(events.CD_CREATE);
@@ -18,7 +14,7 @@ const handleRequest = function* handleRequest({ data }) {
if (!auth) {
yield take(LOGIN.SUCCESS);
}
- const result = yield call(create, data);
+ const result = yield Services.createDiscussion(data);
if (result.success) {
const { discussion: sub } = result;
diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js
index 71036b4aa..bb545bef7 100644
--- a/app/sagas/deepLinking.js
+++ b/app/sagas/deepLinking.js
@@ -6,7 +6,6 @@ import * as types from '../actions/actionsTypes';
import { selectServerRequest, serverInitAdd } from '../actions/server';
import { inviteLinksRequest, inviteLinksSetToken } from '../actions/inviteLinks';
import database from '../lib/database';
-import RocketChat from '../lib/rocketchat';
import EventEmitter from '../utils/events';
import { appInit, appStart } from '../actions/app';
import { localAuthenticate } from '../utils/localAuthentication';
@@ -14,6 +13,9 @@ import { goRoom } from '../utils/goRoom';
import { loginRequest } from '../actions/login';
import log from '../utils/log';
import { RootEnum } from '../definitions';
+import { CURRENT_SERVER, TOKEN_KEY } from '../lib/constants';
+import { callJitsi, callJitsiWithoutServer, canOpenRoom, getUidDirectMessage } from '../lib/methods';
+import { Services } from '../lib/services';
const roomTypes = {
channel: 'c',
@@ -52,12 +54,12 @@ const navigate = function* navigate({ params }) {
[type, name, , jumpToThreadId] = params.path.split('/');
}
if (type !== 'invite' || params.rid) {
- const room = yield RocketChat.canOpenRoom(params);
+ const room = yield canOpenRoom(params);
if (room) {
const item = {
name,
t: roomTypes[type],
- roomUserId: RocketChat.getUidDirectMessage(room),
+ roomUserId: getUidDirectMessage(room),
...room
};
@@ -84,7 +86,7 @@ const navigate = function* navigate({ params }) {
}
if (params.isCall) {
- RocketChat.callJitsi(item);
+ callJitsi(item);
}
}
} else {
@@ -104,7 +106,7 @@ const fallbackNavigation = function* fallbackNavigation() {
const handleOAuth = function* handleOAuth({ params }) {
const { credentialToken, credentialSecret } = params;
try {
- yield RocketChat.loginOAuthOrSso({ oauth: { credentialToken, credentialSecret } }, false);
+ yield Services.loginOAuthOrSso({ oauth: { credentialToken, credentialSecret } }, false);
} catch (e) {
log(e);
}
@@ -125,7 +127,7 @@ const handleOpen = function* handleOpen({ params }) {
});
if (!host && params.fullURL) {
- RocketChat.callJitsiWithoutServer(params.fullURL);
+ callJitsiWithoutServer(params.fullURL);
return;
}
}
@@ -158,8 +160,8 @@ const handleOpen = function* handleOpen({ params }) {
}
const [server, user] = yield all([
- UserPreferences.getString(RocketChat.CURRENT_SERVER),
- UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${host}`)
+ UserPreferences.getString(CURRENT_SERVER),
+ UserPreferences.getString(`${TOKEN_KEY}-${host}`)
]);
// TODO: needs better test
@@ -187,7 +189,7 @@ const handleOpen = function* handleOpen({ params }) {
// do nothing?
}
// if deep link is from a different server
- const result = yield RocketChat.getServerInfo(host);
+ const result = yield Services.getServerInfo(host);
if (!result.success) {
// Fallback to prevent the app from being stuck on splash screen
yield fallbackNavigation();
diff --git a/app/sagas/encryption.js b/app/sagas/encryption.js
index d363c5054..f0d7f994e 100644
--- a/app/sagas/encryption.js
+++ b/app/sagas/encryption.js
@@ -6,13 +6,13 @@ import { encryptionSet } from '../actions/encryption';
import { Encryption } from '../lib/encryption';
import Navigation from '../lib/navigation/appNavigation';
import database from '../lib/database';
-import RocketChat from '../lib/rocketchat';
import UserPreferences from '../lib/methods/userPreferences';
import { getUserSelector } from '../selectors/login';
import { showErrorAlert } from '../utils/info';
import I18n from '../i18n';
import log from '../utils/log';
import { E2E_BANNER_TYPE, E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY } from '../lib/constants';
+import { Services } from '../lib/services';
const getServer = state => state.share.server.server || state.server.server;
const getE2eEnable = state => state.settings.E2E_Enable;
@@ -42,7 +42,7 @@ const handleEncryptionInit = function* handleEncryptionInit() {
const storedPrivateKey = UserPreferences.getString(`${server}-${E2E_PRIVATE_KEY}`);
// Fetch server stored e2e keys
- const keys = yield RocketChat.e2eFetchMyKeys();
+ const keys = yield Services.e2eFetchMyKeys();
// A private key was received from the server, but it's not saved locally yet
// Show the banner asking for the password
@@ -96,7 +96,7 @@ const handleEncryptionDecodeKey = function* handleEncryptionDecodeKey({ password
const user = yield select(getUserSelector);
// Fetch server stored e2e keys
- const keys = yield RocketChat.e2eFetchMyKeys();
+ const keys = yield Services.e2eFetchMyKeys();
const publicKey = EJSON.parse(keys?.publicKey);
diff --git a/app/sagas/init.js b/app/sagas/init.js
index 78f2de3d7..9c2f8619f 100644
--- a/app/sagas/init.js
+++ b/app/sagas/init.js
@@ -1,20 +1,20 @@
import { put, takeLatest } from 'redux-saga/effects';
import RNBootSplash from 'react-native-bootsplash';
-import { BIOMETRY_ENABLED_KEY } from '../lib/constants';
+import { BIOMETRY_ENABLED_KEY, CURRENT_SERVER, TOKEN_KEY } from '../lib/constants';
import UserPreferences from '../lib/methods/userPreferences';
import { selectServerRequest } from '../actions/server';
import { setAllPreferences } from '../actions/sortPreferences';
import { APP } from '../actions/actionsTypes';
-import RocketChat from '../lib/rocketchat';
import log from '../utils/log';
import database from '../lib/database';
import { localAuthenticate } from '../utils/localAuthentication';
import { appReady, appStart } from '../actions/app';
import { RootEnum } from '../definitions';
+import { getSortPreferences } from '../lib/methods';
export const initLocalSettings = function* initLocalSettings() {
- const sortPreferences = RocketChat.getSortPreferences();
+ const sortPreferences = getSortPreferences();
yield put(setAllPreferences(sortPreferences));
};
@@ -22,8 +22,8 @@ const BIOMETRY_MIGRATION_KEY = 'kBiometryMigration';
const restore = function* restore() {
try {
- const server = UserPreferences.getString(RocketChat.CURRENT_SERVER);
- let userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
+ const server = UserPreferences.getString(CURRENT_SERVER);
+ let userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
// Migration biometry setting from WatermelonDB to MMKV
// TODO: remove it after a few versions
@@ -48,7 +48,7 @@ const restore = function* restore() {
if (servers.length > 0) {
for (let i = 0; i < servers.length; i += 1) {
const newServer = servers[i].id;
- userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${newServer}`);
+ userId = UserPreferences.getString(`${TOKEN_KEY}-${newServer}`);
if (userId) {
return yield put(selectServerRequest(newServer));
}
diff --git a/app/sagas/inviteLinks.js b/app/sagas/inviteLinks.js
index f37048074..e9bee9d28 100644
--- a/app/sagas/inviteLinks.js
+++ b/app/sagas/inviteLinks.js
@@ -3,20 +3,21 @@ import { Alert } from 'react-native';
import { INVITE_LINKS } from '../actions/actionsTypes';
import { inviteLinksFailure, inviteLinksSetInvite, inviteLinksSuccess } from '../actions/inviteLinks';
-import RocketChat from '../lib/rocketchat';
import log from '../utils/log';
import Navigation from '../lib/navigation/appNavigation';
import I18n from '../i18n';
+import { getRoomTitle } from '../lib/methods';
+import { Services } from '../lib/services';
const handleRequest = function* handleRequest({ token }) {
try {
- const validateResult = yield RocketChat.validateInviteToken(token);
+ const validateResult = yield Services.validateInviteToken(token);
if (!validateResult.valid) {
yield put(inviteLinksFailure());
return;
}
- const result = yield RocketChat.inviteToken(token);
+ const result = yield Services.inviteToken(token);
if (!result.success) {
yield put(inviteLinksFailure());
return;
@@ -28,7 +29,7 @@ const handleRequest = function* handleRequest({ token }) {
const { room } = result;
Navigation.navigate('RoomView', {
rid: room.rid,
- name: RocketChat.getRoomTitle(room),
+ name: getRoomTitle(room),
t: room.t
});
}
@@ -47,7 +48,7 @@ const handleFailure = function handleFailure() {
const handleCreateInviteLink = function* handleCreateInviteLink({ rid }) {
try {
const inviteLinks = yield select(state => state.inviteLinks);
- const result = yield RocketChat.findOrCreateInvite({
+ const result = yield Services.findOrCreateInvite({
rid,
days: inviteLinks.days,
maxUses: inviteLinks.maxUses
diff --git a/app/sagas/login.js b/app/sagas/login.js
index d7cb94c54..4ff0a6ba5 100644
--- a/app/sagas/login.js
+++ b/app/sagas/login.js
@@ -5,7 +5,7 @@ import { Q } from '@nozbe/watermelondb';
import * as types from '../actions/actionsTypes';
import { appStart } from '../actions/app';
import { selectServerRequest, serverFinishAdd } from '../actions/server';
-import { loginFailure, loginSuccess, logout, setUser } from '../actions/login';
+import { loginFailure, loginSuccess, logout as logoutAction, setUser } from '../actions/login';
import { roomsRequest } from '../actions/rooms';
import RocketChat from '../lib/rocketchat';
import log, { events, logEvent } from '../utils/log';
@@ -21,10 +21,22 @@ import { inquiryRequest, inquiryReset } from '../ee/omnichannel/actions/inquiry'
import { isOmnichannelStatusAvailable } from '../ee/omnichannel/lib';
import { RootEnum } from '../definitions';
import sdk from '../lib/services/sdk';
+import { TOKEN_KEY } from '../lib/constants';
+import {
+ getCustomEmojis,
+ getEnterpriseModules,
+ getPermissions,
+ getRoles,
+ getSlashCommands,
+ getUserPresence,
+ isOmnichannelModuleAvailable,
+ subscribeSettings
+} from '../lib/methods';
+import { Services } from '../lib/services';
const getServer = state => state.server.server;
-const loginWithPasswordCall = args => RocketChat.loginWithPassword(args);
-const loginCall = (credentials, isFromWebView) => RocketChat.login(credentials, isFromWebView);
+const loginWithPasswordCall = args => Services.loginWithPassword(args);
+const loginCall = (credentials, isFromWebView) => Services.login(credentials, isFromWebView);
const logoutCall = args => RocketChat.logout(args);
const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnError = false, isFromWebView = false }) {
@@ -66,9 +78,9 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
}
} catch (e) {
if (e?.data?.message && /you've been logged out by the server/i.test(e.data.message)) {
- yield put(logout(true, 'Logged_out_by_server'));
+ yield put(logoutAction(true, 'Logged_out_by_server'));
} else if (e?.data?.message && /your session has expired/i.test(e.data.message)) {
- yield put(logout(true, 'Token_expired'));
+ yield put(logoutAction(true, 'Token_expired'));
} else {
logEvent(events.LOGIN_DEFAULT_LOGIN_F);
yield put(loginFailure(e));
@@ -76,61 +88,61 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
}
};
-const subscribeSettings = function* subscribeSettings() {
- yield RocketChat.subscribeSettings();
+const subscribeSettingsFork = function* subscribeSettingsFork() {
+ yield subscribeSettings();
};
-const fetchPermissions = function* fetchPermissions() {
- yield RocketChat.getPermissions();
+const fetchPermissionsFork = function* fetchPermissionsFork() {
+ yield getPermissions();
};
-const fetchCustomEmojis = function* fetchCustomEmojis() {
- yield RocketChat.getCustomEmojis();
+const fetchCustomEmojisFork = function* fetchCustomEmojisFork() {
+ yield getCustomEmojis();
};
-const fetchRoles = function* fetchRoles() {
+const fetchRolesFork = function* fetchRolesFork() {
sdk.subscribe('stream-roles', 'roles');
- yield RocketChat.getRoles();
+ yield getRoles();
};
-const fetchSlashCommands = function* fetchSlashCommands() {
- yield RocketChat.getSlashCommands();
+const fetchSlashCommandsFork = function* fetchSlashCommandsFork() {
+ yield getSlashCommands();
};
-const registerPushToken = function* registerPushToken() {
- yield RocketChat.registerPushToken();
+const registerPushTokenFork = function* registerPushTokenFork() {
+ yield Services.registerPushToken();
};
-const fetchUsersPresence = function* fetchUserPresence() {
+const fetchUsersPresenceFork = function* fetchUsersPresenceFork() {
RocketChat.subscribeUsersPresence();
};
-const fetchEnterpriseModules = function* fetchEnterpriseModules({ user }) {
- yield RocketChat.getEnterpriseModules();
+const fetchEnterpriseModulesFork = function* fetchEnterpriseModulesFork({ user }) {
+ yield getEnterpriseModules();
- if (isOmnichannelStatusAvailable(user) && RocketChat.isOmnichannelModuleAvailable()) {
+ if (isOmnichannelStatusAvailable(user) && isOmnichannelModuleAvailable()) {
yield put(inquiryRequest());
}
};
-const fetchRooms = function* fetchRooms() {
+const fetchRoomsFork = function* fetchRoomsFork() {
yield put(roomsRequest());
};
const handleLoginSuccess = function* handleLoginSuccess({ user }) {
try {
- RocketChat.getUserPresence(user.id);
+ getUserPresence(user.id);
const server = yield select(getServer);
- yield fork(fetchRooms);
- yield fork(fetchPermissions);
- yield fork(fetchCustomEmojis);
- yield fork(fetchRoles);
- yield fork(fetchSlashCommands);
- yield fork(registerPushToken);
- yield fork(fetchUsersPresence);
- yield fork(fetchEnterpriseModules, { user });
- yield fork(subscribeSettings);
+ yield fork(fetchRoomsFork);
+ yield fork(fetchPermissionsFork);
+ yield fork(fetchCustomEmojisFork);
+ yield fork(fetchRolesFork);
+ yield fork(fetchSlashCommandsFork);
+ yield fork(registerPushTokenFork);
+ yield fork(fetchUsersPresenceFork);
+ yield fork(fetchEnterpriseModulesFork, { user });
+ yield fork(subscribeSettingsFork);
yield put(encryptionInit());
setLanguage(user?.language);
@@ -164,8 +176,8 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
}
});
- UserPreferences.setString(`${RocketChat.TOKEN_KEY}-${server}`, user.id);
- UserPreferences.setString(`${RocketChat.TOKEN_KEY}-${user.id}`, user.token);
+ UserPreferences.setString(`${TOKEN_KEY}-${server}`, user.id);
+ UserPreferences.setString(`${TOKEN_KEY}-${user.id}`, user.token);
yield put(setUser(user));
EventEmitter.emit('connected');
@@ -205,7 +217,7 @@ const handleLogout = function* handleLogout({ forcedByServer, message }) {
if (servers.length > 0) {
for (let i = 0; i < servers.length; i += 1) {
const newServer = servers[i].id;
- const token = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${newServer}`);
+ const token = UserPreferences.getString(`${TOKEN_KEY}-${newServer}`);
if (token) {
yield put(selectServerRequest(newServer));
return;
@@ -225,7 +237,7 @@ const handleLogout = function* handleLogout({ forcedByServer, message }) {
const handleSetUser = function* handleSetUser({ user }) {
setLanguage(user?.language);
- if (user?.statusLivechat && RocketChat.isOmnichannelModuleAvailable()) {
+ if (user?.statusLivechat && isOmnichannelModuleAvailable()) {
if (isOmnichannelStatusAvailable(user)) {
yield put(inquiryRequest());
} else {
diff --git a/app/sagas/messages.js b/app/sagas/messages.js
index 2f38c2975..bf2ea1275 100644
--- a/app/sagas/messages.js
+++ b/app/sagas/messages.js
@@ -3,10 +3,10 @@ import { Q } from '@nozbe/watermelondb';
import Navigation from '../lib/navigation/appNavigation';
import { MESSAGES } from '../actions/actionsTypes';
-import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
import log from '../utils/log';
import { goRoom } from '../utils/goRoom';
+import { Services } from '../lib/services';
const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
try {
@@ -25,7 +25,7 @@ const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
if (subscriptions.length) {
goRoom({ item: subscriptions[0], isMasterDetail, message });
} else {
- const result = yield RocketChat.createDirectMessage(username);
+ const result = yield Services.createDirectMessage(username);
if (result?.success) {
goRoom({ item: result?.room, isMasterDetail, message });
}
diff --git a/app/sagas/room.js b/app/sagas/room.js
index 10d615a0b..7e00e6a71 100644
--- a/app/sagas/room.js
+++ b/app/sagas/room.js
@@ -6,11 +6,11 @@ import EventEmitter from '../utils/events';
import Navigation from '../lib/navigation/appNavigation';
import * as types from '../actions/actionsTypes';
import { removedRoom } from '../actions/room';
-import RocketChat from '../lib/rocketchat';
import log, { events, logEvent } from '../utils/log';
import I18n from '../i18n';
import { showErrorAlert } from '../utils/info';
import { LISTENER } from '../containers/Toast';
+import { Services } from '../lib/services';
const watchUserTyping = function* watchUserTyping({ rid, status }) {
const auth = yield select(state => state.login.isAuthenticated);
@@ -19,11 +19,11 @@ const watchUserTyping = function* watchUserTyping({ rid, status }) {
}
try {
- yield RocketChat.emitTyping(rid, status);
+ yield Services.emitTyping(rid, status);
if (status) {
yield delay(5000);
- yield RocketChat.emitTyping(rid, false);
+ yield Services.emitTyping(rid, false);
}
} catch (e) {
log(e);
@@ -65,9 +65,9 @@ const handleLeaveRoom = function* handleLeaveRoom({ room, roomType, selected })
let result = {};
if (roomType === 'channel') {
- result = yield RocketChat.leaveRoom(room.rid, room.t);
+ result = yield Services.leaveRoom(room.rid, room.t);
} else if (roomType === 'team') {
- result = yield RocketChat.leaveTeam({ teamId: room.teamId, ...(selected && { rooms: selected }) });
+ result = yield Services.leaveTeam({ teamId: room.teamId, ...(selected && { rooms: selected }) });
}
if (result?.success) {
@@ -91,9 +91,9 @@ const handleDeleteRoom = function* handleDeleteRoom({ room, roomType, selected }
let result = {};
if (roomType === 'channel') {
- result = yield RocketChat.deleteRoom(room.rid, room.t);
+ result = yield Services.deleteRoom(room.rid, room.t);
} else if (roomType === 'team') {
- result = yield RocketChat.deleteTeam({ teamId: room.teamId, ...(selected && { roomsToRemove: selected }) });
+ result = yield Services.deleteTeam({ teamId: room.teamId, ...(selected && { roomsToRemove: selected }) });
}
if (result?.success) {
@@ -116,7 +116,7 @@ const handleCloseRoom = function* handleCloseRoom({ rid }) {
const closeRoom = async (comment = '') => {
try {
- await RocketChat.closeLivechat(rid, comment);
+ await Services.closeLivechat(rid, comment);
if (isMasterDetail) {
Navigation.navigate('DrawerNavigator');
} else {
@@ -150,7 +150,7 @@ const handleCloseRoom = function* handleCloseRoom({ rid }) {
const handleForwardRoom = function* handleForwardRoom({ transferData }) {
try {
- const result = yield RocketChat.forwardLivechat(transferData);
+ const result = yield Services.forwardLivechat(transferData);
if (result === true) {
const isMasterDetail = yield select(state => state.app.isMasterDetail);
if (isMasterDetail) {
diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js
index 4787c2714..ee7cacef4 100644
--- a/app/sagas/rooms.js
+++ b/app/sagas/rooms.js
@@ -9,6 +9,7 @@ import log from '../utils/log';
import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRooms';
import RocketChat from '../lib/rocketchat';
import buildMessage from '../lib/methods/helpers/buildMessage';
+import { getRooms } from '../lib/methods';
const updateRooms = function* updateRooms({ server, newRoomsUpdatedAt }) {
const serversDB = database.servers;
@@ -45,7 +46,7 @@ const handleRoomsRequest = function* handleRoomsRequest({ params }) {
}
}
- const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
+ const [subscriptionsResult, roomsResult] = yield getRooms(roomsUpdatedAt);
const subscriptions = yield mergeSubscriptionsRooms(subscriptionsResult, roomsResult);
const db = database.active;
const subCollection = db.get('subscriptions');
diff --git a/app/sagas/selectServer.js b/app/sagas/selectServer.js
index b58a61642..ee211c1e9 100644
--- a/app/sagas/selectServer.js
+++ b/app/sagas/selectServer.js
@@ -22,13 +22,16 @@ import { encryptionStop } from '../actions/encryption';
import SSLPinning from '../utils/sslPinning';
import { inquiryReset } from '../ee/omnichannel/actions/inquiry';
import { RootEnum } from '../definitions';
+import { CERTIFICATE_KEY, CURRENT_SERVER, TOKEN_KEY } from '../lib/constants';
+import { getLoginSettings, setCustomEmojis, setEnterpriseModules, setPermissions, setRoles, setSettings } from '../lib/methods';
+import { Services } from '../lib/services';
const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
try {
- const serverInfo = yield RocketChat.getServerInfo(server);
+ const serverInfo = yield Services.getServerInfo(server);
let websocketInfo = { success: true };
if (raiseError) {
- websocketInfo = yield RocketChat.getWebsocketInfo({ server });
+ websocketInfo = yield Services.getWebsocketInfo({ server });
}
if (!serverInfo.success || !websocketInfo.success) {
if (raiseError) {
@@ -69,14 +72,14 @@ const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
const handleSelectServer = function* handleSelectServer({ server, version, fetchVersion }) {
try {
// SSL Pinning - Read certificate alias and set it to be used by network requests
- const certificate = UserPreferences.getString(`${RocketChat.CERTIFICATE_KEY}-${server}`);
+ const certificate = UserPreferences.getString(`${CERTIFICATE_KEY}-${server}`);
SSLPinning.setCertificate(certificate, server);
yield put(inquiryReset());
yield put(encryptionStop());
yield put(clearActiveUsers());
const serversDB = database.servers;
- UserPreferences.setString(RocketChat.CURRENT_SERVER, server);
- const userId = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${server}`);
+ UserPreferences.setString(CURRENT_SERVER, server);
+ const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`);
const userCollections = serversDB.get('users');
let user = null;
if (userId) {
@@ -96,7 +99,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
};
} catch {
// search credentials on shared credentials (Experimental/Official)
- const token = UserPreferences.getString(`${RocketChat.TOKEN_KEY}-${userId}`);
+ const token = UserPreferences.getString(`${TOKEN_KEY}-${userId}`);
if (token) {
user = { token };
}
@@ -107,7 +110,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
setBasicAuth(basicAuth);
// Check for running requests and abort them before connecting to the server
- RocketChat.abort();
+ Services.abort();
if (user) {
yield put(clearSettings());
@@ -122,11 +125,11 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
// We can't use yield here because fetch of Settings & Custom Emojis is slower
// and block the selectServerSuccess raising multiples errors
- RocketChat.setSettings();
- RocketChat.setCustomEmojis();
- RocketChat.setPermissions();
- RocketChat.setRoles();
- RocketChat.setEnterpriseModules();
+ setSettings();
+ setCustomEmojis();
+ setPermissions();
+ setRoles();
+ setEnterpriseModules();
let serverInfo;
if (fetchVersion) {
@@ -148,7 +151,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
const handleServerRequest = function* handleServerRequest({ server, username, fromServerHistory }) {
try {
// SSL Pinning - Read certificate alias and set it to be used by network requests
- const certificate = UserPreferences.getString(`${RocketChat.CERTIFICATE_KEY}-${server}`);
+ const certificate = UserPreferences.getString(`${CERTIFICATE_KEY}-${server}`);
SSLPinning.setCertificate(certificate, server);
const serverInfo = yield getServerInfo({ server });
@@ -156,8 +159,8 @@ const handleServerRequest = function* handleServerRequest({ server, username, fr
const serversHistoryCollection = serversDB.get('servers_history');
if (serverInfo) {
- yield RocketChat.getLoginServices(server);
- yield RocketChat.getLoginSettings({ server });
+ yield Services.getLoginServices(server);
+ yield getLoginSettings({ server });
Navigation.navigate('WorkspaceView');
if (fromServerHistory) {
diff --git a/app/sagas/state.js b/app/sagas/state.js
index 0e00e9bb7..86b1de62c 100644
--- a/app/sagas/state.js
+++ b/app/sagas/state.js
@@ -1,11 +1,11 @@
import { select, takeLatest } from 'redux-saga/effects';
-import RocketChat from '../lib/rocketchat';
import Push from '../lib/notifications/push';
import log from '../utils/log';
import { localAuthenticate, saveLastLocalAuthenticationSession } from '../utils/localAuthentication';
import { APP_STATE } from '../actions/actionsTypes';
import { RootEnum } from '../definitions';
+import { Services } from '../lib/services';
const appHasComeBackToForeground = function* appHasComeBackToForeground() {
const appRoot = yield select(state => state.app.root);
@@ -19,9 +19,9 @@ const appHasComeBackToForeground = function* appHasComeBackToForeground() {
}
try {
yield localAuthenticate(server.server);
- RocketChat.checkAndReopen();
+ Services.checkAndReopen();
Push.setBadgeCount();
- return yield RocketChat.setUserPresenceOnline();
+ return yield Services.setUserPresenceOnline();
} catch (e) {
log(e);
}
@@ -36,7 +36,7 @@ const appHasComeBackToBackground = function* appHasComeBackToBackground() {
const server = yield select(state => state.server.server);
yield saveLastLocalAuthenticationSession(server);
- yield RocketChat.setUserPresenceAway();
+ yield Services.setUserPresenceAway();
} catch (e) {
log(e);
}
diff --git a/app/share.tsx b/app/share.tsx
index 53988c7eb..e4836d501 100644
--- a/app/share.tsx
+++ b/app/share.tsx
@@ -10,9 +10,8 @@ import UserPreferences from './lib/methods/userPreferences';
import Navigation from './lib/navigation/shareNavigation';
import store from './lib/store';
import { initStore } from './lib/store/auxStore';
-import { closeShareExtension, shareExtensionInit } from './lib/services/shareExtension';
+import { closeShareExtension, shareExtensionInit } from './lib/methods/shareExtension';
import { defaultHeader, getActiveRouteName, navigationTheme, themedHeader } from './utils/navigation';
-import RocketChat from './lib/rocketchat';
import { ThemeContext, TSupportedThemes } from './theme';
import { localAuthenticate } from './utils/localAuthentication';
import { IThemePreference } from './definitions/ITheme';
@@ -28,7 +27,7 @@ import AuthLoadingView from './views/AuthLoadingView';
import { DimensionsContext } from './dimensions';
import debounce from './utils/debounce';
import { ShareInsideStackParamList, ShareOutsideStackParamList, ShareAppStackParamList } from './definitions/navigationTypes';
-import { colors } from './lib/constants';
+import { colors, CURRENT_SERVER } from './lib/constants';
initStore(store);
@@ -114,7 +113,7 @@ class Root extends React.Component<{}, IState> {
}
init = async () => {
- const currentServer = UserPreferences.getString(RocketChat.CURRENT_SERVER);
+ const currentServer = UserPreferences.getString(CURRENT_SERVER);
if (currentServer) {
await localAuthenticate(currentServer);
diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx
index 6c6c0249a..112ee4ae1 100644
--- a/app/stacks/InsideStack.tsx
+++ b/app/stacks/InsideStack.tsx
@@ -115,11 +115,7 @@ const ChatsStackNavigator = () => {
component={NotificationPrefView}
options={NotificationPrefView.navigationOptions}
/>
-
+
{
options={E2EEncryptionSecurityView.navigationOptions}
/>
-
+
{
return (
}
drawerPosition={I18nManager.isRTL ? 'right' : 'left'}
screenOptions={{ swipeEnabled: false }}
diff --git a/app/stacks/MasterDetailStack/index.tsx b/app/stacks/MasterDetailStack/index.tsx
index 63d876d9e..2fa7cd4ea 100644
--- a/app/stacks/MasterDetailStack/index.tsx
+++ b/app/stacks/MasterDetailStack/index.tsx
@@ -158,11 +158,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
component={NotificationPrefView}
options={NotificationPrefView.navigationOptions}
/>
-
+
@@ -182,7 +178,7 @@ const ModalStackNavigator = React.memo(({ navigation }: INavigation) => {
options={props => SettingsView.navigationOptions!({ ...props, isMasterDetail: true })}
/>
-
+
void;
showAlert?: () => void;
isSearch?: boolean;
- onSearch?: (text: string) => Promise | any>;
+ onSearch?: (text: string) => Promise;
isRadio?: boolean;
};
RoomInfoView: {
@@ -101,7 +101,7 @@ export type ChatsStackParamList = {
DirectoryView: undefined;
NotificationPrefView: {
rid: string;
- room: Model;
+ room: TSubscriptionModel;
};
ForwardLivechatView: {
rid: string;
@@ -126,6 +126,7 @@ export type ChatsStackParamList = {
};
TeamChannelsView: {
teamId: string;
+ joined: boolean;
};
CreateChannelView: {
isTeam?: boolean; // TODO: To check
@@ -133,11 +134,11 @@ export type ChatsStackParamList = {
};
AddChannelTeamView: {
teamId?: string;
- teamChannels: []; // TODO: Change
+ teamChannels: IItem[];
};
AddExistingChannelView: {
teamId?: string;
- teamChannels: []; // TODO: Change
+ teamChannels: IItem[];
};
MarkdownTableView: {
renderRows: (drawExtraBorders?: boolean) => JSX.Element;
@@ -207,7 +208,7 @@ export type NewMessageStackParamList = {
buttonText?: string;
nextAction?: Function;
}; // TODO: Change
- CreateChannelView: {
+ CreateChannelView?: {
isTeam?: boolean; // TODO: To check
teamId?: string;
};
diff --git a/app/theme.tsx b/app/theme.tsx
index 350402d98..b11488119 100644
--- a/app/theme.tsx
+++ b/app/theme.tsx
@@ -8,7 +8,7 @@ import { colors } from './lib/constants';
export type TSupportedThemes = keyof typeof colors;
export type TColors = typeof colors[TSupportedThemes];
-interface IThemeContextProps {
+export interface IThemeContextProps {
theme: TSupportedThemes;
themePreferences?: IThemePreference;
setTheme?: (newTheme?: {}) => void;
diff --git a/app/utils/fetch.ts b/app/utils/fetch.ts
index 51a7c7173..17569798e 100644
--- a/app/utils/fetch.ts
+++ b/app/utils/fetch.ts
@@ -48,6 +48,7 @@ export default (url: string, options: IOptions = {}): Promise => {
}
// TODO: Refactor when migrate rocketchat.js
// @ts-ignore
+ // WHAT?
if (RocketChat.controller) {
// @ts-ignore
const { signal } = RocketChat.controller;
diff --git a/app/utils/goRoom.ts b/app/utils/goRoom.ts
index 46de9fb11..0ad369e0c 100644
--- a/app/utils/goRoom.ts
+++ b/app/utils/goRoom.ts
@@ -1,7 +1,8 @@
import { ChatsStackParamList } from '../stacks/types';
import Navigation from '../lib/navigation/appNavigation';
-import RocketChat from '../lib/rocketchat';
import { IOmnichannelRoom, SubscriptionType, IVisitor, TSubscriptionModel, ISubscription } from '../definitions';
+import { getRoomTitle, getUidDirectMessage } from '../lib/methods';
+import { Services } from '../lib/services';
interface IGoRoomItem {
search?: boolean; // comes from spotlight
@@ -32,12 +33,12 @@ const navigate = ({
navigationMethod('RoomView', {
rid: item.rid,
- name: RocketChat.getRoomTitle(item),
+ name: getRoomTitle(item),
t: item.t,
prid: item.prid,
room: item,
visitor: item.visitor,
- roomUserId: RocketChat.getUidDirectMessage(item),
+ roomUserId: getUidDirectMessage(item),
...props
});
};
@@ -62,7 +63,7 @@ export const goRoom = async ({
// if user is using the search we need first to join/create room
try {
const { username } = item;
- const result = await RocketChat.createDirectMessage(username as string);
+ const result = await Services.createDirectMessage(username as string);
if (result.success && result?.room?._id) {
return navigate({
item: {
diff --git a/app/utils/isReadOnly.ts b/app/utils/isReadOnly.ts
index 9e41362b5..2cb6c11e9 100644
--- a/app/utils/isReadOnly.ts
+++ b/app/utils/isReadOnly.ts
@@ -1,11 +1,11 @@
-import RocketChat from '../lib/rocketchat';
import { store as reduxStore } from '../lib/store/auxStore';
import { ISubscription } from '../definitions/ISubscription';
+import { hasPermission } from '../lib/methods';
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);
+ const permission = await hasPermission([postReadOnlyPermission], rid);
return permission[0];
};
diff --git a/app/utils/localAuthentication.ts b/app/utils/localAuthentication.ts
index f094eee8c..ec72efbb1 100644
--- a/app/utils/localAuthentication.ts
+++ b/app/utils/localAuthentication.ts
@@ -50,11 +50,13 @@ export const saveLastLocalAuthenticationSession = async (
export const resetAttempts = (): Promise => AsyncStorage.multiRemove([LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY]);
-const openModal = (hasBiometry: boolean) =>
- new Promise(resolve => {
+const openModal = (hasBiometry: boolean, force?: boolean) =>
+ new Promise((resolve, reject) => {
EventEmitter.emit(LOCAL_AUTHENTICATE_EMITTER, {
submit: () => resolve(),
- hasBiometry
+ hasBiometry,
+ force,
+ cancel: () => reject()
});
});
@@ -100,6 +102,20 @@ export const checkHasPasscode = async ({ force = true }: { force?: boolean }): P
return Promise.resolve();
};
+export const handleLocalAuthentication = async (canCloseModal = false) => {
+ // let hasBiometry = false;
+ let hasBiometry = UserPreferences.getBool(BIOMETRY_ENABLED_KEY) ?? false;
+
+ // if biometry is enabled on the app
+ if (hasBiometry) {
+ const isEnrolled = await LocalAuthentication.isEnrolledAsync();
+ hasBiometry = isEnrolled;
+ }
+
+ // Authenticate
+ await openModal(hasBiometry, canCloseModal);
+};
+
export const localAuthenticate = async (server: string): Promise => {
const serversDB = database.servers;
const serversCollection = serversDB.get('servers');
@@ -136,17 +152,7 @@ export const localAuthenticate = async (server: string): Promise => {
// set isLocalAuthenticated to false
store.dispatch(setLocalAuthenticated(false));
- // let hasBiometry = false;
- let hasBiometry = UserPreferences.getBool(BIOMETRY_ENABLED_KEY) ?? false;
-
- // if biometry is enabled on the app
- if (hasBiometry) {
- const isEnrolled = await LocalAuthentication.isEnrolledAsync();
- hasBiometry = isEnrolled;
- }
-
- // Authenticate
- await openModal(hasBiometry);
+ await handleLocalAuthentication();
// set isLocalAuthenticated to true
store.dispatch(setLocalAuthenticated(true));
diff --git a/app/views/AddExistingChannelView.tsx b/app/views/AddExistingChannelView.tsx
index 361d5c6c8..68e5a0dc1 100644
--- a/app/views/AddExistingChannelView.tsx
+++ b/app/views/AddExistingChannelView.tsx
@@ -7,7 +7,6 @@ import { Q } from '@nozbe/watermelondb';
import * as List from '../containers/List';
import database from '../lib/database';
-import RocketChat from '../lib/rocketchat';
import I18n from '../i18n';
import log, { events, logEvent } from '../utils/log';
import SearchBox from '../containers/SearchBox';
@@ -23,6 +22,8 @@ import { showErrorAlert } from '../utils/info';
import debounce from '../utils/debounce';
import { ChatsStackParamList } from '../stacks/types';
import { TSubscriptionModel, SubscriptionType } from '../definitions';
+import { getRoomTitle, hasPermission } from '../lib/methods';
+import { Services } from '../lib/services';
interface IAddExistingChannelViewState {
search: TSubscriptionModel[];
@@ -100,7 +101,7 @@ class AddExistingChannelView extends React.Component this.toggleChannel(item.rid)}
testID={`add-existing-channel-view-item-${item.name}`}
diff --git a/app/views/AuthLoadingView.tsx b/app/views/AuthLoadingView.tsx
index 1bdeb063d..b3402afec 100644
--- a/app/views/AuthLoadingView.tsx
+++ b/app/views/AuthLoadingView.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
-import { connect } from 'react-redux';
+import { useSelector } from 'react-redux';
+import { IApplicationState } from '../definitions';
import I18n from '../i18n';
import StatusBar from '../containers/StatusBar';
-import { TSupportedThemes, withTheme } from '../theme';
-import { themes } from '../lib/constants';
+import { useTheme } from '../theme';
import sharedStyles from './Styles';
const styles = StyleSheet.create({
@@ -22,25 +22,20 @@ const styles = StyleSheet.create({
}
});
-interface IAuthLoadingView {
- theme: TSupportedThemes;
- text: string;
-}
-
-const AuthLoadingView = React.memo(({ theme, text }: IAuthLoadingView) => (
-
-
- {text ? (
- <>
-
- {`${text}\n${I18n.t('Please_wait')}`}
- >
- ) : null}
-
-));
-
-const mapStateToProps = (state: any) => ({
- text: state.app.text
+const AuthLoadingView = React.memo((): React.ReactElement => {
+ const text = useSelector((state: IApplicationState) => state.app.text);
+ const { colors } = useTheme();
+ return (
+
+
+ {text ? (
+ <>
+
+ {`${text}\n${I18n.t('Please_wait')}`}
+ >
+ ) : null}
+
+ );
});
-export default connect(mapStateToProps)(withTheme(AuthLoadingView));
+export default AuthLoadingView;
diff --git a/app/views/AuthenticationWebView.tsx b/app/views/AuthenticationWebView.tsx
index 66b251522..71d449117 100644
--- a/app/views/AuthenticationWebView.tsx
+++ b/app/views/AuthenticationWebView.tsx
@@ -7,13 +7,13 @@ import { WebViewMessage } from 'react-native-webview/lib/WebViewTypes';
import { RouteProp } from '@react-navigation/core';
import { OutsideModalParamList } from '../stacks/types';
-import RocketChat from '../lib/rocketchat';
import { isIOS } from '../utils/deviceInfo';
import StatusBar from '../containers/StatusBar';
import ActivityIndicator from '../containers/ActivityIndicator';
import { TSupportedThemes, withTheme } from '../theme';
import debounce from '../utils/debounce';
import * as HeaderButton from '../containers/HeaderButton';
+import { Services } from '../lib/services';
const userAgent = isIOS
? 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'
@@ -102,7 +102,7 @@ class AuthenticationWebView extends React.PureComponent;
- theme: TSupportedThemes;
-}
+type TAutoTranslateViewProps = IBaseScreen;
-class AutoTranslateView extends React.Component {
+class AutoTranslateView extends React.Component {
static navigationOptions = () => ({
title: I18n.t('Auto_Translate')
});
private mounted: boolean;
private rid: string;
- private roomObservable: any;
- private subscription: any;
+ private roomObservable?: Observable;
+ private subscription?: Subscription;
- constructor(props: IAutoTranslateViewProps) {
+ constructor(props: TAutoTranslateViewProps) {
super(props);
this.mounted = false;
this.rid = props.route.params?.rid ?? '';
@@ -64,7 +61,7 @@ class AutoTranslateView extends React.Component {
async componentDidMount() {
this.mounted = true;
try {
- const languages = await RocketChat.getSupportedLanguagesAutoTranslate();
+ const languages = await Services.getSupportedLanguagesAutoTranslate();
this.setState({ languages });
} catch (error) {
console.log(error);
@@ -81,7 +78,7 @@ class AutoTranslateView extends React.Component {
logEvent(events.AT_TOGGLE_TRANSLATE);
const { enableAutoTranslate } = this.state;
try {
- await RocketChat.saveAutoTranslate({
+ await Services.saveAutoTranslate({
rid: this.rid,
field: 'autoTranslate',
value: enableAutoTranslate ? '0' : '1',
@@ -97,7 +94,7 @@ class AutoTranslateView extends React.Component {
saveAutoTranslateLanguage = async (language: string) => {
logEvent(events.AT_SET_LANG);
try {
- await RocketChat.saveAutoTranslate({
+ await Services.saveAutoTranslate({
rid: this.rid,
field: 'autoTranslateLanguage',
value: language
@@ -111,7 +108,7 @@ class AutoTranslateView extends React.Component {
renderIcon = () => {
const { theme } = this.props;
- return ;
+ return ;
};
renderSwitch = () => {
diff --git a/app/views/CannedResponseDetail.tsx b/app/views/CannedResponseDetail.tsx
index 88136acc8..d27d00c13 100644
--- a/app/views/CannedResponseDetail.tsx
+++ b/app/views/CannedResponseDetail.tsx
@@ -9,7 +9,6 @@ import SafeAreaView from '../containers/SafeAreaView';
import StatusBar from '../containers/StatusBar';
import Button from '../containers/Button';
import { TSupportedThemes, useTheme } from '../theme';
-import RocketChat from '../lib/rocketchat';
import Navigation from '../lib/navigation/appNavigation';
import { goRoom } from '../utils/goRoom';
import { themes } from '../lib/constants';
@@ -17,6 +16,7 @@ import Markdown from '../containers/markdown';
import { ICannedResponse } from '../definitions/ICannedResponse';
import { ChatsStackParamList } from '../stacks/types';
import sharedStyles from './Styles';
+import { getRoomTitle, getUidDirectMessage } from '../lib/methods';
const styles = StyleSheet.create({
scroll: {
@@ -84,7 +84,6 @@ const Item = ({ label, content, theme, testID }: IItem) =>
{label}
- {/* @ts-ignore */}
) : null;
@@ -111,12 +110,12 @@ const CannedResponseDetail = ({ navigation, route }: ICannedResponseDetailProps)
const { name } = room;
const params = {
rid: room.rid,
- name: RocketChat.getRoomTitle({
+ name: getRoomTitle({
t: room.t,
fname: name
}),
- t: room.t as any,
- roomUserId: RocketChat.getUidDirectMessage(room),
+ t: room.t,
+ roomUserId: getUidDirectMessage(room),
usedCannedResponse: item.text
};
diff --git a/app/views/CannedResponsesListView/Dropdown/DropdownItem.tsx b/app/views/CannedResponsesListView/Dropdown/DropdownItem.tsx
index 274a9cef6..84c14ebc5 100644
--- a/app/views/CannedResponsesListView/Dropdown/DropdownItem.tsx
+++ b/app/views/CannedResponsesListView/Dropdown/DropdownItem.tsx
@@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native';
import { themes } from '../../../lib/constants';
import { useTheme } from '../../../theme';
import Touch from '../../../utils/touch';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../../containers/CustomIcon';
import sharedStyles from '../../Styles';
export const ROW_HEIGHT = 44;
@@ -26,7 +26,7 @@ const styles = StyleSheet.create({
interface IDropdownItem {
text: string;
- iconName: string | null;
+ iconName: TIconsName | null;
onPress: () => void;
}
diff --git a/app/views/CannedResponsesListView/Dropdown/DropdownItemFilter.tsx b/app/views/CannedResponsesListView/Dropdown/DropdownItemFilter.tsx
index a2d68c528..fa165c67c 100644
--- a/app/views/CannedResponsesListView/Dropdown/DropdownItemFilter.tsx
+++ b/app/views/CannedResponsesListView/Dropdown/DropdownItemFilter.tsx
@@ -1,12 +1,12 @@
import React from 'react';
-import { IDepartment } from '../../../definitions/ICannedResponse';
+import { ILivechatDepartment } from '../../../definitions/ILivechatDepartment';
import DropdownItem from './DropdownItem';
interface IDropdownItemFilter {
- currentDepartment: IDepartment;
- value: IDepartment;
- onPress: (value: IDepartment) => void;
+ currentDepartment: ILivechatDepartment;
+ value: ILivechatDepartment;
+ onPress: (value: ILivechatDepartment) => void;
}
const DropdownItemFilter = ({ currentDepartment, value, onPress }: IDropdownItemFilter): JSX.Element => (
diff --git a/app/views/CannedResponsesListView/Dropdown/DropdownItemHeader.tsx b/app/views/CannedResponsesListView/Dropdown/DropdownItemHeader.tsx
index ecfa95e8a..5ebcaf860 100644
--- a/app/views/CannedResponsesListView/Dropdown/DropdownItemHeader.tsx
+++ b/app/views/CannedResponsesListView/Dropdown/DropdownItemHeader.tsx
@@ -1,14 +1,14 @@
import React from 'react';
-import { IDepartment } from '../../../definitions/ICannedResponse';
+import { ILivechatDepartment } from '../../../definitions/ILivechatDepartment';
import DropdownItem from './DropdownItem';
interface IDropdownItemHeader {
- department: IDepartment;
+ department: ILivechatDepartment;
onPress: () => void;
}
-const DropdownItemHeader = ({ department, onPress }: IDropdownItemHeader): JSX.Element => (
+const DropdownItemHeader = ({ department, onPress }: IDropdownItemHeader): React.ReactElement => (
);
diff --git a/app/views/CannedResponsesListView/Dropdown/index.tsx b/app/views/CannedResponsesListView/Dropdown/index.tsx
index 8ef425676..58dc52dd3 100644
--- a/app/views/CannedResponsesListView/Dropdown/index.tsx
+++ b/app/views/CannedResponsesListView/Dropdown/index.tsx
@@ -6,19 +6,19 @@ import styles from '../styles';
import { themes } from '../../../lib/constants';
import { TSupportedThemes, withTheme } from '../../../theme';
import * as List from '../../../containers/List';
-import { IDepartment } from '../../../definitions/ICannedResponse';
import DropdownItemFilter from './DropdownItemFilter';
import DropdownItemHeader from './DropdownItemHeader';
import { ROW_HEIGHT } from './DropdownItem';
+import { ILivechatDepartment } from '../../../definitions/ILivechatDepartment';
const ANIMATION_DURATION = 200;
interface IDropdownProps {
theme?: TSupportedThemes;
- currentDepartment: IDepartment;
+ currentDepartment: ILivechatDepartment;
onClose: () => void;
- onDepartmentSelected: (value: IDepartment) => void;
- departments: IDepartment[];
+ onDepartmentSelected: (value: ILivechatDepartment) => void;
+ departments: ILivechatDepartment[];
}
class Dropdown extends React.Component {
diff --git a/app/views/CannedResponsesListView/index.tsx b/app/views/CannedResponsesListView/index.tsx
index 9ed27f83c..33ae96d09 100644
--- a/app/views/CannedResponsesListView/index.tsx
+++ b/app/views/CannedResponsesListView/index.tsx
@@ -14,7 +14,6 @@ import SearchHeader from '../../containers/SearchHeader';
import BackgroundContainer from '../../containers/BackgroundContainer';
import { getHeaderTitlePosition } from '../../containers/Header';
import { useTheme } from '../../theme';
-import RocketChat from '../../lib/rocketchat';
import debounce from '../../utils/debounce';
import Navigation from '../../lib/navigation/appNavigation';
import { goRoom } from '../../utils/goRoom';
@@ -26,9 +25,13 @@ import CannedResponseItem from './CannedResponseItem';
import Dropdown from './Dropdown';
import DropdownItemHeader from './Dropdown/DropdownItemHeader';
import styles from './styles';
-import { ICannedResponse, IDepartment } from '../../definitions/ICannedResponse';
+import { ICannedResponse } from '../../definitions/ICannedResponse';
import { ChatsStackParamList } from '../../stacks/types';
import { ISubscription } from '../../definitions/ISubscription';
+import { getRoomTitle, getUidDirectMessage } from '../../lib/methods';
+import { Services } from '../../lib/services';
+import { IApplicationState } from '../../definitions';
+import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
const COUNT = 25;
@@ -45,7 +48,7 @@ const fixedScopes = [
_id: 'user',
name: I18n.t('Private')
}
-] as IDepartment[];
+] as ILivechatDepartment[];
interface ICannedResponsesListViewProps {
navigation: StackNavigationProp;
@@ -57,7 +60,7 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
const [cannedResponses, setCannedResponses] = useState([]);
const [cannedResponsesScopeName, setCannedResponsesScopeName] = useState([]);
- const [departments, setDepartments] = useState([]);
+ const [departments, setDepartments] = useState([]);
// states used by the filter in Header and Dropdown
const [isSearching, setIsSearching] = useState(false);
@@ -73,8 +76,8 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
const insets = useSafeAreaInsets();
const { theme } = useTheme();
- const { isMasterDetail } = useSelector((state: any) => state.app);
- const { rooms } = useSelector((state: any) => state.room);
+ const isMasterDetail = useSelector((state: IApplicationState) => state.app.isMasterDetail);
+ const rooms = useSelector((state: IApplicationState) => state.room.rooms);
const getRoomFromDb = async () => {
const { rid } = route.params;
@@ -91,9 +94,9 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
const getDepartments = debounce(async () => {
try {
- const res: any = await RocketChat.getDepartments();
+ const res = await Services.getDepartments();
if (res.success) {
- setDepartments([...fixedScopes, ...res.departments]);
+ setDepartments([...fixedScopes, ...(res.departments as ILivechatDepartment[])]);
}
} catch (e) {
setDepartments(fixedScopes);
@@ -114,12 +117,12 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
const { name } = room;
const params = {
rid: room.rid,
- name: RocketChat.getRoomTitle({
+ name: getRoomTitle({
t: room.t,
fname: name
}),
- t: room.t as any,
- roomUserId: RocketChat.getUidDirectMessage(room),
+ t: room.t,
+ roomUserId: getUidDirectMessage(room),
usedCannedResponse: item.text
};
@@ -151,7 +154,7 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
debounced: boolean;
}) => {
try {
- const res = await RocketChat.getListCannedResponse({
+ const res = await Services.getListCannedResponse({
text,
offset,
count: COUNT,
@@ -213,7 +216,7 @@ const CannedResponsesListView = ({ navigation, route }: ICannedResponsesListView
searchCallback(text, scope, departmentId);
};
- const onDepartmentSelect = (value: IDepartment) => {
+ const onDepartmentSelect = (value: ILivechatDepartment) => {
let department = '';
let depId = '';
diff --git a/app/views/ChangePasscodeView.tsx b/app/views/ChangePasscodeView.tsx
index a10da7a76..386ea6720 100644
--- a/app/views/ChangePasscodeView.tsx
+++ b/app/views/ChangePasscodeView.tsx
@@ -10,7 +10,7 @@ import { useTheme } from '../theme';
import { hasNotch, isTablet } from '../utils/deviceInfo';
import { PasscodeChoose } from '../containers/Passcode';
import EventEmitter from '../utils/events';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon } from '../containers/CustomIcon';
import { CHANGE_PASSCODE_EMITTER, themes } from '../lib/constants';
const styles = StyleSheet.create({
diff --git a/app/views/CreateChannelView.tsx b/app/views/CreateChannelView.tsx
index a0b33abbb..4b9b9e0a6 100644
--- a/app/views/CreateChannelView.tsx
+++ b/app/views/CreateChannelView.tsx
@@ -20,10 +20,10 @@ import { Review } from '../utils/review';
import { getUserSelector } from '../selectors/login';
import { events, logEvent } from '../utils/log';
import SafeAreaView from '../containers/SafeAreaView';
-import RocketChat from '../lib/rocketchat';
import sharedStyles from './Styles';
import { ChatsStackParamList } from '../stacks/types';
import { IApplicationState, IBaseScreen, IUser } from '../definitions';
+import { hasPermission } from '../lib/methods';
const styles = StyleSheet.create({
container: {
@@ -224,7 +224,7 @@ class CreateChannelView extends React.Component {
const { createPublicChannelPermission, createPrivateChannelPermission } = this.props;
const permissions = [createPublicChannelPermission, createPrivateChannelPermission];
- const permissionsToCreate = await RocketChat.hasPermission(permissions);
+ const permissionsToCreate = await hasPermission(permissions);
this.setState({ permissions: permissionsToCreate });
};
diff --git a/app/views/CreateDiscussionView/SelectChannel.tsx b/app/views/CreateDiscussionView/SelectChannel.tsx
index a83d639f6..ef11604c3 100644
--- a/app/views/CreateDiscussionView/SelectChannel.tsx
+++ b/app/views/CreateDiscussionView/SelectChannel.tsx
@@ -5,11 +5,11 @@ import { themes } from '../../lib/constants';
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
import { ISearchLocal } from '../../definitions';
import I18n from '../../i18n';
-import RocketChat from '../../lib/rocketchat';
import { avatarURL } from '../../utils/avatar';
import debounce from '../../utils/debounce';
import { ICreateDiscussionViewSelectChannel } from './interfaces';
import styles from './styles';
+import { getRoomAvatar, getRoomTitle, localSearch } from '../../lib/methods';
const SelectChannel = ({
server,
@@ -20,21 +20,21 @@ const SelectChannel = ({
blockUnauthenticatedAccess,
serverVersion,
theme
-}: ICreateDiscussionViewSelectChannel): JSX.Element => {
+}: ICreateDiscussionViewSelectChannel): React.ReactElement => {
const [channels, setChannels] = useState([]);
const getChannels = debounce(async (keyword = '') => {
try {
- const res = await RocketChat.localSearch({ text: keyword });
+ const res = await localSearch({ text: keyword });
setChannels(res);
} catch {
// do nothing
}
}, 300);
- const getAvatar = (item: any) =>
+ const getAvatar = (item: ISearchLocal) =>
avatarURL({
- text: RocketChat.getRoomAvatar(item),
+ text: getRoomAvatar(item),
type: item.t,
user: { id: userId, token },
server,
@@ -55,7 +55,7 @@ const SelectChannel = ({
disabled={!!initial}
options={channels.map(channel => ({
value: channel,
- text: { text: RocketChat.getRoomTitle(channel) },
+ text: { text: getRoomTitle(channel) },
imageUrl: getAvatar(channel)
}))}
onClose={() => setChannels([])}
diff --git a/app/views/CreateDiscussionView/SelectUsers.tsx b/app/views/CreateDiscussionView/SelectUsers.tsx
index 26c3291d9..2a2b5de0d 100644
--- a/app/views/CreateDiscussionView/SelectUsers.tsx
+++ b/app/views/CreateDiscussionView/SelectUsers.tsx
@@ -4,18 +4,13 @@ import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
import debounce from '../../utils/debounce';
import { avatarURL } from '../../utils/avatar';
-import RocketChat from '../../lib/rocketchat';
import I18n from '../../i18n';
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
import { themes } from '../../lib/constants';
import styles from './styles';
import { ICreateDiscussionViewSelectUsers } from './interfaces';
-import { SubscriptionType } from '../../definitions/ISubscription';
-
-interface IUser {
- name: string;
- username: string;
-}
+import { SubscriptionType, IUser } from '../../definitions';
+import { getRoomAvatar, getRoomTitle, search } from '../../lib/methods';
const SelectUsers = ({
server,
@@ -26,12 +21,12 @@ const SelectUsers = ({
blockUnauthenticatedAccess,
serverVersion,
theme
-}: ICreateDiscussionViewSelectUsers): JSX.Element => {
+}: ICreateDiscussionViewSelectUsers): React.ReactElement => {
const [users, setUsers] = useState([]);
const getUsers = debounce(async (keyword = '') => {
try {
- const res = await RocketChat.search({ text: keyword, filterRooms: false });
+ const res = await search({ text: keyword, filterRooms: false });
const selectedUsers = users.filter((u: IUser) => selected.includes(u.name));
const filteredUsers = res.filter(r => !users.find((u: IUser) => u.name === r.name));
const items = [...selectedUsers, ...filteredUsers];
@@ -41,9 +36,9 @@ const SelectUsers = ({
}
}, 300);
- const getAvatar = (item: any) =>
+ const getAvatar = (item: IUser) =>
avatarURL({
- text: RocketChat.getRoomAvatar(item),
+ text: getRoomAvatar(item),
type: SubscriptionType.DIRECT,
user: { id: userId, token },
server,
@@ -61,7 +56,7 @@ const SelectUsers = ({
onChange={onUserSelect}
options={users.map((user: IUser) => ({
value: user.name,
- text: { text: RocketChat.getRoomTitle(user) },
+ text: { text: getRoomTitle(user) },
imageUrl: getAvatar(user)
}))}
onClose={() => setUsers(users.filter((u: IUser) => selected.includes(u.name)))}
diff --git a/app/views/CreateDiscussionView/index.tsx b/app/views/CreateDiscussionView/index.tsx
index 11bb8e6cb..cc6495595 100644
--- a/app/views/CreateDiscussionView/index.tsx
+++ b/app/views/CreateDiscussionView/index.tsx
@@ -12,9 +12,8 @@ import StatusBar from '../../containers/StatusBar';
import { withTheme } from '../../theme';
import { getUserSelector } from '../../selectors/login';
import TextInput from '../../containers/TextInput';
-import RocketChat from '../../lib/rocketchat';
import Navigation from '../../lib/navigation/appNavigation';
-import { createDiscussionRequest } from '../../actions/createDiscussion';
+import { createDiscussionRequest, ICreateDiscussionRequestData } from '../../actions/createDiscussion';
import { showErrorAlert } from '../../utils/info';
import SafeAreaView from '../../containers/SafeAreaView';
import { goRoom } from '../../utils/goRoom';
@@ -22,18 +21,19 @@ import { events, logEvent } from '../../utils/log';
import styles from './styles';
import SelectUsers from './SelectUsers';
import SelectChannel from './SelectChannel';
-import { ICreateChannelViewProps, IResult, IError } from './interfaces';
-import { IApplicationState } from '../../definitions';
+import { ICreateChannelViewProps, IResult, IError, ICreateChannelViewState } from './interfaces';
+import { IApplicationState, ISearchLocal, ISubscription } from '../../definitions';
import { E2E_ROOM_TYPES, SWITCH_TRACK_COLOR, themes } from '../../lib/constants';
+import { getRoomTitle } from '../../lib/methods';
-class CreateChannelView extends React.Component {
- private channel: any;
+class CreateChannelView extends React.Component {
+ private channel: ISubscription;
constructor(props: ICreateChannelViewProps) {
super(props);
const { route } = props;
this.channel = route.params?.channel;
- const message: any = route.params?.message ?? {};
+ const message = route.params?.message ?? {};
this.state = {
channel: this.channel,
message,
@@ -45,7 +45,7 @@ class CreateChannelView extends React.Component {
this.setHeader();
}
- componentDidUpdate(prevProps: any, prevState: any) {
+ componentDidUpdate(prevProps: ICreateChannelViewProps, prevState: ICreateChannelViewState) {
const { channel, name } = this.state;
const { loading, failure, error, result, isMasterDetail } = this.props;
@@ -67,7 +67,7 @@ class CreateChannelView extends React.Component {
}
const item = {
rid,
- name: RocketChat.getRoomTitle(result),
+ name: getRoomTitle(result),
t,
prid
};
@@ -96,7 +96,7 @@ class CreateChannelView extends React.Component {
submit = () => {
const {
name: t_name,
- channel: { prid, rid },
+ channel,
message: { id: pmid },
reply,
users,
@@ -104,8 +104,8 @@ class CreateChannelView extends React.Component {
} = this.state;
const { dispatch } = this.props;
- const params: any = {
- prid: prid || rid,
+ const params: ICreateDiscussionRequestData = {
+ prid: ('prid' in channel && channel.prid) || channel.rid,
pmid,
t_name,
reply,
@@ -121,15 +121,15 @@ class CreateChannelView extends React.Component {
valid = () => {
const { channel, name } = this.state;
- return channel && channel.rid && channel.rid.trim().length && name.trim().length;
+ return channel && channel.rid && channel.rid.trim().length && name?.trim().length;
};
- selectChannel = ({ value }: any) => {
+ selectChannel = ({ value }: { value: ISearchLocal }) => {
logEvent(events.CD_SELECT_CHANNEL);
this.setState({ channel: value, encrypted: value?.encrypted });
};
- selectUsers = ({ value }: any) => {
+ selectUsers = ({ value }: { value: string[] }) => {
logEvent(events.CD_SELECT_USERS);
this.setState({ users: value });
};
@@ -140,7 +140,7 @@ class CreateChannelView extends React.Component {
return encryptionEnabled && E2E_ROOM_TYPES[channel?.t];
}
- onEncryptedChange = (value: any) => {
+ onEncryptedChange = (value: boolean) => {
logEvent(events.CD_TOGGLE_ENCRY);
this.setState({ encrypted: value });
};
@@ -161,7 +161,7 @@ class CreateChannelView extends React.Component {
server={server}
userId={user.id}
token={user.token}
- initial={this.channel && { text: RocketChat.getRoomTitle(this.channel) }}
+ initial={this.channel && { text: getRoomTitle(this.channel) }}
onChannelSelect={this.selectChannel}
blockUnauthenticatedAccess={blockUnauthenticatedAccess}
serverVersion={serverVersion}
diff --git a/app/views/CreateDiscussionView/interfaces.ts b/app/views/CreateDiscussionView/interfaces.ts
index 4264f5550..54c0be177 100644
--- a/app/views/CreateDiscussionView/interfaces.ts
+++ b/app/views/CreateDiscussionView/interfaces.ts
@@ -1,6 +1,6 @@
import { NewMessageStackParamList } from '../../stacks/types';
-import { SubscriptionType } from '../../definitions/ISubscription';
-import { IBaseScreen } from '../../definitions';
+import { ISubscription, SubscriptionType } from '../../definitions/ISubscription';
+import { IBaseScreen, IMessage, ISearchLocal, IUser } from '../../definitions';
import { TSupportedThemes } from '../../theme';
export interface IResult {
@@ -14,10 +14,7 @@ export interface IError {
}
export interface ICreateChannelViewProps extends IBaseScreen {
server: string;
- user: {
- id: string;
- token: string;
- };
+ user: IUser;
create: Function;
loading: boolean;
result: IResult;
@@ -29,6 +26,15 @@ export interface ICreateChannelViewProps extends IBaseScreen;
class DefaultBrowserView extends React.Component {
- private mounted?: boolean;
-
static navigationOptions = (): StackNavigationOptions => ({
title: I18n.t('Default_browser')
});
@@ -74,7 +72,6 @@ class DefaultBrowserView extends React.Component {
if (installed) {
- if (this.mounted) {
- this.setState(({ supported }) => ({ supported: [...supported, browser] }));
- } else {
- const { supported } = this.state;
- // @ts-ignore
- this.state.supported = [...supported, browser];
- }
+ this.setState(({ supported }) => ({ supported: [...supported, browser] }));
}
});
});
diff --git a/app/views/DirectoryView/Options.tsx b/app/views/DirectoryView/Options.tsx
index b950cfc48..c1c59a5d3 100644
--- a/app/views/DirectoryView/Options.tsx
+++ b/app/views/DirectoryView/Options.tsx
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import { Animated, Easing, Switch, Text, TouchableWithoutFeedback, View } from 'react-native';
import Touch from '../../utils/touch';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import Check from '../../containers/Check';
import I18n from '../../i18n';
import { SWITCH_TRACK_COLOR, themes } from '../../lib/constants';
@@ -52,7 +52,7 @@ export default class DirectoryOptions extends PureComponent {
const { changeType, type: propType, theme } = this.props;
let text = 'Users';
- let icon = 'user';
+ let icon: TIconsName = 'user';
if (itemType === 'channels') {
text = 'Channels';
icon = 'channel-public';
@@ -70,7 +70,7 @@ export default class DirectoryOptions extends PureComponent
-
+
{I18n.t(text)}
{propType === itemType ? : null}
@@ -104,9 +104,10 @@ export default class DirectoryOptions extends PureComponent
{I18n.t('Search_by')}
diff --git a/app/views/DirectoryView/index.tsx b/app/views/DirectoryView/index.tsx
index 28e3415ca..e186cea62 100644
--- a/app/views/DirectoryView/index.tsx
+++ b/app/views/DirectoryView/index.tsx
@@ -1,17 +1,18 @@
import React from 'react';
-import { FlatList, Text, View } from 'react-native';
+import { FlatList, ListRenderItem, Text, View } from 'react-native';
import { connect } from 'react-redux';
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
+import { CompositeNavigationProp } from '@react-navigation/native';
import { ChatsStackParamList } from '../../stacks/types';
+import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
import * as List from '../../containers/List';
import Touch from '../../utils/touch';
-import RocketChat from '../../lib/rocketchat';
import DirectoryItem from '../../containers/DirectoryItem';
import sharedStyles from '../Styles';
import I18n from '../../i18n';
import SearchBox from '../../containers/SearchBox';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import StatusBar from '../../containers/StatusBar';
import ActivityIndicator from '../../containers/ActivityIndicator';
import * as HeaderButton from '../../containers/HeaderButton';
@@ -21,24 +22,36 @@ import { TSupportedThemes, withTheme } from '../../theme';
import { themes } from '../../lib/constants';
import { getUserSelector } from '../../selectors/login';
import SafeAreaView from '../../containers/SafeAreaView';
-import { goRoom } from '../../utils/goRoom';
+import { goRoom, TGoRoomItem } from '../../utils/goRoom';
+import { IApplicationState, IServerRoom, IUser, SubscriptionType } from '../../definitions';
import styles from './styles';
import Options from './Options';
+import { Services } from '../../lib/services';
interface IDirectoryViewProps {
- navigation: StackNavigationProp;
+ navigation: CompositeNavigationProp<
+ StackNavigationProp,
+ StackNavigationProp
+ >;
baseUrl: string;
isFederationEnabled: boolean;
- user: {
- id: string;
- token: string;
- };
+ user: IUser;
theme: TSupportedThemes;
directoryDefaultView: string;
isMasterDetail: boolean;
}
-class DirectoryView extends React.Component {
+interface IDirectoryViewState {
+ data: IServerRoom[];
+ loading: boolean;
+ text: string;
+ total: number;
+ showOptionsDropdown: boolean;
+ globalUsers: boolean;
+ type: string;
+}
+
+class DirectoryView extends React.Component {
static navigationOptions = ({ navigation, isMasterDetail }: IDirectoryViewProps) => {
const options: StackNavigationOptions = {
title: I18n.t('Directory')
@@ -70,7 +83,6 @@ class DirectoryView extends React.Component {
this.setState({ text }, this.search);
};
- // eslint-disable-next-line react/sort-comp
load = debounce(async ({ newSearch = false }) => {
if (newSearch) {
this.setState({ data: [], total: -1, loading: false });
@@ -91,7 +103,7 @@ class DirectoryView extends React.Component {
try {
const { data, type, globalUsers } = this.state;
const query = { text, type, workspace: globalUsers ? 'all' : 'local' };
- const directories = await RocketChat.getDirectory({
+ const directories = await Services.getDirectory({
query,
offset: data.length,
count: 50,
@@ -99,7 +111,7 @@ class DirectoryView extends React.Component {
});
if (directories.success) {
this.setState({
- data: [...data, ...directories.result],
+ data: [...data, ...(directories.result as IServerRoom[])],
loading: false,
total: directories.total
});
@@ -130,17 +142,17 @@ class DirectoryView extends React.Component {
toggleWorkspace = () => {
this.setState(
- ({ globalUsers }: any) => ({ globalUsers: !globalUsers, data: [] }),
+ ({ globalUsers }) => ({ globalUsers: !globalUsers, data: [] }),
() => this.search()
);
};
toggleDropdown = () => {
- this.setState(({ showOptionsDropdown }: any) => ({ showOptionsDropdown: !showOptionsDropdown }));
+ this.setState(({ showOptionsDropdown }) => ({ showOptionsDropdown: !showOptionsDropdown }));
};
- goRoom = (item: any) => {
- const { navigation, isMasterDetail }: any = this.props;
+ goRoom = (item: TGoRoomItem) => {
+ const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
navigation.navigate('DrawerNavigator');
} else {
@@ -149,21 +161,21 @@ class DirectoryView extends React.Component {
goRoom({ item, isMasterDetail });
};
- onPressItem = async (item: any) => {
+ onPressItem = async (item: IServerRoom) => {
const { type } = this.state;
if (type === 'users') {
- const result = await RocketChat.createDirectMessage(item.username);
+ const result = await Services.createDirectMessage(item.username as string);
if (result.success) {
- this.goRoom({ rid: result.room._id, name: item.username, t: 'd' });
+ this.goRoom({ rid: result.room._id, name: item.username, t: SubscriptionType.DIRECT });
}
} else if (['p', 'c'].includes(item.t) && !item.teamMain) {
- const result = await RocketChat.getRoomInfo(item._id);
+ const result = await Services.getRoomInfo(item._id);
if (result.success) {
this.goRoom({
rid: item._id,
name: item.name,
joinCodeRequired: result.room.joinCodeRequired,
- t: item.t,
+ t: item.t as SubscriptionType,
search: true
});
}
@@ -171,7 +183,7 @@ class DirectoryView extends React.Component {
this.goRoom({
rid: item._id,
name: item.name,
- t: item.t,
+ t: item.t as SubscriptionType,
search: true,
teamMain: item.teamMain,
teamId: item.teamId
@@ -183,7 +195,7 @@ class DirectoryView extends React.Component {
const { type } = this.state;
const { theme } = this.props;
let text = 'Users';
- let icon = 'user';
+ let icon: TIconsName = 'user';
if (type === 'channels') {
text = 'Channels';
@@ -205,12 +217,13 @@ class DirectoryView extends React.Component {
styles.toggleDropdownContainer,
{ borderColor: themes[theme].separatorColor }
]}>
-
+
{I18n.t(text)}
@@ -218,7 +231,7 @@ class DirectoryView extends React.Component {
);
};
- renderItem = ({ item, index }: any) => {
+ renderItem: ListRenderItem = ({ item, index }) => {
const { data, type } = this.state;
const { baseUrl, user, theme } = this.props;
@@ -231,7 +244,7 @@ class DirectoryView extends React.Component {
}
const commonProps = {
- title: item.name,
+ title: item.name as string,
onPress: () => this.onPressItem(item),
baseUrl,
testID: `directory-view-item-${item.name}`.toLowerCase(),
@@ -311,11 +324,11 @@ class DirectoryView extends React.Component {
};
}
-const mapStateToProps = (state: any) => ({
+const mapStateToProps = (state: IApplicationState) => ({
baseUrl: state.server.server,
user: getUserSelector(state),
- isFederationEnabled: state.settings.FEDERATION_Enabled,
- directoryDefaultView: state.settings.Accounts_Directory_DefaultView,
+ isFederationEnabled: state.settings.FEDERATION_Enabled as boolean,
+ directoryDefaultView: state.settings.Accounts_Directory_DefaultView as string,
isMasterDetail: state.app.isMasterDetail
});
diff --git a/app/views/DiscussionsView/DiscussionDetails.tsx b/app/views/DiscussionsView/DiscussionDetails.tsx
index 169c13481..f599c7414 100644
--- a/app/views/DiscussionsView/DiscussionDetails.tsx
+++ b/app/views/DiscussionsView/DiscussionDetails.tsx
@@ -1,8 +1,7 @@
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
-import { CustomIcon } from '../../lib/Icons';
-import { themes } from '../../lib/constants';
+import { CustomIcon } from '../../containers/CustomIcon';
import sharedStyles from '../Styles';
import { useTheme } from '../../theme';
import { IMessageFromServer } from '../../definitions';
@@ -35,8 +34,8 @@ interface IDiscussionDetails {
date: string;
}
-const DiscussionDetails = ({ item, date }: IDiscussionDetails): JSX.Element => {
- const { theme } = useTheme();
+const DiscussionDetails = ({ item, date }: IDiscussionDetails): React.ReactElement => {
+ const { colors } = useTheme();
let count: string | number | undefined = item.dcount;
if (count && count >= 1000) {
count = '+999';
@@ -46,15 +45,15 @@ const DiscussionDetails = ({ item, date }: IDiscussionDetails): JSX.Element => {
-
-
+
+
{count}
-
-
+
+
{date}
diff --git a/app/views/DiscussionsView/Item.stories.js b/app/views/DiscussionsView/Item.stories.js
index d47ecd71e..c14f287b8 100644
--- a/app/views/DiscussionsView/Item.stories.js
+++ b/app/views/DiscussionsView/Item.stories.js
@@ -5,7 +5,7 @@ import { ScrollView } from 'react-native';
import { Provider } from 'react-redux';
import * as List from '../../containers/List';
-import { themes } from '../../lib/constants';
+import { themes, colors } from '../../lib/constants';
import { ThemeContext } from '../../theme';
import { store } from '../../../storybook/stories';
import Item from './Item';
@@ -82,7 +82,7 @@ stories.add('content', () => (
));
const ThemeStory = ({ theme }) => (
-
+
);
diff --git a/app/views/DiscussionsView/Item.tsx b/app/views/DiscussionsView/Item.tsx
index c86bf42e0..aa1a0b46b 100644
--- a/app/views/DiscussionsView/Item.tsx
+++ b/app/views/DiscussionsView/Item.tsx
@@ -6,7 +6,6 @@ import moment from 'moment';
import { useTheme } from '../../theme';
import Avatar from '../../containers/Avatar';
import sharedStyles from '../Styles';
-import { themes } from '../../lib/constants';
import { MarkdownPreview } from '../../containers/markdown';
import { formatDateThreads, makeThreadName } from '../../utils/room';
import DiscussionDetails from './DiscussionDetails';
@@ -55,15 +54,14 @@ interface IItem {
};
}
-const Item = ({ item, onPress }: IItem): JSX.Element => {
- const { theme } = useTheme();
+const Item = ({ item, onPress }: IItem): React.ReactElement => {
+ const { colors } = useTheme();
const username = item?.u?.username;
let messageTime = '';
let messageDate = '';
if (item?.ts) {
messageTime = moment(item.ts).format('LT');
- // @ts-ignore TODO: Unify IMessage
messageDate = formatDateThreads(item.ts);
}
@@ -71,15 +69,15 @@ const Item = ({ item, onPress }: IItem): JSX.Element => {
onPress(item)}
testID={`discussions-view-${item.msg}`}
- style={{ backgroundColor: themes[theme].backgroundColor }}>
+ style={{ backgroundColor: colors.backgroundColor }}>
-
+
{username}
- {messageTime ? {messageTime} : null}
+ {messageTime ? {messageTime} : null}
{username ? : null}
diff --git a/app/views/DiscussionsView/index.tsx b/app/views/DiscussionsView/index.tsx
index bff30f9a6..13d701619 100644
--- a/app/views/DiscussionsView/index.tsx
+++ b/app/views/DiscussionsView/index.tsx
@@ -12,7 +12,6 @@ import I18n from '../../i18n';
import StatusBar from '../../containers/StatusBar';
import log from '../../utils/log';
import debounce from '../../utils/debounce';
-import { themes } from '../../lib/constants';
import SafeAreaView from '../../containers/SafeAreaView';
import * as HeaderButton from '../../containers/HeaderButton';
import * as List from '../../containers/List';
@@ -20,10 +19,10 @@ import BackgroundContainer from '../../containers/BackgroundContainer';
import { isIOS } from '../../utils/deviceInfo';
import { getHeaderTitlePosition } from '../../containers/Header';
import { useTheme } from '../../theme';
-import RocketChat from '../../lib/rocketchat';
import SearchHeader from '../../containers/SearchHeader';
import { TThreadModel } from '../../definitions/IThread';
import Item from './Item';
+import { Services } from '../../lib/services';
const API_FETCH_COUNT = 50;
@@ -39,7 +38,7 @@ interface IDiscussionsViewProps {
item: TThreadModel;
}
-const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Element => {
+const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): React.ReactElement => {
const rid = route.params?.rid;
const t = route.params?.t;
@@ -53,7 +52,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem
const [total, setTotal] = useState(0);
const [searchTotal, setSearchTotal] = useState(0);
- const { theme } = useTheme();
+ const { colors } = useTheme();
const insets = useSafeAreaInsets();
const load = async (text = '') => {
@@ -63,7 +62,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem
setLoading(true);
try {
- const result = await RocketChat.getDiscussions({
+ const result = await Services.getDiscussions({
roomId: rid,
offset: isSearching ? search.length : discussions.length,
count: API_FETCH_COUNT,
@@ -126,7 +125,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem
options = {
headerLeft: () => (
- navigation.pop()} tintColor={themes[theme].headerTintColor} />
+ navigation.pop()} tintColor={colors.headerTintColor} />
),
headerTitleAlign: 'center',
headerTitle: I18n.t('Discussions'),
@@ -192,7 +191,7 @@ const DiscussionsView = ({ navigation, route }: IDiscussionsViewProps): JSX.Elem
data={isSearching ? search : discussions}
renderItem={renderItem}
keyExtractor={(item: any) => item.msg}
- style={{ backgroundColor: themes[theme].backgroundColor }}
+ style={{ backgroundColor: colors.backgroundColor }}
contentContainerStyle={styles.contentContainer}
onEndReachedThreshold={0.5}
removeClippedSubviews={isIOS}
diff --git a/app/views/DisplayPrefsView.tsx b/app/views/DisplayPrefsView.tsx
index 2c0565f7b..61dd958f8 100644
--- a/app/views/DisplayPrefsView.tsx
+++ b/app/views/DisplayPrefsView.tsx
@@ -1,11 +1,12 @@
-import { StackNavigationProp } from '@react-navigation/stack';
import React, { useEffect } from 'react';
+import { StackNavigationProp } from '@react-navigation/stack';
+import { useNavigation } from '@react-navigation/native';
import { Switch } from 'react-native';
import { RadioButton } from 'react-native-ui-lib';
import { useDispatch, useSelector } from 'react-redux';
import { setPreference } from '../actions/sortPreferences';
-import { DisplayMode, SortBy, themes } from '../lib/constants';
+import { DisplayMode, SortBy } from '../lib/constants';
import * as HeaderButton from '../containers/HeaderButton';
import * as List from '../containers/List';
import { ICON_SIZE } from '../containers/List/constants';
@@ -13,27 +14,22 @@ import SafeAreaView from '../containers/SafeAreaView';
import StatusBar from '../containers/StatusBar';
import { IApplicationState, IPreferences } from '../definitions';
import I18n from '../i18n';
-import RocketChat from '../lib/rocketchat';
import { SettingsStackParamList } from '../stacks/types';
import { useTheme } from '../theme';
import { events, logEvent } from '../utils/log';
+import { saveSortPreference } from '../lib/methods';
-interface IDisplayPrefsView {
- navigation: StackNavigationProp;
- isMasterDetail: boolean;
-}
-
-const DisplayPrefsView = (props: IDisplayPrefsView): JSX.Element => {
- const { theme } = useTheme();
+const DisplayPrefsView = (): React.ReactElement => {
+ const navigation = useNavigation>();
+ const { colors } = useTheme();
const { sortBy, groupByType, showFavorites, showUnread, showAvatar, displayMode } = useSelector(
(state: IApplicationState) => state.sortPreferences
);
- const { isMasterDetail } = useSelector((state: any) => state.app);
+ const { isMasterDetail } = useSelector((state: IApplicationState) => state.app);
const dispatch = useDispatch();
useEffect(() => {
- const { navigation } = props;
navigation.setOptions({
title: I18n.t('Display')
});
@@ -42,11 +38,11 @@ const DisplayPrefsView = (props: IDisplayPrefsView): JSX.Element => {
headerLeft: () =>
});
}
- }, []);
+ }, [isMasterDetail, navigation]);
const setSortPreference = (param: Partial) => {
dispatch(setPreference(param));
- RocketChat.saveSortPreference(param);
+ saveSortPreference(param);
};
const sortByName = () => {
@@ -90,7 +86,7 @@ const DisplayPrefsView = (props: IDisplayPrefsView): JSX.Element => {
};
const renderCheckBox = (value: boolean) => (
-
+
);
const renderAvatarSwitch = (value: boolean) => (
@@ -98,11 +94,7 @@ const DisplayPrefsView = (props: IDisplayPrefsView): JSX.Element => {
);
const renderRadio = (value: boolean) => (
-
+
);
return (
@@ -188,6 +180,4 @@ const DisplayPrefsView = (props: IDisplayPrefsView): JSX.Element => {
);
};
-DisplayPrefsView.propTypes = {};
-
export default DisplayPrefsView;
diff --git a/app/views/E2EEncryptionSecurityView.tsx b/app/views/E2EEncryptionSecurityView.tsx
index 2ebb15367..c20392172 100644
--- a/app/views/E2EEncryptionSecurityView.tsx
+++ b/app/views/E2EEncryptionSecurityView.tsx
@@ -16,7 +16,6 @@ import { getUserSelector } from '../selectors/login';
import { PADDING_HORIZONTAL } from '../containers/List/constants';
import { themes } from '../lib/constants';
import { Encryption } from '../lib/encryption';
-import RocketChat from '../lib/rocketchat';
import { logout as logoutAction } from '../actions/login';
import { showConfirmationAlert, showErrorAlert } from '../utils/info';
import EventEmitter from '../utils/events';
@@ -24,6 +23,7 @@ import { LISTENER } from '../containers/Toast';
import debounce from '../utils/debounce';
import sharedStyles from './Styles';
import { IUser } from '../definitions';
+import { Services } from '../lib/services';
const styles = StyleSheet.create({
container: {
@@ -101,7 +101,7 @@ class E2EEncryptionSecurityView extends React.Component {
logEvent(events.E2E_SEC_RESET_OWN_KEY);
try {
- const res = await RocketChat.e2eResetOwnKey();
+ const res = await Services.e2eResetOwnKey();
/**
* It might return an empty object when TOTP is enabled,
* that's why we're using strict equality to boolean
diff --git a/app/views/ForgotPasswordView.tsx b/app/views/ForgotPasswordView.tsx
index 55305c2dd..5ab4775e4 100644
--- a/app/views/ForgotPasswordView.tsx
+++ b/app/views/ForgotPasswordView.tsx
@@ -1,20 +1,19 @@
import React from 'react';
import { Text } from 'react-native';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { RouteProp } from '@react-navigation/native';
-import TextInput from '../containers/TextInput';
import Button from '../containers/Button';
+import FormContainer, { FormContainerInner } from '../containers/FormContainer';
+import TextInput from '../containers/TextInput';
+import I18n from '../i18n';
+import { themes } from '../lib/constants';
+import { Services } from '../lib/services';
+import { OutsideParamList } from '../stacks/types';
+import { withTheme } from '../theme';
import { showErrorAlert } from '../utils/info';
import isValidEmail from '../utils/isValidEmail';
-import I18n from '../i18n';
-import RocketChat from '../lib/rocketchat';
-import { TSupportedThemes, withTheme } from '../theme';
-import { themes } from '../lib/constants';
-import FormContainer, { FormContainerInner } from '../containers/FormContainer';
import { events, logEvent } from '../utils/log';
+import { IBaseScreen } from '../definitions';
import sharedStyles from './Styles';
-import { OutsideParamList } from '../stacks/types';
interface IForgotPasswordViewState {
email: string;
@@ -22,14 +21,10 @@ interface IForgotPasswordViewState {
isFetching: boolean;
}
-interface IForgotPasswordViewProps {
- navigation: StackNavigationProp;
- route: RouteProp;
- theme: TSupportedThemes;
-}
+type IForgotPasswordViewProps = IBaseScreen;
class ForgotPasswordView extends React.Component {
- static navigationOptions = ({ route }: Pick) => ({
+ static navigationOptions = ({ route }: IForgotPasswordViewProps) => ({
title: route.params?.title ?? 'Rocket.Chat'
});
@@ -73,7 +68,7 @@ class ForgotPasswordView extends React.Component) => {
+const ForwardLivechatView = ({ navigation, route }: IBaseScreen) => {
const [departments, setDepartments] = useState([]);
const [departmentId, setDepartment] = useState('');
const [departmentTotal, setDepartmentTotal] = useState(0);
const [users, setUsers] = useState([]);
const [userId, setUser] = useState();
- const [room, setRoom] = useState({} as IServerRoom);
+ const [room, setRoom] = useState({} as IServerRoom);
const dispatch = useDispatch();
+ const { theme, colors } = useTheme();
const rid = route.params?.rid;
const getDepartments = async (text = '', offset = 0) => {
try {
- const result = await RocketChat.getDepartments({ count: COUNT_DEPARTMENT, text, offset });
+ const result = await Services.getDepartments({ count: COUNT_DEPARTMENT, text, offset });
if (result.success) {
const parsedDepartments = result.departments.map(department => ({
label: department.name,
@@ -62,7 +62,7 @@ const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen {
try {
- const result = await RocketChat.getRoomInfo(rid);
+ const result = await Services.getRoomInfo(rid);
if (result.success) {
setRoom(result.room as IServerRoom);
}
@@ -149,7 +149,7 @@ const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen
+
@@ -157,4 +157,4 @@ const ForwardLivechatView = ({ navigation, route, theme }: IBaseScreen
`${baseUrl}/avatar/${url}?format=png&width=${uriSize}&height=${uriSize}${avatarAuthURLFragment}`;
@@ -26,11 +24,8 @@ interface IJitsiMeetViewState {
loading: boolean;
}
-interface IJitsiMeetViewProps {
- navigation: StackNavigationProp;
- route: RouteProp;
+interface IJitsiMeetViewProps extends IBaseScreen {
baseUrl: string;
- theme: TSupportedThemes;
user: IUser;
}
@@ -93,14 +88,14 @@ class JitsiMeetView extends React.Component {
logEvent(events.JM_CONFERENCE_JOIN);
if (this.rid) {
- RocketChat.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
+ Services.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
if (this.jitsiTimeout) {
BackgroundTimer.clearInterval(this.jitsiTimeout);
BackgroundTimer.stopBackgroundTimer();
this.jitsiTimeout = null;
}
this.jitsiTimeout = BackgroundTimer.setInterval(() => {
- RocketChat.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
+ Services.updateJitsiTimeout(this.rid).catch((e: unknown) => console.log(e));
}, 10000);
}
};
diff --git a/app/views/LanguageView/index.tsx b/app/views/LanguageView/index.tsx
index 4e1699cbc..d31e87ebb 100644
--- a/app/views/LanguageView/index.tsx
+++ b/app/views/LanguageView/index.tsx
@@ -12,12 +12,12 @@ import StatusBar from '../../containers/StatusBar';
import { IApplicationState, IBaseScreen, IUser, RootEnum } from '../../definitions';
import I18n, { isRTL, LANGUAGES } from '../../i18n';
import database from '../../lib/database';
-import RocketChat from '../../lib/rocketchat';
import { getUserSelector } from '../../selectors/login';
import { SettingsStackParamList } from '../../stacks/types';
import { withTheme } from '../../theme';
import { showErrorAlert } from '../../utils/info';
import log, { events, logEvent } from '../../utils/log';
+import { Services } from '../../lib/services';
interface ILanguageViewProps extends IBaseScreen {
user: IUser;
@@ -92,7 +92,7 @@ class LanguageView extends React.Component;
route: RouteProp;
theme: TSupportedThemes;
@@ -65,7 +65,7 @@ const LivechatEditView = ({
}: ILivechatEditViewProps) => {
const [customFields, setCustomFields] = useState({});
const [availableUserTags, setAvailableUserTags] = useState([]);
- const [permissions, setPermissions] = useState([]);
+ const [permissions, setPermissions] = useState([]);
const params = {} as TParams;
const inputs = {} as IInputsRefs;
@@ -74,7 +74,7 @@ const LivechatEditView = ({
const visitor = route.params?.roomUser ?? {};
const getCustomFields = async () => {
- const result = await RocketChat.getCustomFields();
+ const result = await Services.getCustomFields();
if (result.success && result.customFields?.length) {
const visitorCustomFields = result.customFields
.filter(field => field.visibility !== 'hidden' && field.scope === 'visitor')
@@ -99,20 +99,20 @@ const LivechatEditView = ({
setTags(uniqueArray);
}, [availableUserTags]);
- const getTagsList = async (agentDepartments: string[]) => {
- const tags = await RocketChat.getTagsList();
- const isAdmin = ['admin', 'livechat-manager'].find(role => user.roles.includes(role));
+ const handleGetTagsList = async (agentDepartments: string[]) => {
+ const tags = await Services.getTagsList();
+ const isAdmin = ['admin', 'livechat-manager'].find(role => user.roles?.includes(role));
const availableTags = tags
.filter(({ departments }) => isAdmin || departments.length === 0 || departments.some(i => agentDepartments.indexOf(i) > -1))
.map(({ name }) => name);
setAvailableUserTags(availableTags);
};
- const getAgentDepartments = async () => {
- const result = await RocketChat.getAgentDepartments(visitor?._id);
+ const handleGetAgentDepartments = async () => {
+ const result = await Services.getAgentDepartments(visitor?._id);
if (result.success) {
const agentDepartments = result.departments.map(dept => dept.departmentId);
- getTagsList(agentDepartments);
+ handleGetTagsList(agentDepartments);
}
};
@@ -158,7 +158,7 @@ const LivechatEditView = ({
delete userData.phone;
}
- const { error } = await RocketChat.editLivechat(userData, roomData);
+ const { error } = await Services.editLivechat(userData, roomData);
if (error) {
EventEmitter.emit(LISTENER, { message: error });
} else {
@@ -172,7 +172,7 @@ const LivechatEditView = ({
};
const getPermissions = async () => {
- const permissionsArray = await RocketChat.hasPermission([editOmnichannelContact, editLivechatRoomCustomfields], livechat.rid);
+ const permissionsArray = await hasPermission([editOmnichannelContact, editLivechatRoomCustomfields], livechat.rid);
setPermissions(permissionsArray);
};
@@ -180,7 +180,7 @@ const LivechatEditView = ({
navigation.setOptions({
title: I18n.t('Edit')
});
- getAgentDepartments();
+ handleGetAgentDepartments();
getCustomFields();
getPermissions();
}, []);
diff --git a/app/views/LoginView.tsx b/app/views/LoginView.tsx
index cf7321123..ad551dd12 100644
--- a/app/views/LoginView.tsx
+++ b/app/views/LoginView.tsx
@@ -1,6 +1,6 @@
import { dequal } from 'dequal';
import React from 'react';
-import { Alert, Keyboard, StyleSheet, Text, View } from 'react-native';
+import { Alert, Keyboard, StyleSheet, Text, View, TextInput as RNTextInput } from 'react-native';
import { connect } from 'react-redux';
import { loginRequest } from '../actions/login';
@@ -64,8 +64,13 @@ interface ILoginViewProps extends IBaseScreen {
inviteLinkToken: string;
}
-class LoginView extends React.Component {
- private passwordInput: any;
+interface ILoginViewState {
+ user: string;
+ password: string;
+}
+
+class LoginView extends React.Component {
+ private passwordInput: RNTextInput | null | undefined;
static navigationOptions = ({ route, navigation }: ILoginViewProps) => ({
title: route?.params?.title ?? 'Rocket.Chat',
@@ -160,7 +165,7 @@ class LoginView extends React.Component {
returnKeyType='next'
onChangeText={(value: string) => this.setState({ user: value })}
onSubmitEditing={() => {
- this.passwordInput.focus();
+ this.passwordInput?.focus();
}}
testID='login-view-email'
textContentType='username'
diff --git a/app/views/MessagesView/index.tsx b/app/views/MessagesView/index.tsx
index f91742d77..042cdddda 100644
--- a/app/views/MessagesView/index.tsx
+++ b/app/views/MessagesView/index.tsx
@@ -9,7 +9,6 @@ import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack
import Message from '../../containers/message';
import ActivityIndicator from '../../containers/ActivityIndicator';
import I18n from '../../i18n';
-import RocketChat from '../../lib/rocketchat';
import StatusBar from '../../containers/StatusBar';
import getFileUrlFromMessage from '../../lib/methods/helpers/getFileUrlFromMessage';
import { themes } from '../../lib/constants';
@@ -20,10 +19,9 @@ import SafeAreaView from '../../containers/SafeAreaView';
import getThreadName from '../../lib/methods/getThreadName';
import styles from './styles';
import { ChatsStackParamList } from '../../stacks/types';
-import { ISubscription, SubscriptionType } from '../../definitions/ISubscription';
-import { IEmoji } from '../../definitions/IEmoji';
import { IRoomInfoParam } from '../SearchMessagesView';
-import { TMessageModel } from '../../definitions';
+import { TMessageModel, IEmoji, ISubscription, SubscriptionType, IUrl } from '../../definitions';
+import { Services } from '../../lib/services';
interface IMessagesViewProps {
user: {
@@ -191,7 +189,7 @@ class MessagesView extends React.Component {
name: I18n.t('Files'),
fetchFunc: async () => {
const { messages } = this.state;
- const result = await RocketChat.getFiles(this.rid, this.t, messages.length);
+ const result = await Services.getFiles(this.rid, this.t, messages.length);
if (result.success) {
return { ...result, messages: result.files };
}
@@ -222,7 +220,7 @@ class MessagesView extends React.Component {
name: I18n.t('Mentions'),
fetchFunc: () => {
const { messages } = this.state;
- return RocketChat.getMessages(this.rid, this.t, { 'mentions._id': { $in: [user.id] } }, messages.length);
+ return Services.getMessages(this.rid, this.t, { 'mentions._id': { $in: [user.id] } }, messages.length);
},
noDataMsg: I18n.t('No_mentioned_messages'),
testID: 'mentioned-messages-view',
@@ -234,7 +232,7 @@ class MessagesView extends React.Component {
name: I18n.t('Starred'),
fetchFunc: () => {
const { messages } = this.state;
- return RocketChat.getMessages(this.rid, this.t, { 'starred._id': { $in: [user.id] } }, messages.length);
+ return Services.getMessages(this.rid, this.t, { 'starred._id': { $in: [user.id] } }, messages.length);
},
noDataMsg: I18n.t('No_starred_messages'),
testID: 'starred-messages-view',
@@ -247,14 +245,14 @@ class MessagesView extends React.Component {
icon: message.starred ? 'star-filled' : 'star',
onPress: this.handleActionPress
}),
- handleActionPress: (message: IMessageItem) => RocketChat.toggleStarMessage(message._id, message.starred)
+ handleActionPress: (message: IMessageItem) => Services.toggleStarMessage(message._id, message.starred)
},
// Pinned Messages Screen
Pinned: {
name: I18n.t('Pinned'),
fetchFunc: () => {
const { messages } = this.state;
- return RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length);
+ return Services.getMessages(this.rid, this.t, { pinned: true }, messages.length);
},
noDataMsg: I18n.t('No_pinned_messages'),
testID: 'pinned-messages-view',
@@ -263,7 +261,7 @@ class MessagesView extends React.Component {
this.onLongPress(item)} theme={theme} />
),
action: () => ({ title: I18n.t('Unpin'), icon: 'pin', onPress: this.handleActionPress }),
- handleActionPress: (message: IMessageItem) => RocketChat.togglePinMessage(message._id, message.pinned)
+ handleActionPress: (message: IMessageItem) => Services.togglePinMessage(message._id, message.pinned)
}
// @ts-ignore
}[name];
@@ -280,8 +278,25 @@ class MessagesView extends React.Component {
try {
const result = await this.content.fetchFunc();
if (result.success) {
+ const urlRenderMessages = result.messages?.map((message: any) => {
+ if (message.urls && message.urls.length > 0) {
+ message.urls = message.urls?.map((url: any, index: any) => {
+ if (url.meta) {
+ return {
+ _id: index,
+ title: url.meta.pageTitle,
+ description: url.meta.ogDescription,
+ image: url.meta.ogImage,
+ url: url.url
+ } as IUrl;
+ }
+ return {} as IUrl;
+ });
+ }
+ return message;
+ });
this.setState({
- messages: [...messages, ...result.messages],
+ messages: [...messages, ...urlRenderMessages],
total: result.total,
loading: false
});
diff --git a/app/views/ModalBlockView.tsx b/app/views/ModalBlockView.tsx
index 9f817f7d2..1893b41fa 100644
--- a/app/views/ModalBlockView.tsx
+++ b/app/views/ModalBlockView.tsx
@@ -10,12 +10,12 @@ import EventEmitter from '../utils/events';
import { themes } from '../lib/constants';
import * as HeaderButton from '../containers/HeaderButton';
import { modalBlockWithContext } from '../containers/UIKit/MessageBlock';
-import RocketChat from '../lib/rocketchat';
import ActivityIndicator from '../containers/ActivityIndicator';
import { textParser } from '../containers/UIKit/utils';
import Navigation from '../lib/navigation/appNavigation';
import { MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
import { ContainerTypes, ModalActions } from '../containers/UIKit/interfaces';
+import { triggerBlockAction, triggerCancel, triggerSubmitView } from '../lib/methods';
const styles = StyleSheet.create({
container: {
@@ -183,7 +183,7 @@ class ModalBlockView extends React.Component {
const { data } = this.state;
const { mid, appId, viewId } = data;
- await RocketChat.triggerBlockAction({
+ await triggerBlockAction({
container: {
type: ContainerTypes.VIEW,
id: viewId
diff --git a/app/views/NewMessageView.tsx b/app/views/NewMessageView.tsx
index 2cbd11ddb..00394c62c 100644
--- a/app/views/NewMessageView.tsx
+++ b/app/views/NewMessageView.tsx
@@ -15,16 +15,17 @@ import StatusBar from '../containers/StatusBar';
import { IApplicationState, IBaseScreen, ISearch, TSubscriptionModel } from '../definitions';
import I18n from '../i18n';
import database from '../lib/database';
-import { CustomIcon } from '../lib/Icons';
+import { CustomIcon, TIconsName } from '../containers/CustomIcon';
import Navigation from '../lib/navigation/appNavigation';
import { compareServerVersion } from '../lib/methods/helpers/compareServerVersion';
-import RocketChat from '../lib/rocketchat';
import UserItem from '../containers/UserItem';
import { withTheme } from '../theme';
-import { goRoom } from '../utils/goRoom';
+import { goRoom, TGoRoomItem } from '../utils/goRoom';
import log, { events, logEvent } from '../utils/log';
import Touch from '../utils/touch';
import sharedStyles from './Styles';
+import { NewMessageStackParamList } from '../stacks/types';
+import { hasPermission, search } from '../lib/methods';
const QUERY_SIZE = 50;
@@ -51,7 +52,7 @@ interface IButton {
onPress: () => void;
testID: string;
title: string;
- icon: string;
+ icon: TIconsName;
first?: boolean;
}
@@ -61,15 +62,15 @@ interface INewMessageViewState {
permissions: boolean[];
}
-interface INewMessageViewProps extends IBaseScreen {
+interface INewMessageViewProps extends IBaseScreen {
maxUsers: number;
isMasterDetail: boolean;
serverVersion: string;
- createTeamPermission: string[] | undefined;
- createDirectMessagePermission: string[] | undefined;
- createPublicChannelPermission: string[] | undefined;
- createPrivateChannelPermission: string[] | undefined;
- createDiscussionPermission: string[] | undefined;
+ createTeamPermission?: string[];
+ createDirectMessagePermission?: string[];
+ createPublicChannelPermission?: string[];
+ createPrivateChannelPermission?: string[];
+ createDiscussionPermission?: string[];
}
class NewMessageView extends React.Component {
@@ -127,8 +128,15 @@ class NewMessageView extends React.Component {
+ const result = (await search({ text, filterRooms: false })) as ISearch[];
+ this.setState({
+ search: result
+ });
+ };
+
onSearchChangeText(text: string) {
- this.search(text);
+ this.handleSearch(text);
}
dismiss = () => {
@@ -136,13 +144,6 @@ class NewMessageView extends React.Component {
- const result = (await RocketChat.search({ text, filterRooms: false })) as ISearch[];
- this.setState({
- search: result
- });
- };
-
createChannel = () => {
logEvent(events.NEW_MSG_CREATE_CHANNEL);
const { navigation } = this.props;
@@ -167,8 +168,7 @@ class NewMessageView extends React.Component {
+ goRoom = (item: TGoRoomItem) => {
logEvent(events.NEW_MSG_CHAT_WITH_USER);
const { isMasterDetail, navigation } = this.props;
if (isMasterDetail) {
@@ -187,7 +187,7 @@ class NewMessageView extends React.Component
-
+
{title}
@@ -214,7 +214,7 @@ class NewMessageView extends React.Component this.goRoom(item)}
+ onPress={() => this.goRoom(itemModel)}
testID={`new-message-view-item-${item.name}`}
style={style}
theme={theme}
diff --git a/app/views/NewServerView/ServerInput/Item.tsx b/app/views/NewServerView/ServerInput/Item.tsx
index a9544cd87..e01ad941f 100644
--- a/app/views/NewServerView/ServerInput/Item.tsx
+++ b/app/views/NewServerView/ServerInput/Item.tsx
@@ -3,7 +3,7 @@ import { StyleSheet, Text, View } from 'react-native';
import { BorderlessButton } from 'react-native-gesture-handler';
import { themes } from '../../../lib/constants';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../../containers/CustomIcon';
import sharedStyles from '../../Styles';
import Touch from '../../../utils/touch';
import { TServerHistoryModel } from '../../../definitions/IServerHistory';
diff --git a/app/views/NewServerView/index.tsx b/app/views/NewServerView/index.tsx
index 7cb68590b..443d1140a 100644
--- a/app/views/NewServerView/index.tsx
+++ b/app/views/NewServerView/index.tsx
@@ -9,17 +9,16 @@ import parse from 'url-parse';
import { inviteLinksClear } from '../../actions/inviteLinks';
import { selectServerRequest, serverFinishAdd, serverRequest } from '../../actions/server';
-import { themes } from '../../lib/constants';
+import { CERTIFICATE_KEY, themes } from '../../lib/constants';
import Button from '../../containers/Button';
import FormContainer, { FormContainerInner } from '../../containers/FormContainer';
import * as HeaderButton from '../../containers/HeaderButton';
import OrSeparator from '../../containers/OrSeparator';
-import { IBaseScreen, TServerHistoryModel } from '../../definitions';
+import { IApplicationState, IBaseScreen, TServerHistoryModel } from '../../definitions';
import { withDimensions } from '../../dimensions';
import I18n from '../../i18n';
import database from '../../lib/database';
import { sanitizeLikeString } from '../../lib/database/utils';
-import RocketChat from '../../lib/rocketchat';
import UserPreferences from '../../lib/methods/userPreferences';
import { OutsideParamList } from '../../stacks/types';
import { withTheme } from '../../theme';
@@ -68,7 +67,7 @@ const styles = StyleSheet.create({
interface INewServerViewProps extends IBaseScreen {
connecting: boolean;
- previousServer: string;
+ previousServer: string | null;
width: number;
height: number;
}
@@ -76,7 +75,7 @@ interface INewServerViewProps extends IBaseScreen {
const { dispatch, previousServer } = this.props;
dispatch(inviteLinksClear());
- dispatch(selectServerRequest(previousServer));
+ if (previousServer) {
+ dispatch(selectServerRequest(previousServer));
+ }
};
handleNewServerEvent = (event: { server: string }) => {
@@ -194,7 +195,7 @@ class NewServerView extends React.Component this.setState({ certificate: null }) // We not need delete file from DocumentPicker because it is a temp file
});
};
@@ -407,7 +407,7 @@ class NewServerView extends React.Component ({
+const mapStateToProps = (state: IApplicationState) => ({
connecting: state.server.connecting,
previousServer: state.server.previousServer
});
diff --git a/app/views/NotificationPreferencesView/index.tsx b/app/views/NotificationPreferencesView/index.tsx
index b706babce..75a263b6b 100644
--- a/app/views/NotificationPreferencesView/index.tsx
+++ b/app/views/NotificationPreferencesView/index.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import { StyleSheet, Switch, Text } from 'react-native';
import { RouteProp } from '@react-navigation/core';
import { StackNavigationProp } from '@react-navigation/stack';
-import Model from '@nozbe/watermelondb/Model';
import { Observable, Subscription } from 'rxjs';
import database from '../../lib/database';
@@ -10,7 +9,6 @@ import { SWITCH_TRACK_COLOR, themes } from '../../lib/constants';
import StatusBar from '../../containers/StatusBar';
import * as List from '../../containers/List';
import I18n from '../../i18n';
-import RocketChat from '../../lib/rocketchat';
import { TSupportedThemes, withTheme } from '../../theme';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
import SafeAreaView from '../../containers/SafeAreaView';
@@ -18,7 +16,8 @@ import log, { events, logEvent } from '../../utils/log';
import sharedStyles from '../Styles';
import { IOptionsField, OPTIONS } from './options';
import { ChatsStackParamList } from '../../stacks/types';
-import { IRoomNotifications } from '../../definitions';
+import { IRoomNotifications, TRoomNotificationsModel } from '../../definitions';
+import { Services } from '../../lib/services';
const styles = StyleSheet.create({
pickerText: {
@@ -27,23 +26,27 @@ const styles = StyleSheet.create({
}
});
-interface INotificationPreferencesView {
+interface INotificationPreferencesViewProps {
navigation: StackNavigationProp;
route: RouteProp;
theme: TSupportedThemes;
}
-class NotificationPreferencesView extends React.Component {
+interface INotificationPreferencesViewState {
+ room: TRoomNotificationsModel;
+}
+
+class NotificationPreferencesView extends React.Component {
static navigationOptions = () => ({
title: I18n.t('Notification_Preferences')
});
private mounted: boolean;
private rid: string;
- private roomObservable?: Observable;
+ private roomObservable?: Observable;
private subscription?: Subscription;
- constructor(props: INotificationPreferencesView) {
+ constructor(props: INotificationPreferencesViewProps) {
super(props);
this.mounted = false;
this.rid = props.route.params?.rid ?? '';
@@ -53,7 +56,7 @@ class NotificationPreferencesView extends React.Component {
+ this.subscription = this.roomObservable.subscribe(changes => {
if (this.mounted) {
this.setState({ room: changes });
} else {
@@ -83,14 +86,14 @@ class NotificationPreferencesView extends React.Component {
await room.update(
- protectedFunction((r: any) => {
+ protectedFunction((r: IRoomNotifications) => {
r[key] = value;
})
);
});
try {
- const result = await RocketChat.saveNotificationSettings(this.rid, params);
+ const result = await Services.saveNotificationSettings(this.rid, params);
if (result.success) {
return;
}
@@ -100,7 +103,7 @@ class NotificationPreferencesView extends React.Component {
await room.update(
- protectedFunction((r: any) => {
+ protectedFunction((r: IRoomNotifications) => {
r[key] = room[key];
})
);
diff --git a/app/views/PickerView.tsx b/app/views/PickerView.tsx
index cb0565941..556e6414f 100644
--- a/app/views/PickerView.tsx
+++ b/app/views/PickerView.tsx
@@ -1,8 +1,7 @@
import React from 'react';
-import { StackNavigationProp } from '@react-navigation/stack';
-import { RouteProp } from '@react-navigation/native';
import { FlatList, StyleSheet, Text, View } from 'react-native';
+import { IBaseScreen } from '../definitions';
import I18n from '../i18n';
import { TSupportedThemes, withTheme } from '../theme';
import { themes } from '../lib/constants';
@@ -49,11 +48,7 @@ interface IPickerViewState {
searchText: string;
}
-interface IPickerViewProps {
- navigation: StackNavigationProp;
- route: RouteProp;
- theme: TSupportedThemes;
-}
+type IPickerViewProps = IBaseScreen;
const Item = React.memo(({ item, selected, onItemPress, theme }: IItem) => (
{
+ user: IUser;
+ baseUrl: string;
+ Accounts_AllowEmailChange: boolean;
+ Accounts_AllowPasswordChange: boolean;
+ Accounts_AllowRealNameChange: boolean;
+ Accounts_AllowUserAvatarChange: boolean;
+ Accounts_AllowUsernameChange: boolean;
+ Accounts_CustomFields: string;
+ theme: TSupportedThemes;
+}
+
+interface IProfileViewState {
+ saving: boolean;
+ name: string;
+ username: string;
+ email: string | null;
+ newPassword: string | null;
+ currentPassword: string | null;
+ avatarUrl: string | null;
+ avatar: IAvatar;
+ avatarSuggestions: IAvatarSuggestion;
+ customFields: {
+ [key: string | number]: string;
+ };
+}
class ProfileView extends React.Component {
- private name: any;
- private username: any;
- private email: any;
- private avatarUrl: any;
- private newPassword: any;
+ private name?: TextInput | null;
+ private username?: TextInput | null;
+ private email?: TextInput;
+ private avatarUrl?: TextInput;
+ private newPassword?: TextInput;
- static navigationOptions = ({ navigation, isMasterDetail }: INavigationOptions) => {
+ static navigationOptions = ({ navigation, isMasterDetail }: IProfileViewProps) => {
const options: StackNavigationOptions = {
title: I18n.t('Profile')
};
@@ -81,7 +109,7 @@ class ProfileView extends React.Component
this.init();
try {
- const result = await RocketChat.getAvatarSuggestion();
+ const result = await Services.getAvatarSuggestion();
this.setState({ avatarSuggestions: result });
} catch (e) {
log(e);
@@ -150,7 +178,7 @@ class ProfileView extends React.Component
!newPassword &&
user.emails &&
user.emails[0].address === email &&
- !avatar!.data &&
+ !avatar.data &&
!customFieldsChanged
);
};
@@ -172,8 +200,8 @@ class ProfileView extends React.Component
this.setState({ saving: true });
const { name, username, email, newPassword, currentPassword, avatar, customFields } = this.state;
- const { user, setUser } = this.props;
- const params = {} as IParams;
+ const { user, dispatch } = this.props;
+ const params = {} as IProfileParams;
// Name
if (user.name !== name) {
@@ -225,10 +253,10 @@ class ProfileView extends React.Component
}
try {
- if (avatar!.url) {
+ if (avatar.url) {
try {
logEvent(events.PROFILE_SAVE_AVATAR);
- await RocketChat.setAvatarFromService(avatar);
+ await Services.setAvatarFromService(avatar);
} catch (e) {
logEvent(events.PROFILE_SAVE_AVATAR_F);
this.setState({ saving: false, currentPassword: null });
@@ -236,14 +264,14 @@ class ProfileView extends React.Component
}
}
- const result = await RocketChat.saveUserProfile(params, customFields);
+ const result = await Services.saveUserProfile(params, customFields);
if (result.success) {
logEvent(events.PROFILE_SAVE_CHANGES);
if (customFields) {
- setUser({ customFields, ...params });
+ dispatch(setUser({ customFields, ...params }));
} else {
- setUser({ ...params });
+ dispatch(setUser({ ...params }));
}
EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
this.init();
@@ -265,7 +293,7 @@ class ProfileView extends React.Component
try {
const { user } = this.props;
- await RocketChat.resetAvatar(user.id);
+ await Services.resetAvatar(user.id);
EventEmitter.emit(LISTENER, { message: I18n.t('Avatar_changed_successfully') });
this.init();
} catch (e) {
@@ -339,7 +367,7 @@ class ProfileView extends React.Component
})}
{this.renderAvatarButton({
child: ,
- onPress: () => this.pickImageWithURL(avatarUrl!),
+ onPress: () => (avatarUrl ? this.pickImageWithURL(avatarUrl) : null),
disabled: !avatarUrl,
key: 'profile-view-avatar-url-button'
})}
@@ -419,7 +447,7 @@ class ProfileView extends React.Component
// @ts-ignore
return this[array[index + 1]].focus();
}
- this.avatarUrl.focus();
+ this.avatarUrl?.focus();
}}
theme={theme}
/>
@@ -437,7 +465,7 @@ class ProfileView extends React.Component
confirmationText: I18n.t('Logout'),
onPress: async () => {
try {
- await RocketChat.logoutOtherLocations();
+ await Services.logoutOtherLocations();
EventEmitter.emit(LISTENER, { message: I18n.t('Logged_out_of_other_clients_successfully') });
} catch {
logEvent(events.PL_OTHER_LOCATIONS_F);
@@ -482,7 +510,7 @@ class ProfileView extends React.Component
value={name}
onChangeText={(value: string) => this.setState({ name: value })}
onSubmitEditing={() => {
- this.username.focus();
+ this.username?.focus();
}}
testID='profile-view-name'
theme={theme}
@@ -498,7 +526,7 @@ class ProfileView extends React.Component
value={username}
onChangeText={value => this.setState({ username: value })}
onSubmitEditing={() => {
- this.email.focus();
+ this.email?.focus();
}}
testID='profile-view-username'
theme={theme}
@@ -507,14 +535,16 @@ class ProfileView extends React.Component
editable={Accounts_AllowEmailChange}
inputStyle={[!Accounts_AllowEmailChange && styles.disabled]}
inputRef={e => {
- this.email = e;
+ if (e) {
+ this.email = e;
+ }
}}
label={I18n.t('Email')}
placeholder={I18n.t('Email')}
- value={email!}
+ value={email || undefined}
onChangeText={value => this.setState({ email: value })}
onSubmitEditing={() => {
- this.newPassword.focus();
+ this.newPassword?.focus();
}}
testID='profile-view-email'
theme={theme}
@@ -523,18 +553,20 @@ class ProfileView extends React.Component
editable={Accounts_AllowPasswordChange}
inputStyle={[!Accounts_AllowPasswordChange && styles.disabled]}
inputRef={e => {
- this.newPassword = e;
+ if (e) {
+ this.newPassword = e;
+ }
}}
label={I18n.t('New_Password')}
placeholder={I18n.t('New_Password')}
- value={newPassword!}
+ value={newPassword || undefined}
onChangeText={value => this.setState({ newPassword: value })}
onSubmitEditing={() => {
if (Accounts_CustomFields && Object.keys(customFields).length) {
// @ts-ignore
return this[Object.keys(customFields)[0]].focus();
}
- this.avatarUrl.focus();
+ this.avatarUrl?.focus();
}}
secureTextEntry
testID='profile-view-new-password'
@@ -545,11 +577,13 @@ class ProfileView extends React.Component
editable={Accounts_AllowUserAvatarChange}
inputStyle={[!Accounts_AllowUserAvatarChange && styles.disabled]}
inputRef={e => {
- this.avatarUrl = e;
+ if (e) {
+ this.avatarUrl = e;
+ }
}}
label={I18n.t('Avatar_Url')}
placeholder={I18n.t('Avatar_Url')}
- value={avatarUrl!}
+ value={avatarUrl || undefined}
onChangeText={value => this.setState({ avatarUrl: value })}
onSubmitEditing={this.submit}
testID='profile-view-avatar-url'
@@ -580,19 +614,15 @@ class ProfileView extends React.Component
}
}
-const mapStateToProps = (state: any) => ({
+const mapStateToProps = (state: IApplicationState) => ({
user: getUserSelector(state),
- Accounts_AllowEmailChange: state.settings.Accounts_AllowEmailChange,
- Accounts_AllowPasswordChange: state.settings.Accounts_AllowPasswordChange,
- Accounts_AllowRealNameChange: state.settings.Accounts_AllowRealNameChange,
- Accounts_AllowUserAvatarChange: state.settings.Accounts_AllowUserAvatarChange,
- Accounts_AllowUsernameChange: state.settings.Accounts_AllowUsernameChange,
- Accounts_CustomFields: state.settings.Accounts_CustomFields,
+ Accounts_AllowEmailChange: state.settings.Accounts_AllowEmailChange as boolean,
+ Accounts_AllowPasswordChange: state.settings.Accounts_AllowPasswordChange as boolean,
+ Accounts_AllowRealNameChange: state.settings.Accounts_AllowRealNameChange as boolean,
+ Accounts_AllowUserAvatarChange: state.settings.Accounts_AllowUserAvatarChange as boolean,
+ Accounts_AllowUsernameChange: state.settings.Accounts_AllowUsernameChange as boolean,
+ Accounts_CustomFields: state.settings.Accounts_CustomFields as string,
baseUrl: state.server.server
});
-const mapDispatchToProps = (dispatch: any) => ({
- setUser: (params: any) => dispatch(setUserAction(params))
-});
-
-export default connect(mapStateToProps, mapDispatchToProps)(withTheme(ProfileView));
+export default connect(mapStateToProps)(withTheme(ProfileView));
diff --git a/app/views/ReadReceiptView/index.tsx b/app/views/ReadReceiptView/index.tsx
index 4ed6e1405..a6838c82c 100644
--- a/app/views/ReadReceiptView/index.tsx
+++ b/app/views/ReadReceiptView/index.tsx
@@ -10,14 +10,14 @@ import * as List from '../../containers/List';
import Avatar from '../../containers/Avatar';
import * as HeaderButton from '../../containers/HeaderButton';
import I18n from '../../i18n';
-import RocketChat from '../../lib/rocketchat';
import StatusBar from '../../containers/StatusBar';
import { TSupportedThemes, withTheme } from '../../theme';
import { themes } from '../../lib/constants';
import SafeAreaView from '../../containers/SafeAreaView';
import styles from './styles';
import { ChatsStackParamList } from '../../stacks/types';
-import { IReadReceipts } from '../../definitions';
+import { IApplicationState, IReadReceipts } from '../../definitions';
+import { Services } from '../../lib/services';
interface IReadReceiptViewState {
loading: boolean;
@@ -85,7 +85,7 @@ class ReadReceiptView extends React.Component ({
- Message_TimeAndDateFormat: state.settings.Message_TimeAndDateFormat
+const mapStateToProps = (state: IApplicationState) => ({
+ Message_TimeAndDateFormat: state.settings.Message_TimeAndDateFormat as string
});
export default connect(mapStateToProps)(withTheme(ReadReceiptView));
diff --git a/app/views/RegisterView.tsx b/app/views/RegisterView.tsx
index b0dd24af6..bd3d78d30 100644
--- a/app/views/RegisterView.tsx
+++ b/app/views/RegisterView.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Keyboard, StyleSheet, Text, View } from 'react-native';
+import { Keyboard, StyleSheet, Text, View, TextInput as RNTextInput } from 'react-native';
import RNPickerSelect from 'react-native-picker-select';
import { connect } from 'react-redux';
@@ -12,7 +12,6 @@ import LoginServices from '../containers/LoginServices';
import TextInput from '../containers/TextInput';
import { IApplicationState, IBaseScreen } from '../definitions';
import I18n from '../i18n';
-import RocketChat from '../lib/rocketchat';
import { getShowLoginButton } from '../selectors/login';
import { OutsideParamList } from '../stacks/types';
import { withTheme } from '../theme';
@@ -21,6 +20,7 @@ import isValidEmail from '../utils/isValidEmail';
import log, { events, logEvent } from '../utils/log';
import openLink from '../utils/openLink';
import sharedStyles from './Styles';
+import { Services } from '../lib/services';
const styles = StyleSheet.create({
title: {
@@ -64,12 +64,12 @@ interface IProps extends IBaseScreen {
class RegisterView extends React.Component {
private parsedCustomFields: any;
- private usernameInput: any;
- private passwordInput: any;
- private emailInput: any;
- private avatarUrl: any;
+ private usernameInput?: RNTextInput | null;
+ private passwordInput?: RNTextInput | null;
+ private emailInput?: RNTextInput | null;
+ private avatarUrl?: RNTextInput | null;
- static navigationOptions = ({ route, navigation }: Partial) => ({
+ static navigationOptions = ({ route, navigation }: IProps) => ({
title: route?.params?.title ?? 'Rocket.Chat',
headerRight: () =>
});
@@ -128,7 +128,7 @@ class RegisterView extends React.Component {
const { dispatch, Accounts_EmailVerification, navigation, Accounts_ManuallyApproveNewUsers } = this.props;
try {
- await RocketChat.register({
+ await Services.register({
name,
email,
pass: password,
@@ -188,7 +188,7 @@ class RegisterView extends React.Component {
}}
value={customFields[key]}>
{
+ inputRef={e => {
// @ts-ignore
this[key] = e;
}}
@@ -221,7 +221,7 @@ class RegisterView extends React.Component {
// @ts-ignore
return this[array[index + 1]].focus();
}
- this.avatarUrl.focus();
+ this.avatarUrl?.focus();
}}
containerStyle={styles.inputContainer}
theme={theme}
@@ -250,7 +250,7 @@ class RegisterView extends React.Component {
returnKeyType='next'
onChangeText={(name: string) => this.setState({ name })}
onSubmitEditing={() => {
- this.usernameInput.focus();
+ this.usernameInput?.focus();
}}
testID='register-view-name'
theme={theme}
@@ -265,7 +265,7 @@ class RegisterView extends React.Component {
returnKeyType='next'
onChangeText={(username: string) => this.setState({ username })}
onSubmitEditing={() => {
- this.emailInput.focus();
+ this.emailInput?.focus();
}}
testID='register-view-username'
theme={theme}
@@ -281,7 +281,7 @@ class RegisterView extends React.Component {
keyboardType='email-address'
onChangeText={(email: string) => this.setState({ email })}
onSubmitEditing={() => {
- this.passwordInput.focus();
+ this.passwordInput?.focus();
}}
testID='register-view-email'
theme={theme}
diff --git a/app/views/RoomActionsView/index.tsx b/app/views/RoomActionsView/index.tsx
index cdd644864..dc1fdac74 100644
--- a/app/views/RoomActionsView/index.tsx
+++ b/app/views/RoomActionsView/index.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable complexity */
import { Q } from '@nozbe/watermelondb';
import { StackNavigationOptions } from '@react-navigation/stack';
import isEmpty from 'lodash/isEmpty';
@@ -16,20 +17,11 @@ import RoomTypeIcon from '../../containers/RoomTypeIcon';
import SafeAreaView from '../../containers/SafeAreaView';
import Status from '../../containers/Status';
import StatusBar from '../../containers/StatusBar';
-import {
- IApplicationState,
- IBaseScreen,
- IRoom,
- ISubscription,
- IUser,
- SubscriptionType,
- TSubscriptionModel
-} from '../../definitions';
+import { IApplicationState, IBaseScreen, ISubscription, IUser, SubscriptionType, TSubscriptionModel } from '../../definitions';
import { withDimensions } from '../../dimensions';
import I18n from '../../i18n';
import database from '../../lib/database';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
-import RocketChat from '../../lib/rocketchat';
import { getUserSelector } from '../../selectors/login';
import { ChatsStackParamList } from '../../stacks/types';
import { withTheme } from '../../theme';
@@ -41,8 +33,23 @@ import styles from './styles';
import { ERoomType } from '../../definitions/ERoomType';
import { E2E_ROOM_TYPES, SWITCH_TRACK_COLOR, themes } from '../../lib/constants';
import { compareServerVersion } from '../../lib/methods/helpers/compareServerVersion';
+import {
+ callJitsi,
+ canAutoTranslate as canAutoTranslateMethod,
+ getPermalinkChannel,
+ getRoomAvatar,
+ getRoomTitle,
+ getUidDirectMessage,
+ hasPermission,
+ isGroupChat
+} from '../../lib/methods';
+import { Services } from '../../lib/services';
import { getSubscriptionByRoomId } from '../../lib/database/services/Subscription';
+interface IOnPressTouch {
+ (item: { route?: T; params?: ChatsStackParamList[T]; event?: Function }): void;
+}
+
interface IRoomActionsViewProps extends IBaseScreen {
userId: string;
jitsiEnabled: boolean;
@@ -163,7 +170,7 @@ class RoomActionsView extends React.Component {
+ onPressTouchable: IOnPressTouch = (item: {
+ route?: keyof ChatsStackParamList;
+ params?: ChatsStackParamList[keyof ChatsStackParamList];
+ event?: Function;
+ }) => {
const { route, event, params } = item;
if (route) {
/**
@@ -269,7 +279,7 @@ class RoomActionsView extends React.Component {
try {
- const { returnQueue } = await RocketChat.getRoutingConfig();
+ const { returnQueue } = await Services.getRoutingConfig();
return returnQueue;
} catch {
return false;
@@ -428,7 +438,7 @@ class RoomActionsView extends React.Component {
try {
- await RocketChat.onHoldLivechat(room.rid);
+ await Services.onHoldLivechat(room.rid);
navigation.navigate('RoomsListView');
} catch (e: any) {
showErrorAlert(e.data?.error, I18n.t('Oops'));
@@ -446,7 +456,7 @@ class RoomActionsView extends React.Component {
try {
- await RocketChat.returnLivechat(rid);
+ await Services.returnLivechat(rid);
} catch (e: any) {
showErrorAlert(e.reason, I18n.t('Oops'));
}
@@ -458,9 +468,9 @@ class RoomActionsView extends React.Component {
logEvent(events.RA_SHARE);
const { room } = this.state;
- const permalink = RocketChat.getPermalinkChannel(room);
+ const permalink = getPermalinkChannel(room);
if (!permalink) {
return;
}
@@ -559,7 +569,7 @@ class RoomActionsView extends React.Component dispatch(leaveRoom(ERoomType.c, room))
});
@@ -573,18 +583,18 @@ class RoomActionsView extends React.Component ({
+ const teamChannels = result.rooms.map(r => ({
rid: r._id,
name: r.name,
teamId: r.teamId
}));
navigation.navigate('SelectListView', {
title: 'Converting_Team_To_Channel',
- data: teamChannels as any,
+ data: teamChannels,
infoText: 'Select_Team_Channels_To_Delete',
nextAction: (data: string[]) => this.convertTeamToChannelConfirmation(data)
});
@@ -606,7 +616,7 @@ class RoomActionsView extends React.Component ({
+ const teamChannels = result.rooms.map(r => ({
rid: r._id,
name: r.name,
teamId: r.teamId,
@@ -653,7 +663,7 @@ class RoomActionsView extends React.Component dispatch(leaveRoom(ERoomType.t, room))
});
@@ -661,7 +671,7 @@ class RoomActionsView extends React.Component dispatch(leaveRoom(ERoomType.t, room))
});
@@ -673,7 +683,7 @@ class RoomActionsView extends React.Component ({
- rid: team.teamId,
+ rid: team.teamId as string,
t: team.t,
name: team.name
- })) as IRoom[]; // TODO: review this usage later
+ }));
navigation.navigate('SelectListView', {
title: 'Move_to_Team',
infoText: 'Move_Channel_Paragraph',
@@ -767,7 +777,7 @@ class RoomActionsView extends React.Component {
const results = await Promise.all(
teamArray.map(async team => {
- const permissions = await RocketChat.hasPermission([addTeamChannelPermission, createTeamPermission], team.rid);
+ const permissions = await hasPermission([addTeamChannelPermission, createTeamPermission], team.rid);
if (!permissions[0]) {
return false;
}
@@ -789,8 +799,8 @@ class RoomActionsView extends React.Component
@@ -810,7 +820,7 @@ class RoomActionsView extends React.Component
@@ -835,7 +845,7 @@ class RoomActionsView extends React.Component
- {RocketChat.getRoomTitle(room)}
+ {getRoomTitle(room)}
)}
@@ -850,7 +860,7 @@ class RoomActionsView extends React.Component
)}
- {isGroupChat ? null : }
+ {isGroupChatHandler ? null : }
@@ -874,7 +884,7 @@ class RoomActionsView extends React.Component
RocketChat.callJitsi(room, true)}
+ onPress={() => callJitsi(room, true)}
testID='room-actions-voice'
left={() => }
showActionIndicator
@@ -882,7 +892,7 @@ class RoomActionsView extends React.Component
RocketChat.callJitsi(room)}
+ onPress={() => callJitsi(room)}
testID='room-actions-video'
left={() => }
showActionIndicator
@@ -924,7 +934,7 @@ class RoomActionsView extends React.Component
@@ -1053,7 +1063,7 @@ class RoomActionsView extends React.Component
@@ -1065,7 +1075,7 @@ class RoomActionsView extends React.Component
- {(['c', 'p'].includes(t) && canViewMembers) || isGroupChat ? (
+ {(['c', 'p'].includes(t) && canViewMembers) || isGroupChatHandler ? (
<>
this.onPressTouchable({ route: 'CannedResponsesListView', params: { rid, room } })}
+ onPress={() => this.onPressTouchable({ route: 'CannedResponsesListView', params: { rid } })}
left={() => }
showActionIndicator
/>
diff --git a/app/views/RoomInfoEditView/index.tsx b/app/views/RoomInfoEditView/index.tsx
index 5b1e499a7..578f479a3 100644
--- a/app/views/RoomInfoEditView/index.tsx
+++ b/app/views/RoomInfoEditView/index.tsx
@@ -16,12 +16,11 @@ import StatusBar from '../../containers/StatusBar';
import RCTextInput from '../../containers/TextInput';
import { LISTENER } from '../../containers/Toast';
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
-import { IApplicationState, IBaseScreen, ISubscription, SubscriptionType, TSubscriptionModel } from '../../definitions';
+import { IApplicationState, IBaseScreen, ISubscription, SubscriptionType, TSubscriptionModel, IAvatar } from '../../definitions';
import { ERoomType } from '../../definitions/ERoomType';
import I18n from '../../i18n';
import database from '../../lib/database';
-import { CustomIcon } from '../../lib/Icons';
-import RocketChat from '../../lib/rocketchat';
+import { CustomIcon } from '../../containers/CustomIcon';
import KeyboardView from '../../containers/KeyboardView';
import { TSupportedPermissions } from '../../reducers/permissions';
import { ModalStackParamList } from '../../stacks/MasterDetailStack/types';
@@ -33,16 +32,17 @@ import log, { events, logEvent } from '../../utils/log';
import { MessageTypeValues } from '../../utils/messageTypes';
import random from '../../utils/random';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
-import { IAvatar } from '../../definitions/IProfileViewInterfaces';
import sharedStyles from '../Styles';
import styles from './styles';
import SwitchContainer from './SwitchContainer';
import { compareServerVersion } from '../../lib/methods/helpers/compareServerVersion';
+import { getRoomTitle, hasPermission } from '../../lib/methods';
+import { Services } from '../../lib/services';
interface IRoomInfoEditViewState {
room: ISubscription;
avatar: IAvatar;
- permissions: Record;
+ permissions: { [key in TSupportedPermissions]?: boolean };
name: string;
description?: string;
topic?: string;
@@ -92,7 +92,7 @@ class RoomInfoEditView extends React.Component,
+ permissions: {},
name: '',
description: '',
topic: '',
@@ -143,7 +143,7 @@ class RoomInfoEditView extends React.Component {
showConfirmationAlert({
- message: I18n.t('You_are_deleting_the_team', { team: RocketChat.getRoomTitle(room) }),
+ message: I18n.t('You_are_deleting_the_team', { team: getRoomTitle(room) }),
confirmationText: I18n.t('Yes_action_it', { action: I18n.t('delete') }),
onPress: () => deleteRoom(ERoomType.t, room, selected)
});
@@ -381,7 +380,7 @@ class RoomInfoEditView extends React.Component dispatch(deleteRoom(ERoomType.t, room))
});
@@ -436,7 +435,7 @@ class RoomInfoEditView extends React.Component {
try {
logEvent(events.RI_EDIT_TOGGLE_ARCHIVE);
- await RocketChat.toggleArchiveRoom(rid, t as SubscriptionType, !archived);
+ await Services.toggleArchiveRoom(rid, t as SubscriptionType, !archived);
} catch (e) {
logEvent(events.RI_EDIT_TOGGLE_ARCHIVE_F);
log(e);
diff --git a/app/views/RoomInfoView/Livechat.tsx b/app/views/RoomInfoView/Livechat.tsx
index f763c07f3..3dec3be1b 100644
--- a/app/views/RoomInfoView/Livechat.tsx
+++ b/app/views/RoomInfoView/Livechat.tsx
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text } from 'react-native';
-import RocketChat from '../../lib/rocketchat';
import { TSupportedThemes, useTheme } from '../../theme';
import sharedStyles from '../Styles';
import { themes } from '../../lib/constants';
@@ -12,6 +11,7 @@ import CustomFields from './CustomFields';
import Item from './Item';
import Timezone from './Timezone';
import { ILivechatDepartment } from '../../definitions/ILivechatDepartment';
+import { Services } from '../../lib/services';
const styles = StyleSheet.create({
title: {
@@ -31,7 +31,7 @@ const Livechat = ({ room, roomUser }: { room: ISubscription; roomUser: ILivechat
const getDepartment = async (id: string) => {
if (id) {
- const result = await RocketChat.getDepartmentInfo(id);
+ const result = await Services.getDepartmentInfo(id);
if (result.success) {
setDepartment(result.department as ILivechatDepartment);
}
diff --git a/app/views/RoomInfoView/index.tsx b/app/views/RoomInfoView/index.tsx
index c7d173635..a19217ef4 100644
--- a/app/views/RoomInfoView/index.tsx
+++ b/app/views/RoomInfoView/index.tsx
@@ -8,11 +8,10 @@ import { StackNavigationProp } from '@react-navigation/stack';
import { CompositeNavigationProp, RouteProp } from '@react-navigation/native';
import { Observable, Subscription } from 'rxjs';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import Status from '../../containers/Status';
import Avatar from '../../containers/Avatar';
import sharedStyles from '../Styles';
-import RocketChat from '../../lib/rocketchat';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import * as HeaderButton from '../../containers/HeaderButton';
@@ -34,6 +33,8 @@ import { ChatsStackParamList } from '../../stacks/types';
import { MasterDetailInsideStackParamList } from '../../stacks/MasterDetailStack/types';
import { SubscriptionType, TSubscriptionModel, ISubscription, IUser, IApplicationState } from '../../definitions';
import { ILivechatVisitor } from '../../definitions/ILivechatVisitor';
+import { callJitsi, getRoomTitle, getUidDirectMessage, hasPermission } from '../../lib/methods';
+import { Services } from '../../lib/services';
interface IGetRoomTitle {
room: ISubscription;
@@ -44,7 +45,7 @@ interface IGetRoomTitle {
theme: TSupportedThemes;
}
-const getRoomTitle = ({ room, type, name, username, statusText, theme }: IGetRoomTitle) =>
+const renderRoomTitle = ({ room, type, name, username, statusText, theme }: IGetRoomTitle) =>
type === SubscriptionType.DIRECT ? (
<>
@@ -71,7 +72,7 @@ const getRoomTitle = ({ room, type, name, username, statusText, theme }: IGetRoo
sourceType={room.source}
/>
- {RocketChat.getRoomTitle(room)}
+ {getRoomTitle(room)}
);
@@ -203,7 +204,7 @@ class RoomInfoView extends React.Component this.setHeader());
}
@@ -309,7 +310,7 @@ class RoomInfoView extends React.Component {
const { room } = this.state;
- RocketChat.callJitsi(room);
+ callJitsi(room);
};
renderAvatar = (room: ISubscription, roomUser: IUserParsed) => {
@@ -373,7 +374,7 @@ class RoomInfoView extends React.Component void, iconName: string, text: string) => {
+ renderButton = (onPress: () => void, iconName: TIconsName, text: string) => {
const { theme } = this.props;
const onActionPress = async () => {
@@ -431,7 +432,7 @@ class RoomInfoView extends React.Component
{this.renderAvatar(room, roomUser)}
- {getRoomTitle({
+ {renderRoomTitle({
room,
type: this.t,
name: roomUser?.name,
diff --git a/app/views/RoomMembersView/index.tsx b/app/views/RoomMembersView/index.tsx
index f92c4a8b9..ff831c5c1 100644
--- a/app/views/RoomMembersView/index.tsx
+++ b/app/views/RoomMembersView/index.tsx
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
import { Observable, Subscription } from 'rxjs';
import { themes } from '../../lib/constants';
-import { withActionSheet } from '../../containers/ActionSheet';
+import { TActionSheetOptions, TActionSheetOptionsItem, withActionSheet } from '../../containers/ActionSheet';
import ActivityIndicator from '../../containers/ActivityIndicator';
import * as HeaderButton from '../../containers/HeaderButton';
import * as List from '../../containers/List';
@@ -13,12 +13,11 @@ import SafeAreaView from '../../containers/SafeAreaView';
import SearchBox from '../../containers/SearchBox';
import StatusBar from '../../containers/StatusBar';
import { LISTENER } from '../../containers/Toast';
-import { IApplicationState, IBaseScreen, IUser, SubscriptionType, TRoomModel, TUserModel } from '../../definitions';
+import { IApplicationState, IBaseScreen, IUser, SubscriptionType, TSubscriptionModel, TUserModel } from '../../definitions';
import I18n from '../../i18n';
import database from '../../lib/database';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../../containers/CustomIcon';
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
-import RocketChat from '../../lib/rocketchat';
import UserItem from '../../containers/UserItem';
import { getUserSelector } from '../../selectors/login';
import { ModalStackParamList } from '../../stacks/MasterDetailStack/types';
@@ -28,8 +27,10 @@ import { goRoom, TGoRoomItem } from '../../utils/goRoom';
import { showConfirmationAlert, showErrorAlert } from '../../utils/info';
import log from '../../utils/log';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
-import { RoomTypes } from '../../lib/methods/roomTypeToApiType';
+import { TSupportedPermissions } from '../../reducers/permissions';
+import { getRoomTitle, hasPermission, isGroupChat, RoomTypes } from '../../lib/methods';
import styles from './styles';
+import { Services } from '../../lib/services';
const PAGE_SIZE = 25;
@@ -37,13 +38,13 @@ interface IRoomMembersViewProps extends IBaseScreen {}; // TODO: this work?
+ showActionSheet: (params: TActionSheetOptions) => {};
theme: TSupportedThemes;
isMasterDetail: boolean;
useRealName: boolean;
@@ -64,14 +65,14 @@ interface IRoomMembersViewState {
rid: string;
members: TUserModel[];
membersFiltered: TUserModel[];
- room: TRoomModel;
+ room: TSubscriptionModel;
end: boolean;
}
class RoomMembersView extends React.Component {
private mounted: boolean;
- private permissions: any; // TODO: fix when get props from api
- private roomObservable!: Observable;
+ private permissions: { [key in TSupportedPermissions]?: boolean };
+ private roomObservable!: Observable;
private subscription!: Subscription;
private roomRoles: any;
@@ -88,7 +89,7 @@ class RoomMembersView extends React.Component member._id !== userId);
const newMembersFiltered = membersFiltered.filter(member => member._id !== userId);
@@ -285,7 +285,7 @@ class RoomMembersView extends React.Component {
showConfirmationAlert({
message: I18n.t(`The_user_${userIsMuted ? 'will' : 'wont'}_be_able_to_type_in_roomName`, {
- roomName: RocketChat.getRoomTitle(room)
+ roomName: getRoomTitle(room)
}),
confirmationText: I18n.t(userIsMuted ? 'Unmute' : 'Mute'),
onPress: () => this.handleMute(selectedUser)
@@ -404,7 +404,7 @@ class RoomMembersView extends React.Component {
showConfirmationAlert({
- message: I18n.t('The_user_will_be_removed_from_s', { s: RocketChat.getRoomTitle(room) }),
+ message: I18n.t('The_user_will_be_removed_from_s', { s: getRoomTitle(room) }),
confirmationText: I18n.t('Yes_remove_user'),
onPress: () => this.handleRemoveUserFromRoom(selectedUser)
});
@@ -434,7 +434,7 @@ class RoomMembersView extends React.Component {
const { rid } = this.state;
try {
- await RocketChat.toggleMuteUserInRoom(rid, user?.username, !user?.muted);
+ await Services.toggleMuteUserInRoom(rid, user?.username, !user?.muted);
EventEmitter.emit(LISTENER, {
message: I18n.t('User_has_been_key', { key: user?.muted ? I18n.t('unmuted') : I18n.t('muted') })
});
@@ -504,7 +504,7 @@ class RoomMembersView extends React.Component {
try {
const { room } = this.state;
- await RocketChat.toggleRoomOwner({
+ await Services.toggleRoomOwner({
roomId: room.rid,
t: room.t,
userId: selectedUser._id,
@@ -516,7 +516,7 @@ class RoomMembersView extends React.Component {
try {
const { room } = this.state;
- await RocketChat.toggleRoomLeader({
+ await Services.toggleRoomLeader({
roomId: room.rid,
t: room.t,
userId: selectedUser._id,
@@ -540,7 +540,7 @@ class RoomMembersView extends React.Component {
try {
const { room } = this.state;
- await RocketChat.toggleRoomModerator({
+ await Services.toggleRoomModerator({
roomId: room.rid,
t: room.t,
userId: selectedUser._id,
@@ -564,7 +564,7 @@ class RoomMembersView extends React.Component {
try {
const { room } = this.state;
- await RocketChat.ignoreUser({
+ await Services.ignoreUser({
rid: room.rid,
userId: selectedUser._id,
ignore
@@ -593,8 +593,8 @@ class RoomMembersView extends React.Component member._id !== userId),
diff --git a/app/views/RoomView/Banner.tsx b/app/views/RoomView/Banner.tsx
index bbfe254e0..e458e9a18 100644
--- a/app/views/RoomView/Banner.tsx
+++ b/app/views/RoomView/Banner.tsx
@@ -4,7 +4,7 @@ import { BorderlessButton, ScrollView } from 'react-native-gesture-handler';
import Modal from 'react-native-modal';
import Markdown, { MarkdownPreview } from '../../containers/markdown';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../../containers/CustomIcon';
import { themes } from '../../lib/constants';
import styles from './styles';
import { useTheme } from '../../theme';
diff --git a/app/views/RoomView/JoinCode.tsx b/app/views/RoomView/JoinCode.tsx
index d4d85b864..db1bf1e41 100644
--- a/app/views/RoomView/JoinCode.tsx
+++ b/app/views/RoomView/JoinCode.tsx
@@ -6,10 +6,10 @@ import { connect } from 'react-redux';
import I18n from '../../i18n';
import Button from '../../containers/Button';
import TextInput from '../../containers/TextInput';
-import RocketChat from '../../lib/rocketchat';
import sharedStyles from '../Styles';
import { themes } from '../../lib/constants';
import { IApplicationState } from '../../definitions';
+import { Services } from '../../lib/services';
import { TSupportedThemes } from '../../theme';
const styles = StyleSheet.create({
@@ -50,8 +50,12 @@ export interface IJoinCodeProps {
theme: TSupportedThemes;
}
+export interface IJoinCode {
+ show: () => void;
+}
+
const JoinCode = React.memo(
- forwardRef(({ rid, t, onJoin, isMasterDetail, theme }: IJoinCodeProps, ref) => {
+ forwardRef(({ rid, t, onJoin, isMasterDetail, theme }, ref) => {
const [visible, setVisible] = useState(false);
const [error, setError] = useState(false);
const [code, setCode] = useState('');
@@ -60,9 +64,9 @@ const JoinCode = React.memo(
const hide = () => setVisible(false);
- const joinRoom = async () => {
+ const handleJoinRoom = async () => {
try {
- await RocketChat.joinRoom(rid, code, t as any);
+ await Services.joinRoom(rid, code, t as any);
onJoin();
hide();
} catch (e) {
@@ -90,7 +94,7 @@ const JoinCode = React.memo(
returnKeyType='send'
autoCapitalize='none'
onChangeText={setCode}
- onSubmitEditing={joinRoom}
+ onSubmitEditing={handleJoinRoom}
placeholder={I18n.t('Join_Code')}
secureTextEntry
error={error ? { error: 'error-code-invalid', reason: I18n.t('Code_or_password_invalid') } : undefined}
@@ -112,7 +116,7 @@ const JoinCode = React.memo(
style={styles.button}
theme={theme}
testID='join-code-submit'
- onPress={joinRoom}
+ onPress={handleJoinRoom}
/>
@@ -125,4 +129,5 @@ const JoinCode = React.memo(
const mapStateToProps = (state: IApplicationState) => ({
isMasterDetail: state.app.isMasterDetail
});
+
export default connect(mapStateToProps, null, null, { forwardRef: true })(JoinCode);
diff --git a/app/views/RoomView/List/List.tsx b/app/views/RoomView/List/List.tsx
index f28f2836f..438e25743 100644
--- a/app/views/RoomView/List/List.tsx
+++ b/app/views/RoomView/List/List.tsx
@@ -17,8 +17,10 @@ const styles = StyleSheet.create({
}
});
+export type TListRef = React.RefObject FlatList }>;
+
export interface IListProps extends FlatListProps {
- listRef: any;
+ listRef: TListRef;
}
const List = ({ listRef, ...props }: IListProps) => (
diff --git a/app/views/RoomView/List/NavBottomFAB.tsx b/app/views/RoomView/List/NavBottomFAB.tsx
index e1fbdaafa..9b885904b 100644
--- a/app/views/RoomView/List/NavBottomFAB.tsx
+++ b/app/views/RoomView/List/NavBottomFAB.tsx
@@ -3,7 +3,7 @@ import { StyleSheet, View } from 'react-native';
import Animated, { call, cond, greaterOrEq, useCode } from 'react-native-reanimated';
import { themes } from '../../../lib/constants';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../../containers/CustomIcon';
import { useTheme } from '../../../theme';
import Touch from '../../../utils/touch';
import { hasNotch } from '../../../utils/deviceInfo';
diff --git a/app/views/RoomView/List/index.tsx b/app/views/RoomView/List/index.tsx
index ad4f2f2c3..1d80efddb 100644
--- a/app/views/RoomView/List/index.tsx
+++ b/app/views/RoomView/List/index.tsx
@@ -12,13 +12,14 @@ import ActivityIndicator from '../../../containers/ActivityIndicator';
import { TAnyMessageModel, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
import database from '../../../lib/database';
import { compareServerVersion } from '../../../lib/methods/helpers/compareServerVersion';
-import RocketChat from '../../../lib/rocketchat';
import debounce from '../../../utils/debounce';
import { animateNextTransition } from '../../../utils/layoutAnimation';
import log from '../../../utils/log';
import EmptyRoom from '../EmptyRoom';
-import List, { IListProps } from './List';
+import List, { IListProps, TListRef } from './List';
import NavBottomFAB from './NavBottomFAB';
+import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods';
+import { Services } from '../../../lib/services';
const QUERY_SIZE = 50;
@@ -42,7 +43,7 @@ export interface IListContainerProps {
tmid?: string;
theme: TSupportedThemes;
loading: boolean;
- listRef: React.RefObject;
+ listRef: TListRef;
hideSystemMessages?: string[];
tunread?: string[];
ignored?: string[];
@@ -219,7 +220,7 @@ class ListContainer extends React.Component['onScrollToIndexFailed'] = params => {
const { listRef } = this.props;
- // @ts-ignore
- listRef.current.getNode().scrollToIndex({ index: params.highestMeasuredFrameIndex, animated: false });
+ listRef.current?.getNode().scrollToIndex({ index: params.highestMeasuredFrameIndex, animated: false });
};
jumpToMessage = (messageId: string) =>
@@ -282,8 +282,7 @@ class ListContainer extends React.Component item.id === messageId);
if (index > -1) {
- // @ts-ignore
- listRef.current.getNode().scrollToIndex({ index, viewPosition: 0.5, viewOffset: 100 });
+ listRef.current?.getNode().scrollToIndex({ index, viewPosition: 0.5, viewOffset: 100 });
await new Promise(res => setTimeout(res, 300));
if (!this.viewableItems?.map(vi => vi.key).includes(messageId)) {
if (!this.jumping) {
@@ -299,8 +298,7 @@ class ListContainer extends React.Component resolve(), 300);
} else {
- // @ts-ignore
- listRef.current.getNode().scrollToIndex({ index: messages.length - 1, animated: false });
+ listRef.current?.getNode().scrollToIndex({ index: messages.length - 1, animated: false });
if (!this.jumping) {
return resolve();
}
@@ -315,8 +313,7 @@ class ListContainer extends React.Component {
const { listRef } = this.props;
- // @ts-ignore
- listRef.current.getNode().scrollToOffset({ offset: -100 });
+ listRef.current?.getNode().scrollToOffset({ offset: -100 });
};
renderFooter = () => {
@@ -366,4 +363,6 @@ class ListContainer extends React.Component void;
- onEmojiSelected: Function; // TODO: properly type this
+ onEmojiSelected: (shortname: string, id: string) => void;
width: number;
height: number;
theme: TSupportedThemes;
@@ -31,7 +31,7 @@ class ReactionPicker extends React.Component {
return nextProps.show !== show || width !== nextProps.width || height !== nextProps.height;
}
- onEmojiSelected = (emoji: string, shortname: string) => {
+ onEmojiSelected = (emoji: string, shortname?: string) => {
// standard emojis: `emoji` is unicode and `shortname` is :joy:
// custom emojis: only `emoji` is returned with shortname type (:joy:)
// to set reactions, we need shortname type
@@ -70,11 +70,7 @@ class ReactionPicker extends React.Component {
}
]}
testID='reaction-picker'>
-
+
) : null;
diff --git a/app/views/RoomView/RightButtons.tsx b/app/views/RoomView/RightButtons.tsx
index 079e46682..4e5bd51dc 100644
--- a/app/views/RoomView/RightButtons.tsx
+++ b/app/views/RoomView/RightButtons.tsx
@@ -128,7 +128,7 @@ class RightButtonsContainer extends Component {
logEvent(events.ROOM_GO_TEAM_CHANNELS);
- const { navigation, isMasterDetail, teamId } = this.props;
+ const { navigation, isMasterDetail, teamId, joined } = this.props;
if (!teamId) {
return;
}
@@ -136,10 +136,10 @@ class RightButtonsContainer extends Component {
- if (!RocketChat.isUploadActive(u.path)) {
+ if (!isUploadActive(u.path)) {
try {
const db = database.active;
await db.write(async () => {
@@ -140,9 +140,9 @@ class UploadProgress extends Component {
+ handleCancelUpload = async (item: TUploadModel) => {
try {
- await RocketChat.cancelUpload(item);
+ await cancelUpload(item);
} catch (e) {
log(e);
}
@@ -158,7 +158,7 @@ class UploadProgress extends Component
{I18n.t('Uploading')} {item.name}
- this.cancelUpload(item)} />
+ this.handleCancelUpload(item)} />
,
{
user: Pick;
@@ -139,14 +158,14 @@ interface IRoomViewProps extends IBaseScreen {
insets: EdgeInsets;
}
-type TRoomUpdate = typeof roomAttrsUpdate[number];
-
interface IRoomViewState {
[key: string]: any;
joined: boolean;
- room: TSubscriptionModel | { rid: string; t: string; name?: string; fname?: string; prid?: string; joinCodeRequired?: boolean };
+ room:
+ | TSubscriptionModel
+ | { rid: string; t: string; name?: string; fname?: string; prid?: string; joinCodeRequired?: boolean; sysMes?: boolean };
roomUpdate: {
- [K in TRoomUpdate]?: any; // TODO: get type from TSubscriptionModel
+ [K in TRoomUpdate]?: any;
};
member: any;
lastOpen: Date | null;
@@ -170,23 +189,27 @@ class RoomView extends React.Component {
private tmid?: string;
private jumpToMessageId?: string;
private jumpToThreadId?: string;
- // TODO: review these refs
- private messagebox: React.RefObject;
- private list: React.RefObject;
- private joinCode: React.RefObject;
- private flatList: React.RefObject;
+ private messagebox: React.RefObject;
+ private list: React.RefObject;
+ private joinCode: React.RefObject;
+ private flatList: TListRef;
private mounted: boolean;
- private sub?: any;
private offset = 0;
- private didMountInteraction: any;
private subSubscription?: Subscription;
private queryUnreads?: Subscription;
private retryInit = 0;
private retryInitTimeout?: number;
private retryFindCount = 0;
private retryFindTimeout?: number;
- private messageErrorActions?: React.RefObject; // TODO: type me
- private messageActions?: React.RefObject;
+ private messageErrorActions?: IMessageErrorActions | null;
+ private messageActions?: IMessageActions | null;
+ // Type of InteractionManager.runAfterInteractions
+ private didMountInteraction?: {
+ then: (onfulfilled?: (() => any) | undefined, onrejected?: (() => any) | undefined) => Promise;
+ done: (...args: any[]) => any;
+ cancel: () => void;
+ };
+ private sub?: RoomClass;
constructor(props: IRoomViewProps) {
super(props);
@@ -213,7 +236,7 @@ class RoomView extends React.Component {
};
this.jumpToMessageId = props.route.params?.jumpToMessageId;
this.jumpToThreadId = props.route.params?.jumpToThreadId;
- const roomUserId = props.route.params?.roomUserId ?? RocketChat.getUidDirectMessage(room);
+ const roomUserId = props.route.params?.roomUserId ?? getUidDirectMessage(room);
this.state = {
joined: true,
room,
@@ -300,6 +323,7 @@ class RoomView extends React.Component {
if (member.statusText !== nextState.member.statusText) {
return true;
}
+
const stateUpdated = stateAttrsUpdate.some(key => nextState[key] !== state[key]);
if (stateUpdated) {
return true;
@@ -328,8 +352,7 @@ class RoomView extends React.Component {
if (appState === 'foreground' && appState !== prevProps.appState && this.rid) {
// Fire List.query() just to keep observables working
if (this.list && this.list.current) {
- // @ts-ignore TODO: is this working?
- this.list.current?.query?.();
+ this.list.current?.query();
}
}
// If it's not direct message
@@ -367,7 +390,6 @@ class RoomView extends React.Component {
const db = database.active;
this.mounted = false;
if (!editing && this.messagebox && this.messagebox.current) {
- // @ts-ignore
const { text } = this.messagebox.current;
let obj: TSubscriptionModel | TThreadModel | null = null;
if (this.tmid) {
@@ -382,9 +404,9 @@ class RoomView extends React.Component {
}
if (obj) {
try {
+ const object = obj;
await db.write(async () => {
- // FIXME: why do I need to tell ts this is non null if we have that if condition above?
- await obj!.update(r => {
+ await object.update(r => {
r.draftMessage = text;
});
});
@@ -431,15 +453,15 @@ class RoomView extends React.Component {
}
const prid = room?.prid;
- const isGroupChat = RocketChat.isGroupChat(room as ISubscription);
+ const isGroupChatConst = isGroupChat(room as ISubscription);
let title = route.params?.name;
let parentTitle = '';
// TODO: I think it's safe to remove this, but we need to test tablet without rooms
if (!tmid) {
- title = RocketChat.getRoomTitle(room);
+ title = getRoomTitle(room);
}
if (tmid) {
- parentTitle = RocketChat.getRoomTitle(room);
+ parentTitle = getRoomTitle(room);
}
let subtitle: string | undefined;
let t: string;
@@ -510,7 +532,7 @@ class RoomView extends React.Component {
type={t}
roomUserId={roomUserId}
visitor={visitor}
- isGroupChat={isGroupChat}
+ isGroupChat={isGroupChatConst}
onPress={this.goRoomActionsView}
testID={`room-view-title-${title}`}
sourceType={sourceType}
@@ -531,20 +553,18 @@ class RoomView extends React.Component {
});
};
- goRoomActionsView = (screen?: string) => {
+ goRoomActionsView = (screen?: keyof ModalStackParamList) => {
logEvent(events.ROOM_GO_RA);
const { room, member, joined } = this.state;
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
- // @ts-ignore TODO: find a way to make it work
+ // @ts-ignore
navigation.navigate('ModalStackNavigator', {
- // @ts-ignore
screen: screen ?? 'RoomActionsView',
params: {
rid: this.rid as string,
t: this.t as SubscriptionType,
- // @ts-ignore
- room,
+ room: room as ISubscription,
member,
showCloseModal: !!screen,
joined
@@ -576,7 +596,7 @@ class RoomView extends React.Component {
return;
}
if (this.tmid) {
- await RoomServices.getThreadMessages(this.tmid, this.rid);
+ await loadThreadMessages({ tmid: this.tmid, rid: this.rid });
} else {
const newLastOpen = new Date();
await RoomServices.getMessages(room);
@@ -588,11 +608,11 @@ class RoomView extends React.Component {
} else {
this.setLastOpen(null);
}
- RoomServices.readMessages(room.rid, newLastOpen).catch(e => console.log(e));
+ readMessages(room.rid, newLastOpen, true).catch(e => console.log(e));
}
}
- const canAutoTranslate = RocketChat.canAutoTranslate();
+ const canAutoTranslate = canAutoTranslateMethod();
const member = await this.getRoomMember();
this.setState({ canAutoTranslate, member, loading: false });
@@ -611,12 +631,12 @@ class RoomView extends React.Component {
const { room } = this.state;
const { t } = room;
- if ('id' in room && t === 'd' && !RocketChat.isGroupChat(room)) {
+ if ('id' in room && t === 'd' && !isGroupChat(room)) {
try {
- const roomUserId = RocketChat.getUidDirectMessage(room);
+ const roomUserId = getUidDirectMessage(room);
this.setState({ roomUserId }, () => this.setHeader());
- const result = await RocketChat.getUserInfo(roomUserId);
+ const result = await Services.getUserInfo(roomUserId);
if (result.success) {
return result.user;
}
@@ -683,7 +703,6 @@ class RoomView extends React.Component {
};
errorActionsShow = (message: TAnyMessageModel) => {
- // @ts-ignore
this.messageErrorActions?.showMessageErrorActions(message);
};
@@ -706,7 +725,7 @@ class RoomView extends React.Component {
onEditRequest = async (message: TAnyMessageModel) => {
this.setState({ selectedMessage: undefined, editing: false });
try {
- await RocketChat.editMessage(message);
+ await Services.editMessage(message);
} catch (e) {
log(e);
}
@@ -733,7 +752,6 @@ class RoomView extends React.Component {
};
onMessageLongPress = (message: TAnyMessageModel) => {
- // @ts-ignore
this.messageActions?.showMessageActions(message);
};
@@ -745,7 +763,7 @@ class RoomView extends React.Component {
onReactionPress = async (shortname: string, messageId: string) => {
try {
- await RocketChat.setReaction(shortname, messageId);
+ await Services.setReaction(shortname, messageId);
this.onReactionClose();
Review.pushPositiveEvent();
} catch (e) {
@@ -858,15 +876,13 @@ class RoomView extends React.Component {
} else {
/**
* if it's from server, we don't have it saved locally and so we fetch surroundings
- * we test if it's not from threads because we're fetching from threads currently with `getThreadMessages`
+ * we test if it's not from threads because we're fetching from threads currently with `loadThreadMessages`
*/
if (message.fromServer && !message.tmid && this.rid) {
- await RocketChat.loadSurroundingMessages({ messageId, rid: this.rid });
+ await loadSurroundingMessages({ messageId, rid: this.rid });
}
- // @ts-ignore
- await Promise.race([this.list.current.jumpToMessage(message.id), new Promise(res => setTimeout(res, 5000))]);
- // @ts-ignore
- this.list.current.cancelJumpToMessage();
+ await Promise.race([this.list.current?.jumpToMessage(message.id), new Promise(res => setTimeout(res, 5000))]);
+ this.list.current?.cancelJumpToMessage();
}
} catch (e) {
log(e);
@@ -890,7 +906,7 @@ class RoomView extends React.Component {
if (rid === this.rid) {
Navigation.navigate('RoomsListView');
!this.isOmnichannel &&
- showErrorAlert(I18n.t('You_were_removed_from_channel', { channel: RocketChat.getRoomTitle(room) }), I18n.t('Oops'));
+ showErrorAlert(I18n.t('You_were_removed_from_channel', { channel: getRoomTitle(room) }), I18n.t('Oops'));
}
};
@@ -902,22 +918,20 @@ class RoomView extends React.Component {
this.setState(...args);
};
- sendMessage = (message: string, tmid?: string, tshow?: boolean) => {
+ handleSendMessage = (message: string, tmid?: string, tshow?: boolean) => {
logEvent(events.ROOM_SEND_MESSAGE);
const { rid } = this.state.room;
const { user } = this.props;
- RocketChat.sendMessage(rid, message, this.tmid || tmid, user, tshow).then(() => {
+ sendMessage(rid, message, this.tmid || tmid, user, tshow).then(() => {
if (this.list && this.list.current) {
- // @ts-ignore
- this.list.current.update();
+ this.list.current?.update();
}
this.setLastOpen(null);
Review.pushPositiveEvent();
});
};
- // TODO: We need to unify
- getCustomEmoji = (name: string): IReduxEmoji | null => {
+ getCustomEmoji = (name: string): Pick | null => {
const { customEmojis } = this.props;
const emoji = customEmojis[name];
if (emoji) {
@@ -947,10 +961,9 @@ class RoomView extends React.Component {
} else {
const { joinCodeRequired, rid } = room;
if (joinCodeRequired) {
- // @ts-ignore
this.joinCode.current?.show();
} else {
- await RocketChat.joinRoom(rid, null, this.t as any);
+ await Services.joinRoom(rid, null, this.t as any);
this.onJoin();
}
}
@@ -986,7 +999,7 @@ class RoomView extends React.Component {
if (!threadMessageId) {
return;
}
- await RocketChat.toggleFollowMessage(threadMessageId, !isFollowingThread);
+ await Services.toggleFollowMessage(threadMessageId, !isFollowingThread);
EventEmitter.emit(LISTENER, { message: isFollowingThread ? I18n.t('Unfollowed_thread') : I18n.t('Following_thread') });
} catch (e) {
log(e);
@@ -1072,14 +1085,14 @@ class RoomView extends React.Component {
});
};
- callJitsi = () => {
+ handleCallJitsi = () => {
const { room } = this.state;
if ('id' in room) {
const { jitsiTimeout } = room;
if (jitsiTimeout && jitsiTimeout < new Date()) {
showErrorAlert(I18n.t('Call_already_ended'));
} else {
- RocketChat.callJitsi(room);
+ callJitsi(room);
}
}
};
@@ -1090,17 +1103,17 @@ class RoomView extends React.Component {
if (handleCommandScroll(event)) {
const offset = input === 'UIKeyInputUpArrow' ? 100 : -100;
this.offset += offset;
- // @ts-ignore
- this.flatList?.scrollToOffset({ offset: this.offset });
+ this.flatList?.current?.scrollToOffset({ offset: this.offset });
} else if (handleCommandRoomActions(event)) {
this.goRoomActionsView();
} else if (handleCommandSearchMessages(event)) {
this.goRoomActionsView('SearchMessagesView');
} else if (handleCommandReplyLatest(event)) {
if (this.list && this.list.current) {
- // @ts-ignore
const message = this.list.current.getLastMessage();
- this.onReplyInit(message, false);
+ if (message) {
+ this.onReplyInit(message, false);
+ }
}
}
}
@@ -1121,7 +1134,7 @@ class RoomView extends React.Component {
rid: string;
mid: string;
}) =>
- RocketChat.triggerBlockAction({
+ triggerBlockAction({
blockId,
actionId,
value,
@@ -1214,11 +1227,12 @@ class RoomView extends React.Component {
onEncryptedPress={this.onEncryptedPress}
onDiscussionPress={this.onDiscussionPress}
onThreadPress={this.onThreadPress}
- onAnswerButtonPress={this.sendMessage}
+ onAnswerButtonPress={this.handleSendMessage}
showAttachment={this.showAttachment}
reactionInit={this.onReactionInit}
replyBroadcast={this.replyBroadcast}
errorActionsShow={this.errorActionsShow}
+ isSystemMessage={room.sysMes as boolean}
baseUrl={baseUrl}
Message_GroupingPeriod={Message_GroupingPeriod}
timeFormat={Message_TimeFormat}
@@ -1228,7 +1242,7 @@ class RoomView extends React.Component {
autoTranslateLanguage={'id' in room ? room.autoTranslateLanguage : undefined}
navToRoomInfo={this.navToRoomInfo}
getCustomEmoji={this.getCustomEmoji}
- callJitsi={this.callJitsi}
+ callJitsi={this.handleCallJitsi}
blockAction={this.blockAction}
threadBadgeColor={this.getBadgeColor(item?.id)}
toggleFollowThread={this.toggleFollowThread}
@@ -1319,7 +1333,7 @@ class RoomView extends React.Component {
return (
{
return (
<>
(this.messageActions = ref)}
tmid={this.tmid}
room={room}
@@ -1359,7 +1372,6 @@ class RoomView extends React.Component {
onReactionPress={this.onReactionPress}
isReadOnly={readOnly}
/>
- {/* @ts-ignore TODO: missing interface on MessageErrorActions */}
(this.messageErrorActions = ref)} tmid={this.tmid} />
>
);
@@ -1384,11 +1396,9 @@ class RoomView extends React.Component {
=> RocketChat.loadThreadMessages({ tmid, rid });
-
-export default getThreadMessages;
diff --git a/app/views/RoomView/services/index.ts b/app/views/RoomView/services/index.ts
index f8799cda8..47565eabe 100644
--- a/app/views/RoomView/services/index.ts
+++ b/app/views/RoomView/services/index.ts
@@ -1,13 +1,9 @@
import getMessages from './getMessages';
import getMoreMessages from './getMoreMessages';
-import getThreadMessages from './getThreadMessages';
-import readMessages from './readMessages';
import getMessageInfo from './getMessageInfo';
export default {
getMessages,
getMoreMessages,
- getThreadMessages,
- readMessages,
getMessageInfo
};
diff --git a/app/views/RoomView/services/readMessages.ts b/app/views/RoomView/services/readMessages.ts
deleted file mode 100644
index 573027d0b..000000000
--- a/app/views/RoomView/services/readMessages.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import RocketChat from '../../../lib/rocketchat';
-
-const readMessages = (rid: string, newLastOpen: Date): Promise => RocketChat.readMessages(rid, newLastOpen, true);
-
-export default readMessages;
diff --git a/app/views/RoomsListView/Header/Header.tsx b/app/views/RoomsListView/Header/Header.tsx
index 316cc34bd..a8c0dd80d 100644
--- a/app/views/RoomsListView/Header/Header.tsx
+++ b/app/views/RoomsListView/Header/Header.tsx
@@ -5,7 +5,7 @@ import TextInput from '../../../presentation/TextInput';
import I18n from '../../../i18n';
import sharedStyles from '../../Styles';
import { themes } from '../../../lib/constants';
-import { CustomIcon } from '../../../lib/Icons';
+import { CustomIcon } from '../../../containers/CustomIcon';
import { isIOS, isTablet } from '../../../utils/deviceInfo';
import { useOrientation } from '../../../dimensions';
import { useTheme } from '../../../theme';
diff --git a/app/views/RoomsListView/ServerDropdown.tsx b/app/views/RoomsListView/ServerDropdown.tsx
index 4abef24ae..b74b2016e 100644
--- a/app/views/RoomsListView/ServerDropdown.tsx
+++ b/app/views/RoomsListView/ServerDropdown.tsx
@@ -9,12 +9,11 @@ import Button from '../../containers/Button';
import { toggleServerDropdown } from '../../actions/rooms';
import { selectServerRequest, serverInitAdd } from '../../actions/server';
import { appStart } from '../../actions/app';
-import RocketChat from '../../lib/rocketchat';
import I18n from '../../i18n';
import EventEmitter from '../../utils/events';
import ServerItem from '../../containers/ServerItem';
import database from '../../lib/database';
-import { themes } from '../../lib/constants';
+import { themes, TOKEN_KEY } from '../../lib/constants';
import { withTheme } from '../../theme';
import { KEY_COMMAND, handleCommandSelectServer, IKeyCommandEvent } from '../../commands';
import { isTablet } from '../../utils/deviceInfo';
@@ -27,6 +26,7 @@ import UserPreferences from '../../lib/methods/userPreferences';
import { IApplicationState, IBaseScreen, RootEnum, TServerModel } from '../../definitions';
import styles from './styles';
import { ChatsStackParamList } from '../../stacks/types';
+import { removeServer } from '../../lib/methods';
const ROW_HEIGHT = 68;
const ANIMATION_DURATION = 200;
@@ -135,7 +135,7 @@ class ServerDropdown extends Component {
this.close();
try {
- await RocketChat.removeServer({ server });
+ await removeServer({ server });
} catch {
// do nothing
}
diff --git a/app/views/RoomsListView/index.tsx b/app/views/RoomsListView/index.tsx
index 9995a47cc..fefd863de 100644
--- a/app/views/RoomsListView/index.tsx
+++ b/app/views/RoomsListView/index.tsx
@@ -9,7 +9,6 @@ import { Subscription } from 'rxjs';
import { StackNavigationOptions } from '@react-navigation/stack';
import database from '../../lib/database';
-import RocketChat from '../../lib/rocketchat';
import RoomItem, { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from '../../containers/RoomItem';
import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
@@ -47,8 +46,19 @@ import ServerDropdown from './ServerDropdown';
import ListHeader, { TEncryptionBanner } from './ListHeader';
import RoomsListHeaderView from './Header';
import { ChatsStackParamList } from '../../stacks/types';
-import { RoomTypes } from '../../lib/methods/roomTypeToApiType';
+import {
+ getRoomAvatar,
+ getRoomTitle,
+ getUidDirectMessage,
+ getUserPresence,
+ hasPermission,
+ isGroupChat,
+ isRead,
+ RoomTypes,
+ search
+} from '../../lib/methods';
import { E2E_BANNER_TYPE, DisplayMode, SortBy, MAX_SIDEBAR_WIDTH, themes } from '../../lib/constants';
+import { Services } from '../../lib/services';
interface IRoomsListViewProps extends IBaseScreen {
[key: string]: any;
@@ -229,7 +239,7 @@ class RoomsListView extends React.Component r === true).length > 0;
this.setState({ canCreateRoom }, () => this.setHeader());
};
@@ -591,7 +601,7 @@ class RoomsListView extends React.Component {
dispatch(openSearchHeader());
- this.search('');
+ this.handleSearch('');
this.setHeader();
});
};
@@ -625,8 +635,8 @@ class RoomsListView extends React.Component {
- const result = await RocketChat.search({ text });
+ handleSearch = debounce(async (text: string) => {
+ const result = await search({ text });
// if the search was cancelled before the promise is resolved
const { searching } = this.state;
@@ -640,19 +650,9 @@ class RoomsListView extends React.Component RocketChat.getRoomTitle(item);
-
- getRoomAvatar = (item: ISubscription) => RocketChat.getRoomAvatar(item);
-
- isGroupChat = (item: ISubscription) => RocketChat.isGroupChat(item);
-
- isRead = (item: ISubscription) => RocketChat.isRead(item);
-
isSwipeEnabled = (item: IRoomItem) => !(item?.search || item?.joinCodeRequired || item?.outside);
- getUserPresence = (uid: string) => RocketChat.getUserPresence(uid);
-
- getUidDirectMessage = (room: ISubscription) => RocketChat.getUidDirectMessage(room);
+ handleGetUserPresence = (uid: string) => getUserPresence(uid);
get isGrouping() {
const { showUnread, showFavorites, groupByType } = this.props;
@@ -679,7 +679,7 @@ class RoomsListView extends React.Component {
@@ -699,11 +699,11 @@ class RoomsListView extends React.Component {
- logEvent(isRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
+ toggleRead = async (rid: string, tIsRead: boolean) => {
+ logEvent(tIsRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
try {
const db = database.active;
- const result = await RocketChat.toggleRead(isRead, rid);
+ const result = await Services.toggleRead(tIsRead, rid);
if (result.success) {
const subCollection = db.get('subscriptions');
@@ -711,7 +711,7 @@ class RoomsListView extends React.Component {
- sub.alert = isRead;
+ sub.alert = tIsRead;
sub.unread = 0;
});
} catch (e) {
@@ -729,7 +729,7 @@ class RoomsListView extends React.Component {
@@ -946,7 +946,7 @@ class RoomsListView extends React.Component ({
+const mapStateToProps = (state: IApplicationState) => ({
server: state.server.server,
- Force_Screen_Lock: state.settings.Force_Screen_Lock,
- Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After
+ Force_Screen_Lock: state.settings.Force_Screen_Lock as boolean,
+ Force_Screen_Lock_After: state.settings.Force_Screen_Lock_After as number
});
export default connect(mapStateToProps)(withTheme(ScreenLockConfigView));
diff --git a/app/views/ScreenLockedView.tsx b/app/views/ScreenLockedView.tsx
index b4306688a..7cf21abed 100644
--- a/app/views/ScreenLockedView.tsx
+++ b/app/views/ScreenLockedView.tsx
@@ -1,22 +1,37 @@
-import React, { useEffect, useState } from 'react';
-import Modal from 'react-native-modal';
-import useDeepCompareEffect from 'use-deep-compare-effect';
import isEmpty from 'lodash/isEmpty';
+import React, { useEffect, useState } from 'react';
+import { StyleSheet } from 'react-native';
+import Modal from 'react-native-modal';
import Orientation from 'react-native-orientation-locker';
+import Touchable from 'react-native-platform-touchable';
+import useDeepCompareEffect from 'use-deep-compare-effect';
-import EventEmitter from '../utils/events';
-import { LOCAL_AUTHENTICATE_EMITTER } from '../lib/constants';
-import { isTablet } from '../utils/deviceInfo';
import { PasscodeEnter } from '../containers/Passcode';
+import { LOCAL_AUTHENTICATE_EMITTER } from '../lib/constants';
+import { CustomIcon } from '../containers/CustomIcon';
+import { useTheme } from '../theme';
+import { hasNotch, isTablet } from '../utils/deviceInfo';
+import EventEmitter from '../utils/events';
interface IData {
submit?: () => void;
+ cancel?: () => void;
hasBiometry?: boolean;
+ force?: boolean;
}
+const styles = StyleSheet.create({
+ close: {
+ position: 'absolute',
+ top: hasNotch ? 50 : 30,
+ left: 15
+ }
+});
+
const ScreenLockedView = (): JSX.Element => {
const [visible, setVisible] = useState(false);
const [data, setData] = useState({});
+ const { colors } = useTheme();
useDeepCompareEffect(() => {
if (!isEmpty(data)) {
@@ -51,6 +66,14 @@ const ScreenLockedView = (): JSX.Element => {
setData({});
};
+ const onCancel = () => {
+ const { cancel } = data;
+ if (cancel) {
+ cancel();
+ }
+ setData({});
+ };
+
return (
{
animationIn='fadeIn'
animationOut='fadeOut'>
+ {data?.force ? (
+
+
+
+ ) : null}
);
};
diff --git a/app/views/SearchMessagesView/index.tsx b/app/views/SearchMessagesView/index.tsx
index f24de99cd..2e6252bee 100644
--- a/app/views/SearchMessagesView/index.tsx
+++ b/app/views/SearchMessagesView/index.tsx
@@ -12,7 +12,6 @@ import RCTextInput from '../../containers/TextInput';
import ActivityIndicator from '../../containers/ActivityIndicator';
import Markdown from '../../containers/markdown';
import debounce from '../../utils/debounce';
-import RocketChat from '../../lib/rocketchat';
import Message from '../../containers/message';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { IMessage } from '../../containers/message/interfaces';
@@ -33,6 +32,8 @@ import styles from './styles';
import { InsideStackParamList, ChatsStackParamList } from '../../stacks/types';
import { IEmoji } from '../../definitions/IEmoji';
import { compareServerVersion } from '../../lib/methods/helpers/compareServerVersion';
+import { IUrl } from '../../definitions';
+import { Services } from '../../lib/services';
const QUERY_SIZE = 50;
@@ -153,11 +154,27 @@ class SearchMessagesView extends React.Component {
+ if (message.urls && message.urls.length > 0) {
+ message.urls = message.urls?.map((url, index) => {
+ if (url.meta) {
+ return {
+ _id: index,
+ title: url.meta.pageTitle,
+ description: url.meta.ogDescription,
+ image: url.meta.ogImage,
+ url: url.url
+ } as IUrl;
+ }
+ return {} as IUrl;
+ });
+ }
+ return message;
+ });
+ return urlRenderMessages;
}
-
return [];
};
getMessages = async (searchText: string, debounced?: boolean) => {
diff --git a/app/views/SecurityPrivacyView.tsx b/app/views/SecurityPrivacyView.tsx
index b62d1ad09..5487819d1 100644
--- a/app/views/SecurityPrivacyView.tsx
+++ b/app/views/SecurityPrivacyView.tsx
@@ -1,38 +1,43 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import { StackNavigationProp } from '@react-navigation/stack';
import React, { useEffect, useState } from 'react';
import { Switch } from 'react-native';
-import { StackNavigationProp } from '@react-navigation/stack';
-import AsyncStorage from '@react-native-community/async-storage';
import { useSelector } from 'react-redux';
-import StatusBar from '../containers/StatusBar';
import * as List from '../containers/List';
-import I18n from '../i18n';
-import {
- logEvent,
- events,
- toggleCrashErrorsReport,
- toggleAnalyticsEventsReport,
- getReportCrashErrorsValue,
- getReportAnalyticsEventsValue
-} from '../utils/log';
import SafeAreaView from '../containers/SafeAreaView';
+import StatusBar from '../containers/StatusBar';
+import { IApplicationState } from '../definitions';
+import I18n from '../i18n';
import { ANALYTICS_EVENTS_KEY, CRASH_REPORT_KEY, isFDroidBuild, SWITCH_TRACK_COLOR } from '../lib/constants';
+import useServer from '../lib/methods/useServer';
+import { SettingsStackParamList } from '../stacks/types';
+import { handleLocalAuthentication } from '../utils/localAuthentication';
+import {
+ events,
+ getReportAnalyticsEventsValue,
+ getReportCrashErrorsValue,
+ logEvent,
+ toggleAnalyticsEventsReport,
+ toggleCrashErrorsReport
+} from '../utils/log';
interface ISecurityPrivacyViewProps {
- navigation: StackNavigationProp;
+ navigation: StackNavigationProp;
}
const SecurityPrivacyView = ({ navigation }: ISecurityPrivacyViewProps): JSX.Element => {
const [crashReportState, setCrashReportState] = useState(getReportCrashErrorsValue());
const [analyticsEventsState, setAnalyticsEventsState] = useState(getReportAnalyticsEventsValue());
+ const [server] = useServer();
- const e2eEnabled = useSelector((state: any) => state.settings.E2E_Enable);
+ const e2eEnabled = useSelector((state: IApplicationState) => state.settings.E2E_Enable);
useEffect(() => {
navigation.setOptions({
title: I18n.t('Security_and_privacy')
});
- }, []);
+ }, [navigation]);
const toggleCrashReport = (value: boolean) => {
logEvent(events.SP_TOGGLE_CRASH_REPORT);
@@ -54,6 +59,13 @@ const SecurityPrivacyView = ({ navigation }: ISecurityPrivacyViewProps): JSX.Ele
navigation.navigate(screen);
};
+ const navigateToScreenLockConfigView = async () => {
+ if (server?.autoLock) {
+ await handleLocalAuthentication(true);
+ }
+ navigateToScreen('ScreenLockConfigView');
+ };
+
return (
@@ -74,7 +86,7 @@ const SecurityPrivacyView = ({ navigation }: ISecurityPrivacyViewProps): JSX.Ele
navigateToScreen('ScreenLockConfigView')}
+ onPress={navigateToScreenLockConfigView}
testID='security-privacy-view-screen-lock'
/>
diff --git a/app/views/SelectListView.tsx b/app/views/SelectListView.tsx
index d36f907ea..e6105a4cb 100644
--- a/app/views/SelectListView.tsx
+++ b/app/views/SelectListView.tsx
@@ -18,7 +18,8 @@ import { animateNextTransition } from '../utils/layoutAnimation';
import { ICON_SIZE } from '../containers/List/constants';
import SearchBox from '../containers/SearchBox';
import sharedStyles from './Styles';
-import { IRoom } from '../definitions/IRoom';
+import { IApplicationState } from '../definitions';
+import { TDataSelect } from '../definitions/IDataSelect';
const styles = StyleSheet.create({
buttonText: {
@@ -29,8 +30,8 @@ const styles = StyleSheet.create({
});
interface ISelectListViewState {
- data?: IRoom[];
- dataFiltered?: IRoom[];
+ data?: TDataSelect[];
+ dataFiltered?: TDataSelect[];
isSearching: boolean;
selected: string[];
}
@@ -53,7 +54,7 @@ class SelectListView extends React.Component Promise | any>;
+ private onSearch?: (text: string) => Promise;
private isRadio?: boolean;
@@ -122,7 +123,7 @@ class SelectListView extends React.Component {
try {
this.setState({ isSearching: true });
- const result = (await this.onSearch?.(text)) as IRoom[];
+ const result = await this.onSearch?.(text);
this.setState({ dataFiltered: result });
} catch (e) {
log(e);
@@ -150,30 +151,31 @@ class SelectListView extends React.Component }) => {
+ renderItem = ({ item }: { item: TDataSelect }) => {
const { theme } = this.props;
const { selected } = this.state;
const channelIcon = item.t === 'p' ? 'channel-private' : 'channel-public';
const teamIcon = item.t === 'p' ? 'teams-private' : 'teams';
const icon = item.teamMain ? teamIcon : channelIcon;
- const checked = this.isChecked(item.rid!) ? 'check' : '';
+ const checked = this.isChecked(item.rid) ? 'check' : '';
const showRadio = () => (
);
- const showCheck = () => (
-
- );
+ const showCheck = () =>
+ checked !== '' ? (
+
+ ) : null;
return (
<>
@@ -182,7 +184,7 @@ class SelectListView extends React.Component (item.alert ? this.showAlert() : this.toggleItem(item.rid!))}
+ onPress={() => (item.alert ? this.showAlert() : this.toggleItem(item.rid))}
alert={item.alert}
left={() => }
right={() => (this.isRadio ? showRadio() : showCheck())}
@@ -211,7 +213,7 @@ class SelectListView extends React.Component ({
+const mapStateToProps = (state: IApplicationState) => ({
isMasterDetail: state.app.isMasterDetail
});
diff --git a/app/views/SelectServerView.tsx b/app/views/SelectServerView.tsx
index 6af55ad7c..de73b4bc4 100644
--- a/app/views/SelectServerView.tsx
+++ b/app/views/SelectServerView.tsx
@@ -2,33 +2,28 @@ import React from 'react';
import { FlatList } from 'react-native';
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
import { connect } from 'react-redux';
-import { Q, Model } from '@nozbe/watermelondb';
+import { Q } from '@nozbe/watermelondb';
import I18n from '../i18n';
import StatusBar from '../containers/StatusBar';
import ServerItem, { ROW_HEIGHT } from '../containers/ServerItem';
-import { shareExtensionInit } from '../lib/services/shareExtension';
+import { shareExtensionInit } from '../lib/methods/shareExtension';
import database from '../lib/database';
import SafeAreaView from '../containers/SafeAreaView';
import * as List from '../containers/List';
import { ShareInsideStackParamList } from '../definitions/navigationTypes';
+import { IApplicationState, TServerModel } from '../definitions';
const getItemLayout = (data: any, index: number) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
-const keyExtractor = (item: IServer) => item.id;
-
-interface IServer extends Model {
- id: string;
- iconURL: string;
- name: string;
-}
+const keyExtractor = (item: TServerModel) => item.id;
interface ISelectServerViewState {
- servers: IServer[];
+ servers: TServerModel[];
}
interface ISelectServerViewProps {
navigation: StackNavigationProp;
- server: string;
+ server?: string;
}
class SelectServerView extends React.Component {
@@ -36,12 +31,12 @@ class SelectServerView extends React.Component {
+ renderItem = ({ item }: { item: TServerModel }) => {
const { server } = this.props;
return this.select(item.id)} item={item} hasCheck={item.id === server} />;
};
@@ -81,7 +76,7 @@ class SelectServerView extends React.Component ({
+const mapStateToProps = ({ share }: IApplicationState) => ({
server: share.server.server
});
diff --git a/app/views/SelectedUsersView.tsx b/app/views/SelectedUsersView.tsx
index d0c29a509..47eafaa86 100644
--- a/app/views/SelectedUsersView.tsx
+++ b/app/views/SelectedUsersView.tsx
@@ -13,10 +13,9 @@ import Loading from '../containers/Loading';
import SafeAreaView from '../containers/SafeAreaView';
import SearchBox from '../containers/SearchBox';
import StatusBar from '../containers/StatusBar';
-import { IApplicationState, IBaseScreen, ISubscription, IUser } from '../definitions';
+import { IApplicationState, IBaseScreen, ISearch, ISearchLocal, IUser } from '../definitions';
import I18n from '../i18n';
import database from '../lib/database';
-import RocketChat from '../lib/rocketchat';
import UserItem from '../containers/UserItem';
import { ISelectedUser } from '../reducers/selectedUsers';
import { getUserSelector } from '../selectors/login';
@@ -25,18 +24,18 @@ import { withTheme } from '../theme';
import { showErrorAlert } from '../utils/info';
import log, { events, logEvent } from '../utils/log';
import sharedStyles from './Styles';
+import { isGroupChat, search } from '../lib/methods';
const ITEM_WIDTH = 250;
const getItemLayout = (_: any, index: number) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
interface ISelectedUsersViewState {
maxUsers?: number;
- search: ISelectedUser[];
+ search: (ISearch | ISearchLocal)[];
chats: ISelectedUser[];
}
interface ISelectedUsersViewProps extends IBaseScreen {
- // REDUX STATE
users: ISelectedUser[];
loading: boolean;
user: IUser;
@@ -106,9 +105,8 @@ class SelectedUsersView extends React.Component {
- const chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
+ this.querySubscription = observable.subscribe(data => {
+ const chats = orderBy(data, ['roomUpdatedAt'], ['desc']) as ISelectedUser[];
this.setState({ chats });
});
} catch (e) {
@@ -117,13 +115,11 @@ class SelectedUsersView extends React.Component {
- // TODO: When migrate rocketchat.js pass the param IUser to there and the return should be
- // IUser | TSubscriptionModel, this because we do a local search too
- const result = (await RocketChat.search({ text, filterRooms: false })) as ISelectedUser[];
+ handleSearch = async (text: string) => {
+ const result = await search({ text, filterRooms: false });
this.setState({
search: result
});
@@ -131,7 +127,7 @@ class SelectedUsersView extends React.Component {
const { maxUsers } = this.state;
- return maxUsers! > 2;
+ return maxUsers && maxUsers > 2;
};
isChecked = (username: string) => {
@@ -166,7 +162,7 @@ class SelectedUsersView extends React.Component {
if (item.search) {
- this.toggleUser({ _id: item._id, name: item.username!, fname: item.name });
+ this.toggleUser({ _id: item._id, name: item.username as string, fname: item.name });
} else {
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
}
@@ -230,7 +226,7 @@ class SelectedUsersView extends React.Component 0 ? search : chats)
- // filter DM between multiple users
- .filter(sub => !RocketChat.isGroupChat(sub as ISubscription));
+ const searchOrChats = (search.length > 0 ? search : chats) as ISelectedUser[];
+ // filter DM between multiple users
+ const data = searchOrChats.filter(sub => !isGroupChat(sub));
return (
;
- route: RouteProp;
-}
+type ISendEmailConfirmationViewProps = IBaseScreen;
-const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmationViewProps): JSX.Element => {
+const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmationViewProps): React.ReactElement => {
const [email, setEmail] = useState('');
const [invalidEmail, setInvalidEmail] = useState(true);
const [isFetching, setIsFetching] = useState(false);
-
const { theme } = useTheme();
const validate = (val: string) => {
@@ -39,7 +34,7 @@ const SendEmailConfirmationView = ({ navigation, route }: ISendEmailConfirmation
}
try {
setIsFetching(true);
- const result = await RocketChat.sendConfirmationEmail(email);
+ const result = await Services.sendConfirmationEmail(email);
if (result.success) {
navigation.pop();
showErrorAlert(I18n.t('Verify_email_desc'));
diff --git a/app/views/SetUsernameView.tsx b/app/views/SetUsernameView.tsx
index 479e755ed..184195e66 100644
--- a/app/views/SetUsernameView.tsx
+++ b/app/views/SetUsernameView.tsx
@@ -13,8 +13,8 @@ import SafeAreaView from '../containers/SafeAreaView';
import StatusBar from '../containers/StatusBar';
import TextInput from '../containers/TextInput';
import { IApplicationState } from '../definitions';
+import { SetUsernameStackParamList } from '../definitions/navigationTypes';
import I18n from '../i18n';
-import RocketChat from '../lib/rocketchat';
import KeyboardView from '../containers/KeyboardView';
import { getUserSelector } from '../selectors/login';
import { TSupportedThemes, withTheme } from '../theme';
@@ -22,6 +22,7 @@ import { isTablet } from '../utils/deviceInfo';
import { showErrorAlert } from '../utils/info';
import scrollPersistTaps from '../utils/scrollPersistTaps';
import sharedStyles from './Styles';
+import { Services } from '../lib/services';
const styles = StyleSheet.create({
loginTitle: {
@@ -36,8 +37,8 @@ interface ISetUsernameViewState {
}
interface ISetUsernameViewProps {
- navigation: StackNavigationProp;
- route: RouteProp<{ SetUsernameView: { title: string } }, 'SetUsernameView'>;
+ navigation: StackNavigationProp;
+ route: RouteProp;
server: string;
userId: string;
token: string;
@@ -64,7 +65,7 @@ class SetUsernameView extends React.Component {
server: IServer;
@@ -96,10 +97,10 @@ class SettingsView extends React.Component {
dispatch
} = this.props;
dispatch(appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Clear_cache_loading') }));
- await RocketChat.clearCache({ server });
+ await clearCache({ server });
await FastImage.clearMemoryCache();
await FastImage.clearDiskCache();
- RocketChat.disconnect();
+ Services.disconnect();
dispatch(selectServerRequest(server));
}
});
@@ -176,7 +177,7 @@ class SettingsView extends React.Component {
<>
-
+
diff --git a/app/views/ShareListView/index.tsx b/app/views/ShareListView/index.tsx
index 0a5f34b4e..0811117e6 100644
--- a/app/views/ShareListView/index.tsx
+++ b/app/views/ShareListView/index.tsx
@@ -20,11 +20,12 @@ import { themes } from '../../lib/constants';
import { animateNextTransition } from '../../utils/layoutAnimation';
import { TSupportedThemes, withTheme } from '../../theme';
import SafeAreaView from '../../containers/SafeAreaView';
-import RocketChat from '../../lib/rocketchat';
import { sanitizeLikeString } from '../../lib/database/utils';
import styles from './styles';
import ShareListHeader from './Header';
-import { IServerInfo } from '../../definitions';
+import { TServerModel, TSubscriptionModel } from '../../definitions';
+import { ShareInsideStackParamList } from '../../definitions/navigationTypes';
+import { getRoomAvatar } from '../../lib/methods';
interface IDataFromShare {
value: string;
@@ -35,39 +36,25 @@ interface IFileToShare {
filename: string;
description: string;
size: number;
- mime: any;
+ mime: string;
path: string;
}
-interface IChat {
- rid: string;
- t: string;
- name: string;
- fname: string;
- blocked: boolean;
- blocker: boolean;
- prid: string;
- uids: string[];
- usernames: string[];
- topic: string;
- description: string;
-}
-
interface IState {
searching: boolean;
searchText: string;
- searchResults: IChat[];
- chats: IChat[];
+ searchResults: TSubscriptionModel[];
+ chats: TSubscriptionModel[];
serversCount: number;
attachments: IFileToShare[];
text: string;
loading: boolean;
- serverInfo: IServerInfo;
+ serverInfo: TServerModel;
needsPermission: boolean;
}
interface INavigationOption {
- navigation: StackNavigationProp;
+ navigation: StackNavigationProp;
}
interface IShareListViewProps extends INavigationOption {
@@ -84,7 +71,7 @@ const permission: Rationale = {
};
const getItemLayout = (data: any, index: number) => ({ length: data.length, offset: ROW_HEIGHT * index, index });
-const keyExtractor = (item: IChat) => item.rid;
+const keyExtractor = (item: TSubscriptionModel) => item.rid;
class ShareListView extends React.Component {
private unsubscribeFocus: (() => void) | undefined;
@@ -102,7 +89,7 @@ class ShareListView extends React.Component {
attachments: [],
text: '',
loading: true,
- serverInfo: {} as IServerInfo,
+ serverInfo: {} as TServerModel,
needsPermission: isAndroid || false
};
this.setHeader();
@@ -252,7 +239,7 @@ class ShareListView extends React.Component {
const data = (await db
.get('subscriptions')
.query(...defaultWhereClause)
- .fetch()) as IChat[];
+ .fetch()) as TSubscriptionModel[];
return data.map(item => ({
rid: item.rid,
@@ -307,12 +294,12 @@ class ShareListView extends React.Component {
uriToPath = (uri: string) => decodeURIComponent(isIOS ? uri.replace(/^file:\/\//, '') : uri);
- getRoomTitle = (item: IChat) => {
+ getRoomTitle = (item: TSubscriptionModel) => {
const { serverInfo } = this.state;
return ((item.prid || serverInfo?.useRealName) && item.fname) || item.name;
};
- shareMessage = (room: IChat) => {
+ shareMessage = (room: TSubscriptionModel) => {
const { attachments, text, serverInfo } = this.state;
const { navigation } = this.props;
@@ -369,7 +356,7 @@ class ShareListView extends React.Component {
);
};
- renderItem = ({ item }: { item: IChat }) => {
+ renderItem = ({ item }: { item: TSubscriptionModel }) => {
const { serverInfo } = this.state;
let description;
switch (item.t) {
@@ -389,7 +376,7 @@ class ShareListView extends React.Component {
return (
this.shareMessage(item)}
diff --git a/app/views/ShareView/Header.tsx b/app/views/ShareView/Header.tsx
index ecbbbbe97..8f13d0554 100644
--- a/app/views/ShareView/Header.tsx
+++ b/app/views/ShareView/Header.tsx
@@ -2,14 +2,14 @@ import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import I18n from '../../i18n';
-import { CustomIcon } from '../../lib/Icons';
-import RocketChat from '../../lib/rocketchat';
+import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import { themes } from '../../lib/constants';
import { useTheme } from '../../theme';
import { isAndroid, isTablet } from '../../utils/deviceInfo';
import sharedStyles from '../Styles';
import { makeThreadName } from '../../utils/room';
import { ISubscription } from '../../definitions';
+import { getRoomTitle, isGroupChat } from '../../lib/methods';
const androidMarginLeft = isTablet ? 0 : 4;
@@ -50,7 +50,7 @@ const Header = React.memo(({ room, thread }: IHeader) => {
} else {
type = room?.t;
}
- let icon;
+ let icon: TIconsName;
if (type === 'discussion') {
icon = 'discussions';
} else if (type === 'thread') {
@@ -60,7 +60,7 @@ const Header = React.memo(({ room, thread }: IHeader) => {
} else if (type === 'l') {
icon = 'omnichannel';
} else if (type === 'd') {
- if (RocketChat.isGroupChat(room)) {
+ if (isGroupChat(room)) {
icon = 'team';
} else {
icon = 'mention';
@@ -75,7 +75,7 @@ const Header = React.memo(({ room, thread }: IHeader) => {
if (thread?.id) {
title = makeThreadName(thread);
} else {
- title = RocketChat.getRoomTitle(room);
+ title = getRoomTitle(room);
}
return (
diff --git a/app/views/ShareView/Preview.tsx b/app/views/ShareView/Preview.tsx
index b2812aa9e..4c09ffa51 100644
--- a/app/views/ShareView/Preview.tsx
+++ b/app/views/ShareView/Preview.tsx
@@ -4,7 +4,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ScrollView, StyleSheet, Text } from 'react-native';
import prettyBytes from 'pretty-bytes';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon, TIconsName } from '../../containers/CustomIcon';
import { ImageViewer, types } from '../../presentation/ImageViewer';
import { useDimensions, useOrientation } from '../../dimensions';
import { getHeaderHeight } from '../../containers/Header';
@@ -37,7 +37,7 @@ const styles = StyleSheet.create({
});
interface IIconPreview {
- iconName: string;
+ iconName: TIconsName;
title: string;
description?: string;
theme: TSupportedThemes;
diff --git a/app/views/ShareView/Thumbs.tsx b/app/views/ShareView/Thumbs.tsx
index 3dd715f39..588de3148 100644
--- a/app/views/ShareView/Thumbs.tsx
+++ b/app/views/ShareView/Thumbs.tsx
@@ -4,7 +4,7 @@ import { RectButton, TouchableNativeFeedback, TouchableOpacity } from 'react-nat
import { BUTTON_HIT_SLOP } from '../../containers/message/utils';
import { themes } from '../../lib/constants';
-import { CustomIcon } from '../../lib/Icons';
+import { CustomIcon } from '../../containers/CustomIcon';
import { isIOS } from '../../utils/deviceInfo';
import { THUMBS_HEIGHT } from './constants';
import { allowPreview } from './utils';
diff --git a/app/views/ShareView/index.tsx b/app/views/ShareView/index.tsx
index 5d842866d..5dbd9c2e9 100644
--- a/app/views/ShareView/index.tsx
+++ b/app/views/ShareView/index.tsx
@@ -14,7 +14,6 @@ import * as HeaderButton from '../../containers/HeaderButton';
import { isBlocked } from '../../utils/room';
import { isReadOnly } from '../../utils/isReadOnly';
import { TSupportedThemes, withTheme } from '../../theme';
-import RocketChat from '../../lib/rocketchat';
import TextInput from '../../containers/TextInput';
import MessageBox from '../../containers/MessageBox';
import SafeAreaView from '../../containers/SafeAreaView';
@@ -29,6 +28,7 @@ import Header from './Header';
import styles from './styles';
import { IAttachment } from './interfaces';
import { IUser, TSubscriptionModel } from '../../definitions';
+import { hasPermission, sendFileMessage, sendMessage } from '../../lib/methods';
interface IShareViewState {
selected: IAttachment;
@@ -144,7 +144,7 @@ class ShareView extends Component {
const permissionsCollection = db.get('permissions');
const uploadFilePermissionFetch = await permissionsCollection.query(Q.where('id', Q.like('mobile-upload-file'))).fetch();
const uploadFilePermission = uploadFilePermissionFetch[0]?.roles;
- const permissionToUpload = await RocketChat.hasPermission([uploadFilePermission], room.rid);
+ const permissionToUpload = await hasPermission([uploadFilePermission], room.rid);
// uploadFilePermission as undefined is considered that there isn't this permission, so all can upload file.
return !uploadFilePermission || permissionToUpload[0];
};
@@ -218,7 +218,7 @@ class ShareView extends Component {
await Promise.all(
attachments.map(({ filename: name, mime: type, description, size, path, canUpload }) => {
if (canUpload) {
- return RocketChat.sendFileMessage(
+ return sendFileMessage(
room.rid,
{
name,
@@ -240,7 +240,7 @@ class ShareView extends Component {
// Send text message
} else if (text.length) {
- await RocketChat.sendMessage(room.rid, text, thread?.id, { id: user.id, token: user.token } as IUser);
+ await sendMessage(room.rid, text, thread?.id, { id: user.id, token: user.token } as IUser);
}
} catch {
// Do nothing
@@ -361,7 +361,7 @@ class ShareView extends Component