import React, { ReactNode } from "react";
import { Room, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
import { Layout } from "../../settings/enums/Layout";
import { GetRelationsForEvent, UnwrappedEventTile } from "../views/rooms/EventTile";
import LegacyCallEventGrouper from "./LegacyCallEventGrouper";
import { IScrollState } from "./ScrollPanel";
import { SeparatorKind } from "../views/messages/TimelineSeparator";
import ResizeNotifier from "../../utils/ResizeNotifier";
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
import EditorStateTransfer from "../../utils/EditorStateTransfer";
export declare function shouldFormContinuation(prevEvent: MatrixEvent | null, mxEvent: MatrixEvent, matrixClient: MatrixClient, showHiddenEvents: boolean, timelineRenderingType?: TimelineRenderingType): boolean;
interface IProps {
    events: MatrixEvent[];
    hidden?: boolean;
    backPaginating?: boolean;
    forwardPaginating?: boolean;
    highlightedEventId?: string;
    room?: Room;
    showUrlPreview?: boolean;
    readMarkerEventId?: string | null;
    readMarkerVisible?: boolean;
    ourUserId?: string;
    canBackPaginate?: boolean;
    showReadReceipts?: boolean;
    stickyBottom?: boolean;
    className?: string;
    isTwelveHour?: boolean;
    alwaysShowTimestamps?: boolean;
    showReactions?: boolean;
    layout?: Layout;
    resizeNotifier?: ResizeNotifier;
    permalinkCreator?: RoomPermalinkCreator;
    editState?: EditorStateTransfer;
    onScroll?(event: Event): void;
    onFillRequest?(backwards: boolean): Promise<boolean>;
    onUnfillRequest?(backwards: boolean, scrollToken: string | null): void;
    getRelationsForEvent?: GetRelationsForEvent;
    hideThreadedMessages?: boolean;
    disableGrouping?: boolean;
    callEventGroupers: Map<string, LegacyCallEventGrouper>;
}
interface IState {
    ghostReadMarkers: string[];
    showTypingNotifications: boolean;
    hideSender: boolean;
}
export default class MessagePanel extends React.Component<IProps, IState> {
    static contextType: React.Context<import("./RoomView").IRoomState & {
        threadId?: string;
    }>;
    context: React.ContextType<typeof RoomContext>;
    static defaultProps: {
        disableGrouping: boolean;
    };
    private readReceiptMap;
    private readReceiptsByEvent;
    private readReceiptsByUserId;
    private readonly _showHiddenEvents;
    private isMounted;
    private readMarkerNode;
    private whoIsTyping;
    private scrollPanel;
    private readonly showTypingNotificationsWatcherRef;
    private eventTiles;
    grouperKeyMap: WeakMap<MatrixEvent, string>;
    constructor(props: IProps, context: React.ContextType<typeof RoomContext>);
    componentDidMount(): void;
    componentWillUnmount(): void;
    componentDidUpdate(prevProps: IProps, prevState: IState): void;
    private shouldHideSender;
    private calculateRoomMembersCount;
    private onShowTypingNotificationsChange;
    getNodeForEventId(eventId: string): HTMLElement | undefined;
    getTileForEventId(eventId?: string): UnwrappedEventTile | undefined;
    isAtBottom(): boolean | undefined;
    getScrollState(): IScrollState | null;
    getReadMarkerPosition(): number | null;
    scrollToTop(): void;
    scrollToBottom(): void;
    /**
     * Scroll up/down in response to a scroll key
     *
     * @param {KeyboardEvent} ev: the keyboard event to handle
     */
    handleScrollKey(ev: React.KeyboardEvent | KeyboardEvent): void;
    scrollToEvent(eventId: string, pixelOffset?: number, offsetBase?: number): void;
    scrollToEventIfNeeded(eventId: string): void;
    private isUnmounting;
    get showHiddenEvents(): boolean;
    shouldShowEvent(mxEv: MatrixEvent, forceHideEvents?: boolean): boolean;
    readMarkerForEvent(eventId: string, isLastEvent: boolean): ReactNode;
    private collectGhostReadMarker;
    private onGhostTransitionEnd;
    /**
     * Find the next event in the list, and the next visible event in the list.
     *
     * @param events     - the list of events to look in and whether they are shown
     * @param i          - where in the list we are now
     *
     * @returns { nextEvent, nextTile }
     *
     * nextEvent is the event after i in the supplied array.
     *
     * nextTile is the first event in the array after i that we will show a tile
     * for. It is used to to determine the 'last successful' flag when rendering
     * the tile.
     */
    private getNextEventInfo;
    private get pendingEditItem();
    private isSentState;
    private getEventTiles;
    getTilesForEvent(prevEvent: MatrixEvent | null, wrappedEvent: WrappedEvent, last?: boolean, isGrouped?: boolean, nextEvent?: WrappedEvent | null, nextEventWithTile?: MatrixEvent | null): ReactNode[];
    wantsSeparator(prevEvent: MatrixEvent | null, mxEvent: MatrixEvent): SeparatorKind;
    private getReadReceiptsForEvent;
    private getReadReceiptsByShownEvent;
    private collectEventTile;
    onHeightChanged: () => void;
    private onTypingShown;
    private onTypingHidden;
    updateTimelineMinHeight(): void;
    onTimelineReset(): void;
    render(): React.ReactNode;
}
/**
 * Holds on to an event, caching the information about it in the context of the current messages list.
 * Avoids calling shouldShowEvent more times than we need to.
 * Simplifies threading of event context like whether it's the last successful event we sent which cannot be determined
 * by a consumer from the event alone, so has to be done by the event list processing code earlier.
 */
export interface WrappedEvent {
    event: MatrixEvent;
    shouldShow?: boolean;
    lastSuccessfulWeSent?: boolean;
}
export {};
