Chore: Properly type MessageActions (#3930)

This commit is contained in:
Diego Mello 2022-03-31 09:38:20 -03:00 committed by GitHub
parent c483abfa60
commit 4416f82665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 129 additions and 105 deletions

View File

@ -2,7 +2,7 @@ import React, { ForwardedRef, forwardRef, useContext, useRef } from 'react';
import ActionSheet from './ActionSheet'; import ActionSheet from './ActionSheet';
export type TActionSheetOptionsItem = { title: string; icon: string; onPress: () => void }; export type TActionSheetOptionsItem = { title: string; icon: string; onPress: () => void; danger?: boolean };
export type TActionSheetOptions = { export type TActionSheetOptions = {
options: TActionSheetOptionsItem[]; options: TActionSheetOptionsItem[];

View File

@ -8,6 +8,7 @@ const CustomEmoji = React.memo(
<FastImage <FastImage
style={style} style={style}
source={{ source={{
// @ts-ignore
uri: `${baseUrl}/emoji-custom/${encodeURIComponent(emoji.content || emoji.name)}.${emoji.extension}`, uri: `${baseUrl}/emoji-custom/${encodeURIComponent(emoji.content || emoji.name)}.${emoji.extension}`,
priority: FastImage.priority.high priority: FastImage.priority.high
}} }}

View File

@ -56,6 +56,7 @@ class EmojiCategory extends React.Component<Partial<IEmojiCategory>> {
contentContainerStyle={{ marginHorizontal }} contentContainerStyle={{ marginHorizontal }}
// rerender FlatList in case of width changes // rerender FlatList in case of width changes
key={`emoji-category-${width}`} key={`emoji-category-${width}`}
// @ts-ignore
keyExtractor={item => (item && item.isCustom && item.content) || item} keyExtractor={item => (item && item.isCustom && item.content) || item}
data={emojis} data={emojis}
extraData={this.props} extraData={this.props}

View File

@ -109,6 +109,7 @@ class EmojiPicker extends Component<IEmojiPickerProps, IEmojiPickerState> {
const freqEmojiCollection = db.get('frequently_used_emojis'); const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojiRecord: any; let freqEmojiRecord: any;
try { try {
// @ts-ignore
freqEmojiRecord = await freqEmojiCollection.find(emoji.content); freqEmojiRecord = await freqEmojiCollection.find(emoji.content);
} catch (error) { } catch (error) {
// Do nothing // Do nothing

View File

@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native'; import { FlatList, StyleSheet, Text, View } from 'react-native';
import { withTheme } from '../../theme'; import { useTheme } from '../../theme';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons'; import { CustomIcon } from '../../lib/Icons';
import shortnameToUnicode from '../../utils/shortnameToUnicode'; import shortnameToUnicode from '../../utils/shortnameToUnicode';
@ -10,26 +10,30 @@ import database from '../../lib/database';
import { Button } from '../ActionSheet'; import { Button } from '../ActionSheet';
import { useDimensions } from '../../dimensions'; import { useDimensions } from '../../dimensions';
import sharedStyles from '../../views/Styles'; import sharedStyles from '../../views/Styles';
import { IEmoji } from '../../definitions/IEmoji';
import { TFrequentlyUsedEmojiModel } from '../../definitions/IFrequentlyUsedEmoji'; import { TFrequentlyUsedEmojiModel } from '../../definitions/IFrequentlyUsedEmoji';
import { TAnyMessageModel } from '../../definitions';
import { IEmoji } from '../../definitions/IEmoji';
interface IHeader { type TItem = TFrequentlyUsedEmojiModel | string;
handleReaction: Function;
export interface IHeader {
handleReaction: (emoji: TItem, message: TAnyMessageModel) => void;
server: string; server: string;
message: object; message: TAnyMessageModel;
isMasterDetail: boolean; isMasterDetail: boolean;
theme?: string;
} }
type TOnReaction = ({ emoji }: { emoji: TItem }) => void;
interface THeaderItem { interface THeaderItem {
item: IEmoji; item: TItem;
onReaction: Function; onReaction: TOnReaction;
server: string; server: string;
theme: string; theme: string;
} }
interface THeaderFooter { interface THeaderFooter {
onReaction: any; onReaction: TOnReaction;
theme: string; theme: string;
} }
@ -62,25 +66,32 @@ const styles = StyleSheet.create({
} }
}); });
const keyExtractor = (item: any) => item?.id || item; const keyExtractor = (item: TItem) => {
const emojiModel = item as TFrequentlyUsedEmojiModel;
return (emojiModel.id ? emojiModel.content : item) as string;
};
const DEFAULT_EMOJIS = ['clap', '+1', 'heart_eyes', 'grinning', 'thinking_face', 'smiley']; const DEFAULT_EMOJIS = ['clap', '+1', 'heart_eyes', 'grinning', 'thinking_face', 'smiley'];
const HeaderItem = React.memo(({ item, onReaction, server, theme }: THeaderItem) => ( const HeaderItem = ({ item, onReaction, server, theme }: THeaderItem) => {
<Button const emojiModel = item as TFrequentlyUsedEmojiModel;
testID={`message-actions-emoji-${item.content || item}`} const emoji = (emojiModel.id ? emojiModel.content : item) as string;
onPress={() => onReaction({ emoji: `:${item.content || item}:` })} return (
style={[styles.headerItem, { backgroundColor: themes[theme].auxiliaryBackground }]} <Button
theme={theme}> testID={`message-actions-emoji-${emoji}`}
{item?.isCustom ? ( onPress={() => onReaction({ emoji: `:${emoji}:` })}
<CustomEmoji style={styles.customEmoji} emoji={item} baseUrl={server} /> style={[styles.headerItem, { backgroundColor: themes[theme].auxiliaryBackground }]}
) : ( theme={theme}>
<Text style={styles.headerIcon}>{shortnameToUnicode(`:${item.content || item}:`)}</Text> {emojiModel?.isCustom ? (
)} <CustomEmoji style={styles.customEmoji} emoji={emojiModel as IEmoji} baseUrl={server} />
</Button> ) : (
)); <Text style={styles.headerIcon}>{shortnameToUnicode(`:${emoji}:`)}</Text>
)}
</Button>
);
};
const HeaderFooter = React.memo(({ onReaction, theme }: THeaderFooter) => ( const HeaderFooter = ({ onReaction, theme }: THeaderFooter) => (
<Button <Button
testID='add-reaction' testID='add-reaction'
onPress={onReaction} onPress={onReaction}
@ -88,17 +99,19 @@ const HeaderFooter = React.memo(({ onReaction, theme }: THeaderFooter) => (
theme={theme}> theme={theme}>
<CustomIcon name='reaction-add' size={24} color={themes[theme].bodyText} /> <CustomIcon name='reaction-add' size={24} color={themes[theme].bodyText} />
</Button> </Button>
)); );
const Header = React.memo(({ handleReaction, server, message, isMasterDetail, theme }: IHeader) => { const Header = React.memo(({ handleReaction, server, message, isMasterDetail }: IHeader) => {
const [items, setItems] = useState<(TFrequentlyUsedEmojiModel | string)[]>([]); const [items, setItems] = useState<TItem[]>([]);
const { width, height }: any = useDimensions(); const { width, height } = useDimensions();
const { theme } = useTheme();
// TODO: create custom hook to re-render based on screen size
const setEmojis = async () => { const setEmojis = async () => {
try { try {
const db = database.active; const db = database.active;
const freqEmojiCollection = db.get('frequently_used_emojis'); const freqEmojiCollection = db.get('frequently_used_emojis');
let freqEmojis: (TFrequentlyUsedEmojiModel | string)[] = await freqEmojiCollection.query().fetch(); let freqEmojis: TItem[] = await freqEmojiCollection.query().fetch();
const isLandscape = width > height; const isLandscape = width > height;
const size = (isLandscape || isMasterDetail ? width / 2 : width) - CONTAINER_MARGIN * 2; const size = (isLandscape || isMasterDetail ? width / 2 : width) - CONTAINER_MARGIN * 2;
@ -115,22 +128,21 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
setEmojis(); setEmojis();
}, []); }, []);
const onReaction = ({ emoji }: { emoji: IEmoji }) => handleReaction(emoji, message); const onReaction: TOnReaction = ({ emoji }) => handleReaction(emoji, message);
const renderItem = useCallback( const renderItem = ({ item }: { item: TItem }) => (
({ item }) => <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme!} />, <HeaderItem item={item} onReaction={onReaction} server={server} theme={theme} />
[]
); );
const renderFooter = useCallback(() => <HeaderFooter onReaction={onReaction} theme={theme!} />, []); const renderFooter = () => <HeaderFooter onReaction={onReaction} theme={theme} />;
return ( return (
<View style={[styles.container, { backgroundColor: themes[theme!].focusedBackground }]}> <View style={[styles.container, { backgroundColor: themes[theme].focusedBackground }]}>
<FlatList <FlatList
data={items} data={items}
renderItem={renderItem} renderItem={renderItem}
ListFooterComponent={renderFooter} ListFooterComponent={renderFooter}
style={{ backgroundColor: themes[theme!].focusedBackground }} style={{ backgroundColor: themes[theme].focusedBackground }}
keyExtractor={keyExtractor} keyExtractor={keyExtractor}
showsHorizontalScrollIndicator={false} showsHorizontalScrollIndicator={false}
scrollEnabled={false} scrollEnabled={false}
@ -140,4 +152,4 @@ const Header = React.memo(({ handleReaction, server, message, isMasterDetail, th
); );
}); });
export default withTheme(Header); export default Header;

View File

@ -13,33 +13,33 @@ import { getMessageTranslation } from '../message/utils';
import { LISTENER } from '../Toast'; import { LISTENER } from '../Toast';
import EventEmitter from '../../utils/events'; import EventEmitter from '../../utils/events';
import { showConfirmationAlert } from '../../utils/info'; import { showConfirmationAlert } from '../../utils/info';
import { useActionSheet } from '../ActionSheet'; import { TActionSheetOptionsItem, useActionSheet } from '../ActionSheet';
import Header, { HEADER_HEIGHT } from './Header'; import Header, { HEADER_HEIGHT, IHeader } from './Header';
import events from '../../utils/log/events'; import events from '../../utils/log/events';
import { ILoggedUser, TAnyMessageModel, TSubscriptionModel } from '../../definitions'; import { IApplicationState, ILoggedUser, TAnyMessageModel, TSubscriptionModel } from '../../definitions';
export interface IMessageActions { export interface IMessageActions {
room: TSubscriptionModel; room: TSubscriptionModel;
tmid?: string; tmid?: string;
user: Pick<ILoggedUser, 'id'>; user: Pick<ILoggedUser, 'id'>;
editInit: Function; editInit: (message: TAnyMessageModel) => void;
reactionInit: Function; reactionInit: (message: TAnyMessageModel) => void;
onReactionPress: Function; onReactionPress: (shortname: string, messageId: string) => void;
replyInit: Function; replyInit: (message: TAnyMessageModel, mention: boolean) => void;
isMasterDetail: boolean; isMasterDetail: boolean;
isReadOnly: boolean; isReadOnly: boolean;
Message_AllowDeleting: boolean; Message_AllowDeleting?: boolean;
Message_AllowDeleting_BlockDeleteInMinutes: number; Message_AllowDeleting_BlockDeleteInMinutes?: number;
Message_AllowEditing: boolean; Message_AllowEditing?: boolean;
Message_AllowEditing_BlockEditInMinutes: number; Message_AllowEditing_BlockEditInMinutes?: number;
Message_AllowPinning: boolean; Message_AllowPinning?: boolean;
Message_AllowStarring: boolean; Message_AllowStarring?: boolean;
Message_Read_Receipt_Store_Users: boolean; Message_Read_Receipt_Store_Users?: boolean;
server: string; server: string;
editMessagePermission: []; editMessagePermission?: string[];
deleteMessagePermission: []; deleteMessagePermission?: string[];
forceDeleteMessagePermission: []; forceDeleteMessagePermission?: string[];
pinMessagePermission: []; pinMessagePermission?: string[];
} }
const MessageActions = React.memo( const MessageActions = React.memo(
@ -69,9 +69,14 @@ const MessageActions = React.memo(
pinMessagePermission pinMessagePermission
}: IMessageActions, }: IMessageActions,
ref ref
): any => { ) => {
let permissions: any = {}; let permissions = {
const { showActionSheet, hideActionSheet }: any = useActionSheet(); hasEditPermission: false,
hasDeletePermission: false,
hasForceDeletePermission: false,
hasPinPermission: false
};
const { showActionSheet, hideActionSheet } = useActionSheet();
const getPermissions = async () => { const getPermissions = async () => {
try { try {
@ -88,9 +93,9 @@ const MessageActions = React.memo(
} }
}; };
const isOwn = (message: any) => message.u && message.u._id === user.id; const isOwn = (message: TAnyMessageModel) => message.u && message.u._id === user.id;
const allowEdit = (message: any) => { const allowEdit = (message: TAnyMessageModel) => {
if (isReadOnly) { if (isReadOnly) {
return false; return false;
} }
@ -105,7 +110,7 @@ const MessageActions = React.memo(
if (message.ts != null) { if (message.ts != null) {
msgTs = moment(message.ts); msgTs = moment(message.ts);
} }
let currentTsDiff: any; let currentTsDiff = 0;
if (msgTs != null) { if (msgTs != null) {
currentTsDiff = moment().diff(msgTs, 'minutes'); currentTsDiff = moment().diff(msgTs, 'minutes');
} }
@ -114,7 +119,7 @@ const MessageActions = React.memo(
return true; return true;
}; };
const allowDelete = (message: any) => { const allowDelete = (message: TAnyMessageModel) => {
if (isReadOnly) { if (isReadOnly) {
return false; return false;
} }
@ -136,7 +141,7 @@ const MessageActions = React.memo(
if (message.ts != null) { if (message.ts != null) {
msgTs = moment(message.ts); msgTs = moment(message.ts);
} }
let currentTsDiff: any; let currentTsDiff = 0;
if (msgTs != null) { if (msgTs != null) {
currentTsDiff = moment().diff(msgTs, 'minutes'); currentTsDiff = moment().diff(msgTs, 'minutes');
} }
@ -145,19 +150,19 @@ const MessageActions = React.memo(
return true; return true;
}; };
const getPermalink = (message: any) => RocketChat.getPermalinkMessage(message); const getPermalink = (message: TAnyMessageModel) => RocketChat.getPermalinkMessage(message);
const handleReply = (message: any) => { const handleReply = (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_REPLY); logEvent(events.ROOM_MSG_ACTION_REPLY);
replyInit(message, true); replyInit(message, true);
}; };
const handleEdit = (message: any) => { const handleEdit = (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_EDIT); logEvent(events.ROOM_MSG_ACTION_EDIT);
editInit(message); editInit(message);
}; };
const handleCreateDiscussion = (message: any) => { const handleCreateDiscussion = (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_DISCUSSION); logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
const params = { message, channel: room, showCloseModal: true }; const params = { message, channel: room, showCloseModal: true };
if (isMasterDetail) { if (isMasterDetail) {
@ -167,7 +172,7 @@ const MessageActions = React.memo(
} }
}; };
const handleUnread = async (message: any) => { const handleUnread = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_UNREAD); logEvent(events.ROOM_MSG_ACTION_UNREAD);
const { id: messageId, ts } = message; const { id: messageId, ts } = message;
const { rid } = room; const { rid } = room;
@ -179,7 +184,7 @@ const MessageActions = React.memo(
const subRecord = await subCollection.find(rid); const subRecord = await subCollection.find(rid);
await db.write(async () => { await db.write(async () => {
try { try {
await subRecord.update(sub => (sub.lastOpen = ts)); await subRecord.update(sub => (sub.lastOpen = ts as Date)); // TODO: reevaluate IMessage
} catch { } catch {
// do nothing // do nothing
} }
@ -192,42 +197,44 @@ const MessageActions = React.memo(
} }
}; };
const handlePermalink = async (message: any) => { const handlePermalink = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_PERMALINK); logEvent(events.ROOM_MSG_ACTION_PERMALINK);
try { try {
const permalink: any = await getPermalink(message); const permalink = await getPermalink(message);
Clipboard.setString(permalink); Clipboard.setString(permalink ?? '');
EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') }); EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') });
} catch { } catch {
logEvent(events.ROOM_MSG_ACTION_PERMALINK_F); logEvent(events.ROOM_MSG_ACTION_PERMALINK_F);
} }
}; };
const handleCopy = async (message: any) => { const handleCopy = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_COPY); logEvent(events.ROOM_MSG_ACTION_COPY);
await Clipboard.setString(message?.attachments?.[0]?.description || message.msg); await Clipboard.setString((message?.attachments?.[0]?.description || message.msg) ?? '');
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') }); EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
}; };
const handleShare = async (message: any) => { const handleShare = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_SHARE); logEvent(events.ROOM_MSG_ACTION_SHARE);
try { try {
const permalink: any = await getPermalink(message); const permalink = await getPermalink(message);
Share.share({ message: permalink }); if (permalink) {
Share.share({ message: permalink });
}
} catch { } catch {
logEvent(events.ROOM_MSG_ACTION_SHARE_F); logEvent(events.ROOM_MSG_ACTION_SHARE_F);
} }
}; };
const handleQuote = (message: any) => { const handleQuote = (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_QUOTE); logEvent(events.ROOM_MSG_ACTION_QUOTE);
replyInit(message, false); replyInit(message, false);
}; };
const handleStar = async (message: any) => { const handleStar = async (message: TAnyMessageModel) => {
logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR); logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
try { try {
await RocketChat.toggleStarMessage(message.id, message.starred); await RocketChat.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') }); EventEmitter.emit(LISTENER, { message: message.starred ? I18n.t('Message_unstarred') : I18n.t('Message_starred') });
} catch (e) { } catch (e) {
logEvent(events.ROOM_MSG_ACTION_STAR_F); logEvent(events.ROOM_MSG_ACTION_STAR_F);
@ -235,20 +242,21 @@ const MessageActions = React.memo(
} }
}; };
const handlePin = async (message: any) => { const handlePin = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_PIN); logEvent(events.ROOM_MSG_ACTION_PIN);
try { try {
await RocketChat.togglePinMessage(message.id, message.pinned); await RocketChat.togglePinMessage(message.id, message.pinned as boolean); // TODO: reevaluate `message.pinned` type on IMessage
} catch (e) { } catch (e) {
logEvent(events.ROOM_MSG_ACTION_PIN_F); logEvent(events.ROOM_MSG_ACTION_PIN_F);
log(e); log(e);
} }
}; };
const handleReaction = (shortname: any, message: any) => { const handleReaction: IHeader['handleReaction'] = (shortname, message) => {
logEvent(events.ROOM_MSG_ACTION_REACTION); logEvent(events.ROOM_MSG_ACTION_REACTION);
if (shortname) { if (shortname) {
onReactionPress(shortname, message.id); // TODO: evaluate unification with IEmoji
onReactionPress(shortname as any, message.id);
} else { } else {
reactionInit(message); reactionInit(message);
} }
@ -256,7 +264,7 @@ const MessageActions = React.memo(
hideActionSheet(); hideActionSheet();
}; };
const handleReadReceipt = (message: any) => { const handleReadReceipt = (message: TAnyMessageModel) => {
if (isMasterDetail) { if (isMasterDetail) {
Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } }); Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
} else { } else {
@ -291,7 +299,7 @@ const MessageActions = React.memo(
} }
}; };
const handleReport = async (message: any) => { const handleReport = async (message: TAnyMessageModel) => {
logEvent(events.ROOM_MSG_ACTION_REPORT); logEvent(events.ROOM_MSG_ACTION_REPORT);
try { try {
await RocketChat.reportMessage(message.id); await RocketChat.reportMessage(message.id);
@ -302,14 +310,14 @@ const MessageActions = React.memo(
} }
}; };
const handleDelete = (message: any) => { const handleDelete = (message: TAnyMessageModel) => {
showConfirmationAlert({ showConfirmationAlert({
message: I18n.t('You_will_not_be_able_to_recover_this_message'), message: I18n.t('You_will_not_be_able_to_recover_this_message'),
confirmationText: I18n.t('Delete'), confirmationText: I18n.t('Delete'),
onPress: async () => { onPress: async () => {
try { try {
logEvent(events.ROOM_MSG_ACTION_DELETE); logEvent(events.ROOM_MSG_ACTION_DELETE);
await RocketChat.deleteMessage(message.id, message.subscription.id); await RocketChat.deleteMessage(message.id, message.subscription ? message.subscription.id : '');
} catch (e) { } catch (e) {
logEvent(events.ROOM_MSG_ACTION_DELETE_F); logEvent(events.ROOM_MSG_ACTION_DELETE_F);
log(e); log(e);
@ -319,7 +327,7 @@ const MessageActions = React.memo(
}; };
const getOptions = (message: TAnyMessageModel) => { const getOptions = (message: TAnyMessageModel) => {
let options: any = []; let options: TActionSheetOptionsItem[] = [];
// Reply // Reply
if (!isReadOnly) { if (!isReadOnly) {
@ -463,16 +471,15 @@ const MessageActions = React.memo(
} }
) )
); );
const mapStateToProps = (state: IApplicationState) => ({
const mapStateToProps = (state: any) => ({
server: state.server.server, server: state.server.server,
Message_AllowDeleting: state.settings.Message_AllowDeleting, Message_AllowDeleting: state.settings.Message_AllowDeleting as boolean,
Message_AllowDeleting_BlockDeleteInMinutes: state.settings.Message_AllowDeleting_BlockDeleteInMinutes, Message_AllowDeleting_BlockDeleteInMinutes: state.settings.Message_AllowDeleting_BlockDeleteInMinutes as number,
Message_AllowEditing: state.settings.Message_AllowEditing, Message_AllowEditing: state.settings.Message_AllowEditing as boolean,
Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes, Message_AllowEditing_BlockEditInMinutes: state.settings.Message_AllowEditing_BlockEditInMinutes as number,
Message_AllowPinning: state.settings.Message_AllowPinning, Message_AllowPinning: state.settings.Message_AllowPinning as boolean,
Message_AllowStarring: state.settings.Message_AllowStarring, Message_AllowStarring: state.settings.Message_AllowStarring as boolean,
Message_Read_Receipt_Store_Users: state.settings.Message_Read_Receipt_Store_Users, Message_Read_Receipt_Store_Users: state.settings.Message_Read_Receipt_Store_Users as boolean,
isMasterDetail: state.app.isMasterDetail, isMasterDetail: state.app.isMasterDetail,
editMessagePermission: state.permissions['edit-message'], editMessagePermission: state.permissions['edit-message'],
deleteMessagePermission: state.permissions['delete-message'], deleteMessagePermission: state.permissions['delete-message'],

View File

@ -1,8 +1,9 @@
// TODO: evaluate unification with IEmoji
export interface IEmoji { export interface IEmoji {
content: any; content?: string;
name: string; name?: string;
extension: any; extension?: string;
isCustom: boolean; isCustom?: boolean;
} }
export interface ICustomEmoji { export interface ICustomEmoji {

View File

@ -1,5 +1,6 @@
import Model from '@nozbe/watermelondb/Model'; import Model from '@nozbe/watermelondb/Model';
// TODO: evaluate unification with IEmoji
export interface IFrequentlyUsedEmoji { export interface IFrequentlyUsedEmoji {
content?: string; content?: string;
extension?: string; extension?: string;

View File

@ -7,7 +7,7 @@ import { TNavigationOptions } from './definitions/navigationTypes';
export interface IDimensionsContextProps { export interface IDimensionsContextProps {
width: number; width: number;
height: number; height: number;
scale?: number; scale: number;
fontScale: number; fontScale: number;
setDimensions?: ({ setDimensions?: ({
width, width,