diff --git a/app/containers/ActionSheet/Provider.tsx b/app/containers/ActionSheet/Provider.tsx index 30982a32..4da84069 100644 --- a/app/containers/ActionSheet/Provider.tsx +++ b/app/containers/ActionSheet/Provider.tsx @@ -7,8 +7,8 @@ export type TActionSheetOptionsItem = { title: string; icon: TIconsName; onPress 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/MessageActions/index.tsx b/app/containers/MessageActions/index.tsx index d54d8780..1c7ca953 100644 --- a/app/containers/MessageActions/index.tsx +++ b/app/containers/MessageActions/index.tsx @@ -19,7 +19,7 @@ import { IApplicationState, ILoggedUser, TAnyMessageModel, TSubscriptionModel } import { getPermalinkMessage, hasPermission } from '../../lib/methods'; import { Services } from '../../lib/services'; -export interface IMessageActions { +export interface IMessageActionsProps { room: TSubscriptionModel; tmid?: string; user: Pick; @@ -43,8 +43,12 @@ export interface IMessageActions { pinMessagePermission?: string[]; } +export interface IMessageActions { + showMessageActions: (message: TAnyMessageModel) => Promise; +} + const MessageActions = React.memo( - forwardRef( + forwardRef( ( { room, @@ -68,7 +72,7 @@ const MessageActions = React.memo( deleteMessagePermission, forceDeleteMessagePermission, pinMessagePermission - }: IMessageActions, + }, ref ) => { let permissions = { diff --git a/app/containers/MessageBox/index.tsx b/app/containers/MessageBox/index.tsx index 235ffd7d..91f334a5 100644 --- a/app/containers/MessageBox/index.tsx +++ b/app/containers/MessageBox/index.tsx @@ -128,7 +128,7 @@ interface IMessageBoxState { } class MessageBox extends Component { - private text: string; + public text: string; private selection: { start: number; end: number }; @@ -1182,4 +1182,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 6a5d9e02..de5829e9 100644 --- a/app/containers/MessageErrorActions.tsx +++ b/app/containers/MessageErrorActions.tsx @@ -9,9 +9,12 @@ 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 resendMessage(message, tmid); diff --git a/app/views/RoomView/JoinCode.tsx b/app/views/RoomView/JoinCode.tsx index 58ce81d8..db1bf1e4 100644 --- a/app/views/RoomView/JoinCode.tsx +++ b/app/views/RoomView/JoinCode.tsx @@ -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(''); @@ -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 f28f2836..438e2574 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/index.tsx b/app/views/RoomView/List/index.tsx index 37680108..1d80efdd 100644 --- a/app/views/RoomView/List/index.tsx +++ b/app/views/RoomView/List/index.tsx @@ -16,7 +16,7 @@ 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'; @@ -43,7 +43,7 @@ export interface IListContainerProps { tmid?: string; theme: TSupportedThemes; loading: boolean; - listRef: React.RefObject; + listRef: TListRef; hideSystemMessages?: string[]; tunread?: string[]; ignored?: string[]; @@ -272,8 +272,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) => @@ -283,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) { @@ -300,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(); } @@ -316,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 = () => { @@ -367,4 +363,6 @@ class ListContainer extends React.Component { user: Pick; @@ -151,14 +158,12 @@ 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 }; roomUpdate: { - [K in TRoomUpdate]?: any; // TODO: get type from TSubscriptionModel + [K in TRoomUpdate]?: any; }; member: any; lastOpen: Date | null; @@ -182,23 +187,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); @@ -312,6 +321,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; @@ -340,8 +350,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 @@ -379,7 +388,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) { @@ -394,9 +402,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; }); }); @@ -543,20 +551,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 @@ -695,7 +701,6 @@ class RoomView extends React.Component { }; errorActionsShow = (message: TAnyMessageModel) => { - // @ts-ignore this.messageErrorActions?.showMessageErrorActions(message); }; @@ -745,7 +750,6 @@ class RoomView extends React.Component { }; onMessageLongPress = (message: TAnyMessageModel) => { - // @ts-ignore this.messageActions?.showMessageActions(message); }; @@ -875,10 +879,8 @@ class RoomView extends React.Component { if (message.fromServer && !message.tmid && 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); @@ -920,8 +922,7 @@ class RoomView extends React.Component { const { user } = this.props; 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(); @@ -959,7 +960,6 @@ class RoomView extends React.Component { } else { const { joinCodeRequired, rid } = room; if (joinCodeRequired) { - // @ts-ignore this.joinCode.current?.show(); } else { await Services.joinRoom(rid, null, this.t as any); @@ -1102,17 +1102,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); + } } } } @@ -1360,7 +1360,6 @@ class RoomView extends React.Component { return ( <> (this.messageActions = ref)} tmid={this.tmid} room={room} @@ -1371,7 +1370,6 @@ class RoomView extends React.Component { onReactionPress={this.onReactionPress} isReadOnly={readOnly} /> - {/* @ts-ignore TODO: missing interface on MessageErrorActions */} (this.messageErrorActions = ref)} tmid={this.tmid} /> ); @@ -1396,11 +1394,9 @@ class RoomView extends React.Component {