/**
 * A node in a {@link TextBlock} that renders its children as a clickable {@link https://talkjs.com/docs/Guides/JavaScript/Classic/Action_Buttons_Links/ | action button} which triggers a custom action.
 *
 * @remarks
 * By default, users do not have permission to send messages containing action buttons as they can be used maliciously to trick others into invoking custom actions.
 * For example, a user could send an "accept offer" action button, but disguise it as "view offer".
 *
 * @public
 */
export declare interface ActionButtonNode {
    readonly type: "actionButton";
    /**
     * The name of the custom action to invoke when the button is clicked.
     */
    readonly action: string;
    /**
     * The parameters to pass to the custom action when the button is clicked.
     */
    readonly params: Record<string, string>;
    readonly children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that renders its children as a clickable {@link https://talkjs.com/docs/Guides/JavaScript/Classic/Action_Buttons_Links/ | action link} which triggers a custom action.
 *
 * @remarks
 * By default, users do not have permission to send messages containing `ActionLinkNode` as it can be used maliciously to trick others into invoking custom actions.
 * For example, a user could send an "accept offer" action link, but disguise it as a link to a website.
 *
 * @public
 */
export declare interface ActionLinkNode {
    readonly type: "actionLink";
    /**
     * The name of the custom action to invoke when the link is clicked.
     */
    readonly action: string;
    /**
     * The parameters to pass to the custom action when the link is clicked.
     */
    readonly params: Record<string, string>;
    readonly children: TextNode[];
}

/**
 * A FileBlock variant for an audio attachment, with additional audio-specific metadata.
 *
 * @remarks
 * You can identify this variant by checking for `subtype: "audio"`.
 *
 * The same file could be uploaded as either an audio block, or as a {@link VoiceBlock}.
 * The same data will be available either way, but they will be rendered differently in the UI.
 *
 * Includes metadata about the duration of the audio file in seconds, where available.
 *
 * Audio files that you upload with the TalkJS UI will include the duration as long as the sender's browser can preview the file.
 * Audio files that you upload with the REST API or {@link Session.uploadAudio} will include the duration if you specified it when uploading.
 * Audio files attached in a reply to an email notification will not include the duration.
 *
 * @public
 */
export declare interface AudioBlock {
    readonly type: "file";
    readonly subtype: "audio";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this file in another message.
     */
    readonly fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    readonly url: string;
    /**
     * The size of the file in bytes
     */
    readonly size: number;
    /**
     * The name of the audio file, including file extension
     */
    readonly filename: string;
    /**
     * The duration of the audio in seconds, if known
     */
    readonly duration?: number;
}

export declare interface AudioFileMetadata {
    /**
     * The name of the file including extension.
     */
    filename: string;
    /**
     * The duration of the audio file in seconds, if known.
     */
    duration?: number;
}

/**
 * A node in a {@link TextBlock} that renders `text` as a link (HTML `<a>`).
 *
 * @remarks
 * Used when user-typed text is turned into a link automatically.
 *
 * Unlike {@link LinkNode}, users do have permission to send AutoLinkNodes by default, because the `text` and `url` properties must match.
 * Specifically:
 *
 * - If `text` is an email, `url` must contain a `mailto:` link to the same email address
 *
 * - If `text` is a phone number, `url` must contain a `tel:` link to the same phone number
 *
 * - If `text` is a website, the domain name including subdomains must be the same in both `text` and `url`.
 * If `text` includes a protocol (such as `https`), path (/page), query string (?page=true), or url fragment (#title), they must be the same in `url`.
 * If `text` does not specify a protocol, `url` must use either `https` or `http`.
 *
 * This means that the following AutoLink is valid:
 *
 * ```json
 * {
 *     type: "autoLink",
 *     text: "talkjs.com"
 *     url: "https://talkjs.com/docs/JavaScript_Data_API/Message_Content/#AutoLinkNode"
 * }
 * ```
 *
 * That link will appear as `talkjs.com` and link you to the specific section of the documentation that explains how AutoLinkNodes work.
 *
 * These rules ensure that the user knows what link they are clicking, and prevents AutoLinkNode being used for phishing.
 * If you try to send a message containing an AutoLink that breaks these rules, the request will be rejected.
 *
 * @public
 */
export declare interface AutoLinkNode {
    readonly type: "autoLink";
    /**
     * The URL to open when a user clicks this node.
     */
    readonly url: string;
    /**
     * The text to display in the link.
     */
    readonly text: string;
}

/**
 * A node in a {@link TextBlock} that adds indentation for a bullet-point list around its children (HTML `<ul>`).
 *
 * @remarks
 * Used when users send a bullet-point list by starting lines of their message with `-` or `*`.
 *
 * @public
 */
export declare interface BulletListNode {
    readonly type: "bulletList";
    readonly children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that renders its children with a bullet-point (HTML `<li>`).
 *
 * @remarks
 * Used when users start a line of their message with `-` or `*`.
 *
 * @public
 */
export declare interface BulletPointNode {
    readonly type: "bulletPoint";
    readonly children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that renders `text` in an inline code span (HTML `<code>`).
 *
 * @remarks
 * Used when a user types ```text```.
 *
 * @public
 */
export declare interface CodeSpanNode {
    readonly type: "codeSpan";
    readonly text: string;
}

/**
 * Combines multiple simple filters into one, matching whenever any of the simple filters match (OR).
 *
 * @remarks
 * The first element must be the string "any", and the second element a list of simple filter objects.
 *
 * See {@link SimpleConversationFilter} for all available options in simple conversation filters.
 *
 * @example Only show conversations with messages, and empty conversations with the subject "cats!"
 * ```json
 * ["any", [
 *   { hasMessages: true },
 *   { subject: ["==", "cats!"] }
 * ]]
 * ```
 *
 * @public
 */
export declare type CompoundFilter<T> = ["any", T[]];

/**
 * The content of a message is structured as a list of content blocks.
 *
 * @remarks
 * Currently, each message can only have one content block, but this will change in the future.
 * This will not be considered a breaking change, so your code should assume there can be multiple content blocks.
 *
 * These blocks are rendered in order, top-to-bottom.
 *
 * Currently the available Content Block types are:
 *
 * - `type: "text"` ({@link TextBlock})
 *
 * - `type: "file"` ({@link FileBlock})
 *
 * - `type: "location"` ({@link LocationBlock})
 *
 * @public
 */
export declare type ContentBlock = TextBlock | FileBlock | LocationBlock;

/**
 * The state of a conversation subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ConversationActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the conversation, or `null` if you are not a participant in the conversation (including when the conversation does not exist).
     */
    readonly latestSnapshot: ConversationSnapshot | null;
}

/**
 * Passed to `Session.subscribeConversations`, specifying which conversations should be returned in the subscription.
 *
 * @remarks
 * Either a {@link SimpleConversationFilter} or a {@link CompoundFilter} OR-ing multiple simple filters together.
 *
 * @example A simple conversation filter that only includes conversations with the subject "cats!"
 * ```json
 * { subject: ["==", "cats!"] }
 * ```
 *
 * @example A compound conversation filter that includes conversations with messages, and empty conversations with the subject "cats!"
 * ```json
 * ["any", [
 *   { hasMessages: true },
 *   { subject: ["==", "cats!"] }
 * ]]
 *
 * @public
 */
export declare type ConversationFilter = SimpleConversationFilter | CompoundFilter<SimpleConversationFilter>;

/**
 * The state of a conversation list subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ConversationListActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the conversations
     */
    readonly latestSnapshot: ConversationSnapshot[];
    /**
     * True if `latestSnapshot` contains all conversations you are in.
     * Use {@link ConversationListSubscription.loadMore} to load more.
     */
    readonly loadedAll: boolean;
}

/**
 * A subscription to your most recently active conversations.
 *
 * @remarks
 * Get a ConversationListSubscription by calling {@link Session.subscribeConversations}.
 *
 * The subscription is 'windowed'. Initially, this window contains the 20 most recent conversations.
 * Conversations are ordered by last activity. The last activity of a conversation is either `joinedAt` or `lastMessage.createdAt`, whichever is higher.
 *
 * The window will automatically expand to include any conversations you join, and any old conversations that receive new messages after subscribing.
 *
 * You can expand this window by calling {@link ConversationListSubscription.loadMore}, which extends the window further into the past.
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface ConversationListSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot` and `loadedAll`.
     *
     * - `latestSnapshot: ConversationSnapshot[]` the current state of the conversations in the window
     *
     * - `loadedAll: boolean` true when `latestSnapshot` contains all the conversations you are in
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | ConversationListActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<ConversationListActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older conversations
     *
     * @remarks
     * The `count` parameter is relative to the current number of loaded conversations.
     * If you call `loadMore(5)` and then call `loadMore(10)` immediately afterwards (without awaiting the promise),
     * then only 10 additional conversations will be loaded, not 15.
     *
     * Avoid calling `.loadMore` in a loop until you have loaded all conversations.
     * This is usually unnecessary: any time a conversation receives a message, it appears at the start of the list of conversations.
     * If you do need to call loadMore in a loop, make sure you set a small upper bound (e.g. 100) on the number of conversations, where the loop will exit.
     *
     * @param count - The number of additional conversations to load. Must be between 1 and 30. Default 20.
     * @returns A promise that resolves once the additional conversations have loaded
     */
    loadMore(count?: number): Promise<void>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * References the current user's view of the conversation with a given conversation ID.
 *
 * @remarks
 * Used in all Data API operations affecting that conversation, such as fetching or updating conversation attributes.
 * Created via {@link Session.conversation|Session.conversation()}.
 *
 * Important note: ConversationRef is a reference to *the current user's view* of the conversation.
 *
 * If they are not a participant, "their view" of the conversation does not exist.
 * This means that {@link ConversationRef.get|ConversationRef.get()} will return null.
 * Additionally, it means that {@link ConversationRef.set|set()} and {@link ConversationRef.createIfNotExists|createIfNotExists()} will add the current user as a participant, in order to create "their view" of the conversation.
 * For more details, see the documentation for those methods.
 *
 * @public
 */
export declare interface ConversationRef {
    /**
     * The ID of the referenced conversation.
     *
     * @remarks
     * Immutable: if you want to reference a different conversation, get a new ConversationRef instead.
     */
    readonly id: string;
    /**
     * Get a reference to a participant in this conversation
     *
     * @remarks
     * Note that `Participant` is not the same as `User`.
     * A `Participant` represents a user's settings related to a specific conversation.
     *
     * Calling this method multiple times with the same ID reuses the same {@link ParticipantRef} object.
     *
     * Calling {@link ConversationRef.createIfNotExists|ConversationRef.createIfNotExists} or {@link ConversationRef.set|ConversationRef.set} will automatically add the current user as a participant.
     *
     * @example To add "Alice" to the conversation "Cats"
     * ```ts
     * session.conversation("Cats").participant("Alice").createIfNotExists();
     * ```
     *
     * The user "Alice" must exist before you do this.
     *
     * @example To remove "Alice" from the conversation "Cats"
     * ```ts
     * session.conversation("Cats").participant("Alice").delete();
     * ```
     *
     * The user "Alice" will still exist after you do this. This deletes the participant, not the user.
     *
     * @param user - Specifies which participant in the conversation you want to reference. Either the user's ID, or a reference to that user.
     * @returns A {@link ParticipantRef} for that user's participation in this conversation
     * @throws If the user is not a UserRef or a non-empty string
     * @public
     */
    participant(user: string | UserRef): ParticipantRef;
    /**
     * Get a reference to a message in this conversation
     *
     * @remarks
     * Use this if you need to fetch, delete, or edit a specific message in this conversation, and you know its message ID.
     *
     * Calling this method multiple times with the same ID reuses the same {@link MessageRef} object.
     *
     * To fetch the most recent messages in this conversation, use {@link ConversationRef.subscribeMessages} instead.
     * To send a message, use {@link ConversationRef.send}.
     *
     * @param id - The ID of the message that you want to reference
     * @returns A {@link MessageRef} for the message with that ID in this conversation
     * @throws If the id is not a string or is an empty string
     * @public
     */
    message(id: string): MessageRef;
    /**
     * Fetches a snapshot of the conversation.
     *
     * @remarks
     * This contains all of the information related to the conversation and the current user's participation in the conversation.
     *
     * @returns A snapshot of the current user's view of the conversation, or null if the current user is not a participant (including if the conversation doesn't exist).
     */
    get(): Promise<ConversationSnapshot | null>;
    /**
     * Sets properties of this conversation and the current user's participation.
     *
     * @remarks
     * If this conversation does not already exist, it will be created.
     *
     * If the user is not currently a participant in this conversation, they will be added.
     *
     * @returns A promise that resolves when the operation completes.
     * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
     * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
     */
    set(params: SetConversationParams): Promise<void>;
    /**
     * Creates this conversation if it does not already exist.
     * Adds you as a participant in this conversation, if you are not already a participant.
     *
     * @remarks
     * If the conversation already exists or you are already a participant, this operation is still considered successful and the promise will still resolve.
     *
     * @returns A promise that resolves when the operation completes. The promise rejects if you are not already a participant and client-side conversation syncing is disabled.
     */
    createIfNotExists(params?: CreateConversationParams): Promise<void>;
    /**
     * Marks the conversation as read.
     *
     * @returns A promise that resolves when the operation completes. The promise rejects if you are not a participant in the conversation.
     */
    markAsRead(): Promise<void>;
    /**
     * Marks the conversation as unread.
     *
     * @returns A promise that resolves when the operation completes. The promise rejects if you are not a participant in the conversation.
     */
    markAsUnread(): Promise<void>;
    /**
     * Sends a message in the conversation
     *
     * @example Send a simple message with markup (bold in this example)
     * ```ts
     * conversationRef.send("*Hello*");
     * ```
     *
     * @example Reply to a message and set custom message data
     * ```ts
     * conversationRef.send({
     *   text: "Agreed",
     *   referencedMessageId: "...",
     *   custom: { priority: "HIGH" }
     * });
     * ```
     *
     * @example Send pre-formatted text with {@link TextBlock}
     * ```ts
     * conversationRef.send({
     *   content: [{
     *     type: "text",
     *     children: [{
     *       type: "bold",
     *       children: ["Hello"]
     *     }]
     *   }]
     * });
     * ```
     *
     * @example Send a file with {@link SendFileBlock}
     * ```ts
     * // `file` is a File object from `<input type="file">`
     * const fileToken = await session.uploadImage(
     *   file, { filename: file.name, width: 640, height: 480 }
     * );
     *
     * conversationRef.send({
     *   content: [{ type: "file", fileToken }]
     * });
     * ```
     *
     * @example Send a location with {@link LocationBlock}
     * ```ts
     * // You can get the user's location with the browser's geolocation API
     * const [latitude, longitude] = [42.43, -83.99];
     * conversationRef.send({
     *   content: [{ type: "location", latitude, longitude }]
     * });
     * ```
     *
     * @returns A promise that resolves with a reference to the newly created message. The promise will reject if you do not have permission to send the message.
     */
    send(params: string | SendTextMessageParams | SendMessageParams): Promise<MessageRef>;
    /**
     * Subscribes to the messages in the conversation.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called whenever the message snapshots change.
     * This includes when a message is sent, edited, deleted, and when you load more messages.
     * It also includes when nested data changes, such as when `snapshot[0].referencedMessage.sender.name` changes.
     * `loadedAll` is true when `snapshot` contains all the messages in the conversation, and false if you could load more.
     *
     * The `snapshot` list is ordered chronologically with the most recent messages at the start.
     * When a new message is received, it will be added to the start of the list.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     *
     * Initially, you will be subscribed to the 30 most recent messages and any new messages.
     * Call `loadMore` to load additional older messages. This will trigger `onSnapshot`.
     *
     * Tip: If you only care about the most recent message in the conversation, use `ConversationRef.subscribe` or `Session.subscribeConversations`.
     * Then use the `ConversationSnapshot.lastMessage` property. This is easier to use and slightly more efficient.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     */
    subscribeMessages(onSnapshot?: (snapshot: MessageSnapshot[] | null, loadedAll: boolean) => void): MessageSubscription;
    /**
     * Subscribes to the participants in the conversation.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called whenever the participant snapshots change.
     * This includes when someone joins or leaves, when their participant attributes are edited, and when you load more participants.
     * It also includes when nested data changes, such as when `snapshot[0].user.name` changes.
     * `loadedAll` is true when `snapshot` contains all the participants in the conversation, and false if you could load more.
     *
     * The `snapshot` list is ordered chronologically with the participants who joined most recently at the start.
     * When someone joins the conversation, they will be added to the start of the list.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     *
     * Initially, you will be subscribed to the 10 participants who joined most recently, and any new participants.
     * Call `loadMore` to load additional older participants. This will trigger `onSnapshot`.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     */
    subscribeParticipants(onSnapshot?: (snapshot: ParticipantSnapshot[] | null, loadedAll: boolean) => void): ParticipantSubscription;
    /**
     * Subscribes to the conversation.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called when you join or leave the conversation, or when the snapshot changes.
     * This includes changes to nested data. As an extreme example, `onSnapshot` would be called when `snapshot.lastMessage.referencedMessage.sender.name` changes.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     */
    subscribe(onSnapshot?: (snapshot: ConversationSnapshot | null) => void): ConversationSubscription;
    /**
     * Subscribes to the typing status of the conversation.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called when you join or leave the conversation, or when the snapshot changes.
     * This includes changes to the nested `UserSnapshot`s. If one of the people who is typing, changes their name, `onSnapshot` will be called.
     * You will not be notified when there are already "many" people typing, and another person starts typing, because the snapshot does not change.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     */
    subscribeTyping(onSnapshot?: (snapshot: TypingSnapshot | null) => void): TypingSubscription;
    /**
     * Marks the current user as typing in this conversation for 10 seconds.
     *
     * @remarks
     * This means that other users will see a typing indicator in the UI, from the current user.
     *
     * The user will automatically stop typing after 10 seconds. You cannot manually mark a user as "not typing".
     * Users are also considered "not typing" when they send a message, even if that message was sent from a different tab or using the REST API.
     *
     * To keep the typing indicator visible for longer, call this function again to reset the 10s timer.
     *
     * @example Example implementation
     * ```ts
     * let lastMarkedAsTyping = 0;
     *
     * inputElement.addEventListener("change", event => {
     *   const text = event.target.value;
     *
     *   // Deleting your draft never counts as typing
     *   if (text.length === 0) {
     *     return;
     *   }
     *
     *   const now = Date.now();
     *
     *   // Call `markAsTyping` sparingly - not on every keystroke
     *   // Only call if it has been at least 5 seconds since last time
     *   if (now - lastMarkedAsTyping > 5000) {
     *     lastMarkedAsTyping = now;
     *     convRef.markAsTyping();
     *   }
     * });
     *
     * // When you send a message, you are no longer considered typing
     * // So we need to send markAsTyping as soon as you type something
     * function onSendMessage() {
     *   lastMarkedAsTyping = 0;
     * }
     * ```
     */
    markAsTyping(): Promise<void>;
}

/**
 * Search object returned by `TalkSession.searchConversations` functions.
 * Used to search for conversations the user is in.
 * @public
 */
export declare interface ConversationSearch {
    /**
     * Sets the query string for this search and starts searching for conversations whose `subject` or `custom.search` match the query.
     *
     * @remarks
     * This resets the search to its initial state, clearing all previous results.
     * Initially loads 3 results. Call {@link MessageSearch.loadMore} to load additional results.
     *
     * The query matches a conversation when, for each word in the query, that word appears in the conversation's subject or in `conversation.custom.search`.
     * This means one of the words in the string starts with the word from the query.
     * This is case-insensitive and punctuation at the start / end of words is ignored (in both the string and the query).
     *
     * A conversation titled `I like to look at rainbows`, will appear in searches for `rainbows`, `rain`, `look at`, `(look, i *LIKE* rain)`, and `look look look!`.
     * It will not appear in searches for `bows`, `rain-bows`, `look-at`, or `I like to look at rainbows too`.
     *
     * It is not possible to match both a conversation's subject and its `custom.search` field at the same time.
     * A conversation called `Kittens` with `custom.search: "where to buy food"` will not appear in a search for `kitten food`.
     * However, this only applies per-conversation. If there is one conversation with subject `Kittens` and a second conversation with `custom.search: "Kittens"`, then a search for `kittens` will return both conversations.
     *
     * You can optionally pass `filters.conversation` to restrict results to conversations that match a {@link ConversationFilter}.
     * Pass the same filter you use for a conversation list to keep search within that feed's scope. Omit it to search across all of the current user's conversations.
     *
     * @param query - The string to search for.
     * @param filters - Optional {@link ConversationSearchFilters}, e.g. `{ conversation }` to restrict results to conversations matching a {@link ConversationFilter}.
     * @returns A promise that resolves with the complete first page of results. The promise rejects if the search encounters an error.
     */
    setQuery(query: string, filters?: ConversationSearchFilters): Promise<ConversationSearchState>;
    /**
     * Continues searching for more conversations.
     *
     * @remarks
     * You can only call `loadMore` when the search has a query set, and is idle.
     * Calling `loadMore` before calling `setQuery`, while the `setQuery` promise is still pending, or while another `loadMore` promise is pending, has no effect.
     *
     * @param limit - The number of results to load. `limit` should be between 1 and 50. Default 10.
     * @returns A promise that resolves once finished loading, containing all the results from this page and all previous pages. The promise rejects if the search encounters an error.
     */
    loadMore(limit?: number): Promise<ConversationSearchState>;
}

/**
 * Filters for a conversation search, passed to {@link ConversationSearch.setQuery}.
 *
 * @public
 */
export declare interface ConversationSearchFilters {
    /**
     * Only return conversations that match this {@link ConversationFilter}.
     *
     * Pass the same filter you use for a conversation list to keep search within
     * that feed's scope.
     */
    conversation?: ConversationFilter;
}

/**
 * The state of a conversation search in the current step.
 *
 * @public
 */
export declare interface ConversationSearchState {
    /**
     * The conversations that were found in the search.
     */
    results: ConversationSnapshot[];
    /**
     * Whether all results have been loaded.
     *
     * @remarks
     * Note: When true, this means that the search has reached the oldest matching conversation and no more conversations can be loaded.
     * However, it does not mean that `results` contains every matching conversation.
     * Any conversations that received messages since you called `setQuery`, may be missing from `results`.
     */
    loadedAll: boolean;
}

/**
 * A snapshot of a conversation's attributes at a given moment in time.
 *
 * @remarks
 * Also includes information about the current user's view of that conversation, such as whether or not notifications are enabled.
 *
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface ConversationSnapshot {
    /**
     * The ID of the conversation
     */
    readonly id: string;
    /**
     * Contains the conversation subject, or `null` if the conversation does not have a subject specified.
     */
    readonly subject: string | null;
    /**
     * Contains the URL of a photo to represent the topic of the conversation or `null` if the conversation does not have a photo specified.
     */
    readonly photoUrl: string | null;
    /**
     * One or more welcome messages that will be rendered at the start of this conversation as system messages.
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are not real messages.
     * This means they do not appear when you list messages using the REST API or JS Data API, and you cannot reply or react to them.
     */
    readonly welcomeMessages: string[];
    /**
     * Custom metadata you have set on the conversation
     */
    readonly custom: Record<string, string>;
    /**
     * The date that the conversation was created, as a unix timestamp in milliseconds.
     */
    readonly createdAt: number;
    /**
     * The date that the current user joined the conversation, as a unix timestamp in milliseconds.
     */
    readonly joinedAt: number;
    /**
     * The last message sent in this conversation, or null if no messages have been sent.
     */
    readonly lastMessage: MessageSnapshot | null;
    /**
     * The number of messages in this conversation that the current user hasn't read.
     */
    readonly unreadMessageCount: number;
    /**
     * The most recent date that the current user read the conversation.
     *
     * @remarks
     * This value is updated whenever you read a message in a chat UI, open an email notification, or mark the conversation as read using an API like {@link ConversationRef.markAsRead}.
     *
     * Any messages sent after this timestamp are unread messages.
     */
    readonly readUntil: number;
    /**
     * Everyone in the conversation has read any messages sent on or before this date.
     *
     * @remarks
     * This is the minimum of all the participants' `readUntil` values.
     * Any messages sent on or before this timestamp should show a "read" indicator in the UI.
     *
     * This value will rarely change in very large conversations.
     * If just one person stops checking their messages, `everyoneReadUntil` will never update.
     */
    readonly everyoneReadUntil: number;
    /**
     * Whether the conversation should be considered unread.
     *
     * @remarks
     * This can be true even when `unreadMessageCount` is zero, if the user has manually marked the conversation as unread.
     */
    readonly isUnread: boolean;
    /**
     * The current user's permission level in this conversation.
     */
    readonly access: "Read" | "ReadWrite";
    /**
     * The current user's notification settings for this conversation.
     *
     * @remarks
     * `false` means no notifications, `true` means notifications for all messages, and `"MentionsOnly"` means that the user will only be notified when they are mentioned with an `@`.
     */
    readonly notify: boolean | "MentionsOnly";
}

/**
 * A subscription to a specific conversation.
 *
 * @remarks
 * Get a ConversationSubscription by calling {@link ConversationRef.subscribe}
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface ConversationSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot: ConversationSnapshot | null`, the current state of the conversation.
     * `latestSnapshot` is `null` when you are not a participant or the conversation does not exist.
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | ConversationActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     */
    readonly connected: Promise<ConversationActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * Parameters you can pass to {@link ConversationRef.createIfNotExists}.
 *
 * Properties that are `undefined` will be set to the default.
 *
 * @public
 */
export declare interface CreateConversationParams {
    /**
     * The conversation subject to display in the chat header.
     * Default = no subject, list participant names instead.
     */
    subject?: string;
    /**
     * The URL for the conversation photo to display in the chat header.
     * Default = no photo, show a placeholder image.
     */
    photoUrl?: string;
    /**
     * System messages which are sent at the beginning of a conversation.
     * Default = no messages.
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are not real messages.
     * This means they do not appear when you list messages using the REST API or JS Data API, and you cannot reply or react to them.
     */
    welcomeMessages?: string[];
    /**
     * Custom metadata to set on the conversation.
     * Default = no custom metadata
     */
    custom?: Record<string, string>;
    /**
     * Your access to the conversation.
     * Default = "ReadWrite" access.
     */
    access?: "Read" | "ReadWrite";
    /**
     * Your notification settings.
     * Default = `true`
     */
    notify?: boolean | "MentionsOnly";
}

/**
 * Parameters you can pass to {@link ParticipantRef.createIfNotExists}.
 *
 * @remarks
 * Properties that are `undefined` will be set to the default.
 *
 * @public
 */
export declare interface CreateParticipantParams {
    /**
     * The level of access the participant should have in the conversation.
     * Default = "ReadWrite" access.
     */
    access?: "ReadWrite" | "Read";
    /**
     * When the participant should be notified about new messages in this conversation.
     * Default = `true`
     *
     * @remarks
     * `false` means no notifications, `true` means notifications for all messages, and `"MentionsOnly"` means that the user will only be notified when they are mentioned with an `@`.
     */
    notify?: boolean | "MentionsOnly";
}

/**
 * Parameters you can pass to {@link UserRef.createIfNotExists}.
 *
 * @remarks
 * Properties that are `undefined` will be set to the default.
 *
 * @public
 */
export declare interface CreateUserParams {
    /**
     * The user's name which is displayed on the TalkJS UI
     */
    name: string;
    /**
     * Custom metadata you have set on the user.
     * Default = no custom metadata
     */
    custom?: Record<string, string>;
    /**
     * An {@link https://www.w3.org/International/articles/language-tags/ | IETF language tag}.
     * See the {@link https://talkjs.com/docs/Features/Language_Support/#localization | localization documentation}
     * Default = null, will use the locale set on the dashboard
     */
    locale?: string;
    /**
     * An optional URL to a photo that is displayed as the user's avatar.
     * Default = no photo
     */
    photoUrl?: string;
    /**
     * TalkJS supports multiple sets of settings, called "roles". These allow you to change the behavior of TalkJS for different users.
     * You have full control over which user gets which configuration.
     * Default = the `default` role
     */
    role?: string;
    /**
     * The default message a person sees when starting a chat with this user.
     * Default = no welcome message
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are not real messages.
     * This means they do not appear when you list messages using the REST API or JS Data API, and you cannot reply or react to them.
     *
     * Note: User welcome messages are only supported by the Classic SDKs, and in
     * the Components-based SDKs, this field is ignored. To show welcome messages
     * in the Components-based SDK, see
     * {@link https://talkjs.com/docs/Guides/React/Welcome_Messages/ | Welcome Messages}.
     *
     * @deprecated
     */
    welcomeMessage?: string;
    /**
     * A single email address or an array of email addresses associated with the user.
     * Default = no email addresses
     */
    email?: string | string[];
    /**
     * A single phone number or an array of phone numbers associated with the user.
     * Default = no phone numbers
     */
    phone?: string | string[];
    /**
     * An object of push registration tokens to use when notifying this user.
     *
     * Keys in the object have the format `'provider:token_id'`,
     * where `provider` is either `"fcm"` for Android (Firebase Cloud Messaging),
     * or `"apns"` for iOS (Apple Push Notification Service).
     *
     * Default = no push registration tokens
     */
    pushTokens?: Record<string, true>;
}

/**
 * A node in a {@link TextBlock} that is used for {@link https://talkjs.com/docs/Features/Messages/Emojis/#custom-emojis | custom emoji}.
 *
 * @public
 */
export declare interface CustomEmojiNode {
    readonly type: "customEmoji";
    /**
     * The name (including colons at the start and end) of the custom emoji to show.
     */
    readonly text: string;
}

/**
 * @public
 * A string or a two-element array that forms a predicate about a string field in a `custom` field.
 *
 * @remarks
 * Used in {@link MessagePredicate} and {@link ConversationPredicate}.
 * Allows all forms in {@link StringFilter} plus the following:
 *
 * - `"exists"`
 *
 * - `"!exists"`
 */
export declare type CustomFilter = Record<string, StringFilter | "exists" | "!exists">;

/**
 * Parameters you can pass to {@link MessageRef.edit}.
 *
 * @remarks
 * Properties that are `undefined` will not be changed.
 * To clear / reset a property to the default, pass `null`.
 *
 * This is the more advanced method for editing a message. It gives you full control over the message content.
 * You can decide exactly how a text message should be formatted, edit an attachment, or even turn a text message into a location.
 *
 * @public
 */
export declare interface EditMessageParams {
    /**
     * Custom metadata to set on the message.
     * This value acts as a patch. Remove specific properties by setting them to `null`.
     * Default = no custom metadata
     */
    custom?: Record<string, string | null> | null;
    /**
     * The new content for the message.
     *
     * @remarks
     * Any value provided here will overwrite the existing message content.
     *
     * By default users do not have permission to send {@link LinkNode}, {@link ActionLinkNode}, or {@link ActionButtonNode}, as they can be used to trick the recipient.
     */
    content?: [SendContentBlock];
}

/**
 * Parameters you can pass to {@link MessageRef.edit}.
 *
 * @remarks
 * Properties that are `undefined` will not be changed.
 * To clear / reset a property to the default, pass `null`.
 *
 * This is a simpler version of {@link EditMessageParams} that only supports setting the message content to text.
 *
 * @public
 */
export declare interface EditTextMessageParams {
    /**
     * Custom metadata to set on the message.
     * This value acts as a patch. Remove specific properties by setting them to `null`.
     * Default = no custom metadata
     */
    custom?: Record<string, string | null> | null;
    /**
     * The new text to set in the message body.
     *
     * @remarks
     * This is parsed the same way as the text entered in the message field. For example, `*hi*` will appear as `hi` in bold.
     *
     * See the {@link https://talkjs.com/docs/Features/Messages/Formatting/ | message formatting documentation} for more details.
     */
    text?: string;
}

/**
 * The state of a subscription after it encounters an unrecoverable error
 *
 * @public
 */
export declare interface ErrorState {
    readonly type: "error";
    /**
     * The error that caused the subscription to be terminated
     */
    readonly error: Error;
}

/**
 * The {@link TypingSnapshot} variant used when only a few people are typing.
 */
export declare interface FewTypingSnapshot {
    /**
     * Check this to differentiate between FewTypingSnapshot (`false`) and ManyTypingSnapshot (`true`).
     *
     * @remarks
     * When `false`, you can see the list of users who are typing in the `users` property.
     */
    readonly many: false;
    /**
     * The users who are currently typing in this conversation.
     *
     * @remarks
     * The list is in chronological order, starting with the users who have been typing the longest.
     * The current user is never contained in the list, only other users.
     */
    readonly users: UserSnapshot[];
}

/**
 * A file attachment received in a message's content.
 *
 * @remarks
 * All `FileBlock` variants contain `url`, `size`, and `fileToken`.
 * Some file blocks have additional metadata, in which case they will have the `subtype` property set.
 *
 * Currently the available FileBlock subtypes are:
 *
 * - No `subtype` set ({@link GenericFileBlock})
 *
 * - `subtype: "video"` ({@link VideoBlock})
 *
 * - `subtype: "image"` ({@link ImageBlock})
 *
 * - `subtype: "audio"` ({@link AudioBlock})
 *
 * - `subtype: "voice"` ({@link VoiceBlock})
 *
 * @public
 */
export declare type FileBlock = VideoBlock | ImageBlock | AudioBlock | VoiceBlock | GenericFileBlock;

/**
 * A token representing a file uploaded to TalkJS.
 *
 * @remarks
 * You cannot create a FileToken yourself. Get a file token by uploading your file to TalkJS with {@link Session.uploadFile}, or one of the subtype-specific variants like {@link Session.uploadImage}.
 * Alternatively, take a file token from an existing {@link FileBlock} to re-send an attachment you received, without having to download and re-upload the file.
 * You can also upload files using the {@link https://talkjs.com/docs/REST_API/Messages/#1-upload-a-file| REST API}.
 * This system ensures that all files must be uploaded to TalkJS before being sent to users, limiting the risk of malware.
 *
 * Passed in {@link SendFileBlock} when you send a message containing a file attachment.
 *
 * We may change the FileToken format in the future.
 * Do not store old file tokens for future use, as these may stop working.
 *
 * @example Using a file input
 * ```ts
 * // From `<input type="file">`
 * const file: File = fileInputElement.files[0];
 * const myFileToken = await session.uploadFile(file, { filename: file.name });
 *
 * const block = {
 *   type: 'file',
 *   fileToken: myFileToken,
 * };
 * session.conversation('example_conversation_id').send({ content: [block] });
 * ```
 *
 * @example Re-sending a file from a previous message
 * ```ts
 * session.conversation('example_conversation_id').send({
 *   content: previousMessageSnapshot.content
 * });
 * ```
 *
 * @public
 */
export declare type FileToken = string & {
    readonly __tag: Record<"TalkJS Encoded File Token", true>;
};

/**
 * The most basic FileBlock variant, used whenever there is no additional metadata for a file.
 *
 * @remarks
 * Do not try to check for `subtype === undefined` directly, as this will break when we add new FileBlock variants in the future.
 *
 * Instead, treat GenericFileBlock as the default. For example:
 *
 * ```ts
 * if (block.subtype === "video") {
 *     handleVideoBlock(block);
 * } else if (block.subtype === "image") {
 *     handleImageBlock(block);
 * } else if (block.subtype === "audio") {
 *     handleAudioBlock(block);
 * } else if (block.subtype === "voice") {
 *     handleVoiceBlock(block);
 * } else {
 *     handleGenericFileBlock(block);
 * }
 * ```
 *
 * @public
 */
export declare interface GenericFileBlock {
    readonly type: "file";
    /**
     * Never set for generic file blocks.
     */
    readonly subtype?: never;
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this file in another message.
     */
    readonly fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    readonly url: string;
    /**
     * The size of the file in bytes
     */
    readonly size: number;
    /**
     * The name of the file, including file extension
     */
    readonly filename: string;
}

export declare interface GenericFileMetadata {
    /**
     * The name of the file including extension.
     */
    filename: string;
}

/**
 * Returns a TalkSession for the specified App ID and User ID.
 *
 * @remarks
 * Backed by a registry, so calling this function twice with the same app and user returns the same session object both times.
 * A new session will be created if the old one encountered an error.
 */
export declare function getTalkSession(options: TalkSessionOptions): TalkSession;

/**
 * A FileBlock variant for an image attachment, with additional image-specific metadata.
 *
 * @remarks
 * You can identify this variant by checking for `subtype: "image"`.
 *
 * Includes metadata about the height and width of the image in pixels, where available.
 *
 * Images that you upload with the TalkJS UI will include the image dimensions as long as the sender's browser can preview the file.
 * Images that you upload with the REST API or {@link Session.uploadImage} will include the dimensions if you specified them when uploading.
 * Image attached in a reply to an email notification will not include the dimensions.
 *
 * @public
 */
export declare interface ImageBlock {
    readonly type: "file";
    readonly subtype: "image";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this image in another message.
     */
    readonly fileToken: FileToken;
    /**
     * The URL where you can fetch the file.
     */
    readonly url: string;
    /**
     * The size of the file in bytes.
     */
    readonly size: number;
    /**
     * The name of the image file, including file extension.
     */
    readonly filename: string;
    /**
     * The width of the image in pixels, if known.
     */
    readonly width?: number;
    /**
     * The height of the image in pixels, if known.
     */
    readonly height?: number;
}

export declare interface ImageFileMetadata {
    /**
     * The name of the file including extension.
     */
    filename: string;
    /**
     * The width of the image in pixels, if known.
     */
    width?: number;
    /**
     * The height of the image in pixels, if known.
     */
    height?: number;
}

/**
 * A node in a {@link TextBlock} that renders its children as a clickable link (HTML `<a>`).
 *
 * @remarks
 * By default, users do not have permission to send messages containing `LinkNode` as it can be used to maliciously hide the true destination of a link.
 *
 * @public
 */
export declare interface LinkNode {
    readonly type: "link";
    /**
     * The URL to open when the node is clicked.
     */
    readonly url: string;
    readonly children: TextNode[];
}

/**
 * A block showing a location in the world, typically because a user shared their location in the chat.
 *
 * @remarks
 * In the TalkJS UI, location blocks are rendered as a link to Google Maps, with the map pin showing at the specified coordinate.
 * A thumbnail shows the surrounding area on the map.
 *
 * @public
 */
export declare interface LocationBlock {
    readonly type: "location";
    /**
     * The north-south coordinate of the location.
     *
     * @remarks
     * Usually listed first in a pair of coordinates.
     *
     * Must be a number between -90 and 90
     */
    readonly latitude: number;
    /**
     * The east-west coordinate of the location.
     *
     * @remarks
     * Usually listed second in a pair of coordinates.
     *
     * Must be a number between -180 and 180
     */
    readonly longitude: number;
}

/**
 * The {@link TypingSnapshot} variant used when many people are typing.
 */
export declare interface ManyTypingSnapshot {
    /**
     * Check this to differentiate between FewTypingSnapshot (`false`) and ManyTypingSnapshot (`true`).
     *
     * @remarks
     * When `true`, you do not receive a list of users who are typing.
     * You should show a message like "several people are typing" instead.
     */
    readonly many: true;
}

/**
 * A node in a {@link TextBlock} that renders its children with a specific style.
 *
 * @public
 */
export declare interface MarkupNode {
    /**
     * The kind of formatting to apply when rendering the children
     *
     * - `type: "bold"` is used when users type `*text*` and is rendered with HTML `<strong>`
     *
     * - `type: "italic"` is used when users type `_text_` and is rendered with HTML `<em>`
     *
     * - `type: "strikethrough"` is used when users type `~text~` and is rendered with HTML `<s>`
     */
    readonly type: "bold" | "italic" | "strikethrough";
    readonly children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that is used when a user is {@link https://talkjs.com/docs/Features/Messages/Mentions/ | mentioned}.
 *
 * @remarks
 * Used when a user types `@name` and selects the user they want to mention.
 *
 * @public
 */
export declare interface MentionNode {
    readonly type: "mention";
    /**
     * The ID of the user who is mentioned.
     */
    readonly id: string;
    /**
     * The name of the user who is mentioned.
     */
    readonly text: string;
}

/**
 * The state of a messages subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface MessageActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the messages, or `null` if you're not a participant in the conversation.
     */
    readonly latestSnapshot: MessageSnapshot[] | null;
    /**
     * True if `latestSnapshot` contains all messages in the conversation.
     * Use {@link MessageSubscription.loadMore} to load more.
     */
    readonly loadedAll: boolean;
}

/**
 * Not yet exposed, message filtering is not implemented
 * @hidden
 */
export declare type MessageFilter = SimpleMessageFilter | CompoundFilter<SimpleMessageFilter>;

/**
 * References the message with a given message ID.
 *
 * @remarks
 * Used in all Data API operations affecting that message, such as fetching or editing the message attributes, or deleting the message.
 * Created via {@link ConversationRef.message} and {@link ConversationRef.send}.
 *
 * @public
 */
export declare interface MessageRef {
    /**
     * The ID of the referenced message.
     *
     * @remarks
     * Immutable: if you want to reference a different message, get a new MessageRef instead.
     */
    readonly id: string;
    /**
     * The ID of the conversation that the referenced message belongs to.
     *
     * @remarks
     * Immutable: if you want to reference a message from a different conversation, get a new MessageRef from that conversation.
     */
    readonly conversationId: string;
    /**
     * Get a reference to a specific emoji reaction on this message
     *
     * @remarks
     * If you call `.reactions` with an invalid emoji, it will still succeed and you will still get a `ReactionRef`.
     * However, the TalkJS server will reject any calls that use an invalid emoji.
     *
     * Calling this method multiple times with the same emoji reuses the same {@link ReactionsRef} object.
     *
     * @example Reacting to the message with a Unicode emoji
     * ```ts
     * MessageRef.reactions("🚀").add()
     * ```
     *
     * @example Removing your custom emoji reaction from the message
     * ```ts
     * MessageRef.reactions(":cat-roomba:").remove()
     * ```
     *
     * @example Subscribing to the list of users who reacted with a specific emoji
     * ```ts
     * MessageRef.reactions("🚀").subscribe(snapshots => console.log(snapshots))
     * ```
     *
     * @param emoji - The emoji for the reaction you want to reference. a single Unicode emoji like "🚀" or a custom emoji like ":cat_roomba:". Custom emoji can be up to 50 characters long.
     * @returns A {@link ReactionsRef} for the reactions with that emoji on this message
     * @throws If the emoji is not a string or is an empty string
     * @public
     */
    reactions(emoji: string): ReactionsRef;
    /**
     * Get a reference to a specific emoji reaction on this message
     *
     * @deprecated This has been renamed to {@link MessageRef.reactions}. For back-compat, this method will continue to be available as an alias.
     */
    reaction(emoji: string): ReactionsRef;
    /**
     * Fetches a snapshot of the message.
     *
     * @returns A snapshot of the message's attributes, or null if the message doesn't exist, the conversation doesn't exist, or you're not a participant in the conversation.
     */
    get(): Promise<MessageSnapshot | null>;
    /**
     * Edits this message.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if the request is invalid, the message doesn't exist, or you do not have permission to edit that message.
     */
    edit(params: string | EditTextMessageParams | EditMessageParams): Promise<void>;
    /**
     * Deletes this message, or does nothing if the message does not exist.
     *
     * @remarks
     * Deleting a nonexistent message is treated as success, and the promise will resolve.
     *
     * @returns A promise that resolves when the operation completes. This promise will reject if you are not a participant in the conversation or if your role does not give you permission to delete this message.
     */
    delete(): Promise<void>;
}

/**
 * Search object returned by `TalkSession.searchMessages`.
 * Used to search for messages in the current user's conversations.
 *
 * @public
 */
export declare interface MessageSearch {
    /**
     * Sets the query string for this search and starts searching for messages matching the query.
     *
     * @remarks
     * This resets the search to its initial state, clearing all previous results.
     * Initially loads 3 results. Call {@link MessageSearch.loadMore} to load additional results.
     *
     * The query matches a message when, for each word in the query, that word appears in the message text.
     * This means one of the words in the string starts with the word from the query.
     * This is case-insensitive and punctuation at the start / end of words is ignored (in both the string and the query).
     *
     * Non-text messages (such as uploaded images) are never returned by search.
     *
     * A message saying `I like to look at rainbows`, will appear in searches for `rainbows`, `rain`, `look at`, `(look, i *LIKE* rain)`, and `look look look!`.
     * It will not appear in searches for `bows`, `rain-bows`, `look-at`, or `I like to look at rainbows too`.
     *
     * You can optionally pass `filters.conversation` to restrict results to messages in conversations that match a {@link ConversationFilter}.
     * Pass the same filter you use for a conversation list to keep search within that feed's scope. Omit it to search across all of the current user's conversations.
     *
     * @param query - The string to search for.
     * @param filters - Optional {@link MessageSearchFilters}, e.g. `{ conversation }` to restrict results to messages in conversations matching a {@link ConversationFilter}.
     * @returns A promise that resolves with the complete first page of results. The promise rejects if the search encounters an error.
     */
    setQuery(query: string, filters?: MessageSearchFilters): Promise<MessageSearchState>;
    /**
     * Continues searching for more messages.
     *
     * @remarks
     * You can only call `loadMore` when the search has a query set, and is idle.
     * Calling `loadMore` before calling `setQuery`, while the `setQuery` promise is still pending, or while another `loadMore` promise is pending, has no effect.
     *
     * @param limit - The number of results to load. `limit` should be between 1 and 50. Default 10.
     * @returns A promise that resolves once finished loading, containing all the results from this page and all previous pages. The promise rejects if the search encounters an error.
     */
    loadMore(limit?: number): Promise<MessageSearchState>;
}

/**
 * Filters for a message search, passed to {@link MessageSearch.setQuery}.
 *
 * @public
 */
export declare interface MessageSearchFilters {
    /**
     * Only return messages in conversations that match this
     * {@link ConversationFilter}.
     *
     * Pass the same filter you use for a conversation list to keep search within
     * that feed's scope.
     */
    conversation?: ConversationFilter;
}

/**
 * The state of a message search in the current step.
 *
 * @public
 */
export declare interface MessageSearchState {
    /**
     * Contains all messages found by the search. Each message is paired up with the conversation it is from.
     */
    results: SearchMessageSnapshot[];
    /**
     * Whether all results have been loaded.
     *
     * @remarks
     * Note: When true, this means that the search has reached the oldest matching message and no more messages can be loaded.
     * However, it does not mean that `results` contains every matching message.
     * Any messages sent after you called `setQuery` will be missing from `results`.
     */
    loadedAll: boolean;
}

/**
 * A snapshot of a message's attributes at a given moment in time.
 *
 * @remarks
 * Automatically expanded to include a snapshot of the user that sent the message, and a snapshot of the referenced message, if this message is a reply.
 *
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface MessageSnapshot {
    /**
     * The unique ID that is used to identify the message in TalkJS
     */
    readonly id: string;
    /**
     * Whether this message was "from a user" or a general system message without a specific sender.
     *
     * The `sender` property is always present for "UserMessage" messages and never present for "SystemMessage" messages.
     */
    readonly type: "UserMessage" | "SystemMessage";
    /**
     * A snapshot of the user who sent the message, or null if it is a system message.
     * The user's attributes may have been updated since they sent the message, in which case this snapshot contains the updated data.
     * It is not a historical snapshot.
     */
    readonly sender: UserSnapshot | null;
    /**
     * Custom metadata you have set on the message
     */
    readonly custom: Record<string, string>;
    /**
     * Time at which the message was sent, as a unix timestamp in milliseconds
     */
    readonly createdAt: number;
    /**
     * Time at which the message was last edited, as a unix timestamp in milliseconds.
     * `null` if the message has never been edited.
     */
    readonly editedAt: number | null;
    /**
     * A snapshot of the message that this message is a reply to, or null if this message is not a reply.
     *
     * @remarks
     * Only UserMessages can reference other messages.
     * The referenced message snapshot does not have a `referencedMessage` field.
     * Instead, it has `referencedMessageId`.
     * This prevents TalkJS fetching an unlimited number of messages in a long chain of replies.
     */
    readonly referencedMessage: ReferencedMessageSnapshot | null;
    /**
     * Specifies how this message was created.
     *
     * - "rest" = Message sent normally, via one of the UI components, the Data API, or the REST API
     *
     * - "import" = Message sent via the admin REST API's "import messages" endpoint
     *
     * - "email" = Message sent as a reply to an email notification
     *
     * - "web" = Message sent using a classic SDK
     *
     * To track more detailed information about where a message comes from, such as browser vs mobile app, use message custom data.
     *
     * The "rest" and "web" values are confusingly named. This is for historical reasons and to maintain backwards compatibility.
     */
    readonly origin: "rest" | "import" | "email" | "web";
    /**
     * The contents of the message, as a plain text string without any formatting or attachments.
     * Useful for showing in a conversation list or in notifications.
     */
    readonly plaintext: string;
    /**
     * The main body of the message, as a list of blocks that are rendered top-to-bottom.
     */
    readonly content: ContentBlock[];
    /**
     * A summary of the emoji reactions that have been added to this message.
     *
     * @remarks
     * Each message can have up to 50 unique emoji used for reactions.
     * They are sorted in the order they were first added to the message, starting with the oldest.
     */
    readonly reactions: ReactionsSummarySnapshot[];
}

/**
 * A subscription to the messages in a specific conversation.
 *
 * @remarks
 * Get a MessageSubscription by calling {@link ConversationRef.subscribeMessages}
 *
 * The subscription is 'windowed'. It includes all messages since a certain point in time.
 * By default, you subscribe to the 30 most recent messages, and any new messages that are sent after you subscribe.
 *
 * You can expand this window by calling {@link MessageSubscription.loadMore}, which extends the window further into the past.
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface MessageSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot` and `loadedAll`.
     *
     * - `latestSnapshot: MessageSnapshot[] | null` the current state of the messages in the window, or null if you're not a participant in the conversation
     *
     * - `loadedAll: boolean` true when `latestSnapshot` contains all the messages in the conversation
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | MessageActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<MessageActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older messages
     *
     * @remarks
     * The `count` parameter is relative to the current number of loaded messages.
     * If you call `loadMore(5)` and then call `loadMore(10)` immediately afterwards (without awaiting the promise),
     * then only 10 additional messages will be loaded, not 15.
     *
     * Avoid calling `.loadMore` in a loop until you have loaded all messages.
     * If you do need to call loadMore in a loop, make sure you set an upper bound (e.g. 1000) on the number of messages, where the loop will exit.
     *
     * @param count - The number of additional messages to load. Must be between 1 and 100. Default 30.
     * @returns A promise that resolves once the additional messages have loaded
     */
    loadMore(count?: number): Promise<void>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * @public
 * A two-element array that forms a predicate about a numeric field.
 *
 * @remarks
 * Used in {@link ConversationPredicate}.
 * Possible forms:
 *
 * - `[">", someNumber]`
 *
 * - `["<", someNumber]`
 *
 * - `[">=", someNumber]`
 *
 * - `["<=", someNumber]`
 *
 * - `["between", [lowerBound, upperBound]]`
 *
 * - `["!between", [lowerBound, upperBound]]`
 *
 * The lower bound is inclusive, the upper bound is exclusive.
 */
export declare type NumberFilter = [">" | "<" | ">=" | "<=", number] | ["between" | "!between", [number, number]];

/**
 * The state of a participants subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ParticipantActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the participants, or `null` if you are not a participant in that conversation.
     */
    readonly latestSnapshot: ParticipantSnapshot[] | null;
    /**
     * True if `latestSnapshot` contains all participants in the conversation.
     * Use {@link ParticipantSubscription.loadMore} to load more.
     */
    readonly loadedAll: boolean;
}

/**
 * References a given user's participation in a conversation.
 *
 * @remarks
 * Used in all Data API operations affecting that participant, such as joining/leaving a conversation, or setting their access.
 * Created via {@link ConversationRef.participant}.
 *
 * @public
 */
export declare interface ParticipantRef {
    /**
     * The ID of the user who is participating.
     *
     * @remarks
     * Immutable: if you want to reference a different participant, get a new ParticipantRef instead.
     */
    readonly userId: string;
    /**
     * The ID of the conversation the user is participating in.
     *
     * @remarks
     * Immutable: if you want to reference the user in a different conversation, get a new ParticipantRef instead.
     */
    readonly conversationId: string;
    /**
     * Fetches a snapshot of the participant.
     *
     * @remarks
     * This contains all of the participant's public information.
     *
     * @returns A snapshot of the participant's attributes, or null if the user is not a participant. The promise will reject if you are not a participant and try to read information about someone else.
     */
    get(): Promise<ParticipantSnapshot | null>;
    /**
     * Sets properties of this participant. If the user is not already a participant in the conversation, they will be added.
     *
     * @returns A promise that resolves when the operation completes.
     * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
     * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
     */
    set(params: SetParticipantParams): Promise<void>;
    /**
     * Edits properties of a pre-existing participant. If the user is not already a participant in the conversation, the promise will reject.
     *
     * @returns A promise that resolves when the operation completes.
     * When client-side conversation syncing is disabled, you must already be a participant and you cannot set anything except the `notify` property.
     * Everything else requires client-side conversation syncing to be enabled, and will cause the promise to reject.
     */
    edit(params: SetParticipantParams): Promise<void>;
    /**
     * Adds the user as a participant, or does nothing if they are already a participant.
     *
     * @remarks
     * If the participant already exists, this operation is still considered successful and the promise will still resolve.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if client-side conversation syncing is disabled and the user is not already a participant.
     */
    createIfNotExists(params?: CreateParticipantParams): Promise<void>;
    /**
     * Removes the user as a participant, or does nothing if they are already not a participant.
     *
     * @remarks
     * Deleting a nonexistent participant is treated as success, and the promise will resolve.
     *
     * @returns A promise that resolves when the operation completes. This promise will reject if client-side conversation syncing is disabled.
     */
    delete(): Promise<void>;
    /**
     * Subscribe to this participant's state.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called when the participant joins or leaves the conversation, or their attributes change, including attributes on their user.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     *
     * @returns A subscription to the participant
     */
    subscribe(onSnapshot?: (snapshot: ParticipantSnapshot | null) => void): SingleParticipantSubscription;
}

/**
 * A snapshot of a participant's attributes at a given moment in time.
 *
 * @remarks
 * Automatically expanded to include a snapshot of the user who is a participant.
 *
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface ParticipantSnapshot {
    /**
     * The user who this participant snapshot is referring to
     */
    readonly user: UserSnapshot;
    /**
     * The level of access this participant has in the conversation.
     */
    readonly access: "ReadWrite" | "Read";
    /**
     * When the participant will be notified about new messages in this conversation.
     *
     * @remarks
     * `false` means no notifications, `true` means notifications for all messages, and `"MentionsOnly"` means that the user will only be notified when they are mentioned with an `@`.
     */
    readonly notify: boolean | "MentionsOnly";
    /**
     * The date that this user joined the conversation, as a unix timestamp in milliseconds.
     */
    readonly joinedAt: number;
}

/**
 * A subscription to the participants in a specific conversation.
 *
 * @remarks
 * Get a ParticipantSubscription by calling {@link ConversationRef.subscribeParticipants}
 *
 * The subscription is 'windowed'. It includes everyone who joined since a certain point in time.
 * By default, you subscribe to the 10 most recent participants, and any participants who joined after you subscribe.
 *
 * You can expand this window by calling {@link ParticipantSubscription.loadMore}, which extends the window further into the past.
 * Do not call `.loadMore` in a loop until you have loaded all participants, unless you know that the maximum number of participants is small (under 100).
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface ParticipantSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot` and `loadedAll`.
     *
     * - `latestSnapshot: ParticipantSnapshot[] | null` the current state of the participants in the window, or null if you're not a participant in the conversation
     *
     * - `loadedAll: boolean` true when `latestSnapshot` contains all the participants in the conversation
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | ParticipantActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<ParticipantActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older participants
     *
     * @remarks
     * The `count` parameter is relative to the current number of loaded participants.
     * If you call `loadMore(5)` and then call `loadMore(10)` immediately afterwards (without awaiting the promise),
     * then only 10 additional participants will be loaded, not 15.
     *
     * Avoid calling `.loadMore` in a loop until you have loaded all participants.
     * If you do need to call loadMore in a loop, make sure you set a small upper bound (e.g. 100) on the number of participants, where the loop will exit.
     *
     * @param count - The number of additional participants to load. Must be between 1 and 50. Default 10.
     * @returns A promise that resolves once the additional participants have loaded
     */
    loadMore(count?: number): Promise<void>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * The state of a subscription before it has connected to the server
 *
 * @public
 */
export declare interface PendingState {
    readonly type: "pending";
}

/**
 * References all the reactions on a message using a specific emoji.
 *
 * @deprecated This has been renamed to {@link ReactionsRef}. For back-compat, this will continue to be available as an alias.
 *
 * @public
 */
export declare type ReactionRef = ReactionsRef;

/**
 * The state of a user reaction list subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ReactionsActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the participants, or `null` if you are not a participant in that conversation.
     */
    readonly latestSnapshot: SingleReactionSnapshot[] | null;
    /**
     * True if `latestSnapshot` contains all users who used this reaction.
     * Use {@link ReactionsSubscription.loadMore} to load more.
     */
    readonly loadedAll: boolean;
}

/**
 * A summary of the reactions to a message using a specific emoji.
 *
 * @deprecated This has been renamed to {@link ReactionsSummarySnapshot}. For back-compat, this will continue to be available as an alias.
 *
 * @public
 */
export declare type ReactionSnapshot = ReactionsSummarySnapshot;

/**
 * References all the reactions on a message using a specific emoji.
 *
 * @remarks
 * Used in all Data API operations affecting reactions with this emoji.
 * This includes mutating *your* reaction with `.add` and `.remove`, as well as fetching information about the aggregate state using `getFirstReactions` and `.subscribe`.
 * Created via {@link MessageRef.reactions}.
 *
 * @public
 */
export declare interface ReactionsRef {
    /**
     * Which emoji the reactions use.
     *
     * @remarks
     * Either a single Unicode emoji, or the name of a custom emoji with a colon at the start and end.
     * This is not validated until you send a request to the server.
     * Since custom emoji are configured in the frontend, there are no checks to make sure a custom emoji actually exists.
     *
     * Immutable: if you want to use a different emoji, get a new ReactionRef instead.
     *
     * @example Unicode emoji
     * "👍"
     *
     * @example Custom emoji
     * ":cat-roomba:"
     */
    readonly emoji: string;
    /**
     * The ID of the message that this is a reaction to.
     *
     * @remarks
     * Immutable: if you want reactions for a different message, get a new ReactionRef instead.
     */
    readonly messageId: string;
    /**
     * The ID of the conversation the message belongs to.
     *
     * @remarks
     * Immutable: if you want reactions for a message in a different conversation, get a new MessageRef from that conversation and call `.reactions` on that MessageRef.
     */
    readonly conversationId: string;
    /**
     * React with this emoji reaction, as the current user.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if the request is invalid, the message doesn't exist, there are already 50 different reactions on this message, or if you do not have permission to use emoji reactions on that message. The promise will resolve with no effect if you have already reacted with this emoji.
     */
    add(): Promise<void>;
    /**
     * Un-react with this emoji reaction, as the current user.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if the request is invalid, the message doesn't exist, or you do not have permission to use emoji reactions on that message. The promise will resolve with no effect if you have not reacted with this emoji.
     */
    remove(): Promise<void>;
    /**
     * Lists the first 10 users who added this reaction to the message.
     *
     * @remarks
     * If more than 10 users added this reaction to the message, only the first 10 users will be returned.
     *
     * To load more than 10 users, and to get real-time updates when users add or remove reactions, use {@link subscribe} instead.
     *
     * @returns The first 10 users, or `null` if the message doesn't exist or is inaccessible to you.
     */
    getFirstReactions(): Promise<SingleReactionSnapshot[] | null>;
    /**
     * Subscribe to the list of users who have added this reaction to the message
     */
    subscribe(onSnapshot?: (snapshot: SingleReactionSnapshot[] | null, loadedAll: boolean) => void): ReactionsSubscription;
}

/**
 * A subscription to the users who have reacted with a specific emoji on a specific message.
 *
 * @remarks
 * Get a ReactionsSubscription by calling {@link ReactionsRef.subscribe}
 *
 * The subscription is 'windowed'. It includes all reactions up to a certain point in time.
 * By default, you subscribe to the 10 oldest reactions.
 *
 * You can expand this window to load newer reactions by calling {@link ReactionsSubscription.loadMore}, which extends the window further into the future.
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface ReactionsSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot` and `loadedAll`.
     *
     * - `latestSnapshot: SingleReactionSnapshot[] | null` the current state of who used this reaction, or null if the message does not exist, or if you're not a participant in the conversation
     *
     * - `loadedAll: boolean` true when `latestSnapshot` contains all the users who added this reaction to the message
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | ReactionsActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<ReactionsActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include people who added the reaction later
     *
     * @remarks
     * The `count` parameter is relative to the current number of loaded users.
     * If you call `loadMore(5)` and then call `loadMore(10)` immediately afterwards (without awaiting the promise),
     * then only 10 additional users will be loaded, not 15.
     *
     * Avoid calling `.loadMore` in a loop until you have loaded all users.
     * If you do need to call loadMore in a loop, make sure you set an upper bound (e.g. 1000) on the number of users, where the loop will exit.
     *
     * @param count - The number of additional users to load. Must be between 1 and 100. Default 30.
     * @returns A promise that resolves once the additional users have loaded
     */
    loadMore(count?: number): Promise<void>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * A summary of the reactions to a message using a specific emoji.
 *
 * @remarks
 * To see who reacted with a given emoji, or to add a reaction yourself, get a {@link ReactionsRef} using {@link MessageRef.reactions}.
 *
 * @public
 */
export declare interface ReactionsSummarySnapshot {
    /**
     * Which emoji the users reacted with.
     *
     * @remarks
     * Either a single Unicode emoji, or the name of a custom emoji with a colon at the start and end.
     * Since custom emoji are defined in the frontend, they are not validated by the TalkJS server.
     * The UI should ignore reactions that use unrecognised custom emoji.
     *
     * NOTE: In unicode, it is possible to have multiple emoji that look identical but are represented differently.
     * For example, `"👍" !== "👍️"` because the second emoji includes a {@link https://en.wikipedia.org/wiki/Variation_Selectors_(Unicode_block) | variation selector 16 codepoint}.
     * This codepoint forces the character to appear as an emoji.
     *
     * TalkJS normalises all emoji reactions to be "fully qualified" {@link https://unicode.org/Public/emoji/16.0/emoji-test.txt | according to this list}.
     * This prevents a message having multiple separate 👍 reactions.
     *
     * Be careful when processing the `emoji` property, as this normalisation might break equality checks:
     *
     * ```ts
     * // Emoji has unnecessary variation selector 16
     * const sent = "👍"
     *
     * // React with thumbs up,
     * await message.reactions(emoji).add()
     *
     * // Fetch the reaction
     * const snapshot = await message.get();
     * const received = snapshot.reactions[0].emoji;
     *
     * // Fails because TalkJS removed the variation selector
     * assert sent === received;
     * ```
     *
     * @example Unicode emoji
     * "👍"
     *
     * @example Custom emoji
     * ":cat-roomba:"
     */
    readonly emoji: string;
    /**
     * The number of times this emoji has been added to the message.
     */
    readonly count: number;
    /**
     * Whether the current user has reacted to the message with this emoji.
     */
    readonly currentUserReacted: boolean;
}

/**
 * A snapshot of a message's attributes at a given moment in time, used in {@link MessageSnapshot.referencedMessage}.
 *
 * @remarks
 * Automatically expanded to include a snapshot of the user that sent the message.
 * Since this is a snapshot of a referenced message, its referenced message is not automatically expanded, to prevent fetching an unlimited number of messages in a long chain of replies.
 * Instead, contains the `referencedMessageId` field.
 *
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface ReferencedMessageSnapshot {
    /**
     * The unique ID that is used to identify the message in TalkJS
     */
    readonly id: string;
    /**
     * Referenced messages are always "UserMessage" because you cannot reply to a system message.
     */
    readonly type: "UserMessage";
    /**
     * A snapshot of the user who sent the message.
     * The user's attributes may have been updated since they sent the message, in which case this snapshot contains the updated data.
     * It is not a historical snapshot.
     *
     * @remarks
     * Guaranteed to be set, unlike in MessageSnapshot, because you cannot reference a SystemMessage
     */
    readonly sender: UserSnapshot;
    /**
     * Custom metadata you have set on the message
     */
    readonly custom: Record<string, string>;
    /**
     * Time at which the message was sent, as a unix timestamp in milliseconds
     */
    readonly createdAt: number;
    /**
     * Time at which the message was last edited, as a unix timestamp in milliseconds.
     * `null` if the message has never been edited.
     */
    readonly editedAt: number | null;
    /**
     * The ID of the message that this message is a reply to, or null if this message is not a reply.
     *
     * @remarks
     * Since this is a snapshot of a referenced message, we do not automatically expand its referenced message.
     * The ID of its referenced message is provided here instead.
     */
    readonly referencedMessageId: string | null;
    /**
     * Specifies how this message was created.
     *
     * - "rest" = Message sent normally, via one of the UI components, the Data API, or the REST API
     *
     * - "import" = Message sent via the admin REST API's "import messages" endpoint
     *
     * - "email" = Message sent as a reply to an email notification
     *
     * - "web" = Message sent using a classic SDK
     *
     * To track more detailed information about where a message comes from, such as browser vs mobile app, use message custom data.
     *
     * The "rest" and "web" values are confusingly named. This is for historical reasons and to maintain backwards compatibility.
     */
    readonly origin: "rest" | "import" | "email" | "web";
    /**
     * The contents of the message, as a plain text string without any formatting or attachments.
     * Useful for showing in a conversation list or in notifications.
     */
    readonly plaintext: string;
    /**
     * The main body of the message, as a list of blocks that are rendered top-to-bottom.
     */
    readonly content: ContentBlock[];
    /**
     * All the emoji reactions that have been added to this message.
     */
    readonly reactions: ReactionsSummarySnapshot[];
}

export declare function registerPolyfills({ WebSocket }: {
    WebSocket: object;
}): void;

/**
 * A snapshot of search results in a given moment in time.
 * contains a message and the conversation it from.
 *
 * @public
 */
export declare interface SearchMessageSnapshot {
    /**
     * The conversation that the message was found in.
     */
    conversation: ConversationSnapshot;
    /**
     * The message that was found in the search.
     */
    message: MessageSnapshot;
}

/**
 * The version of {@link ContentBlock} that is used when sending or editing messages.
 *
 * @remarks
 * This is the same as {@link ContentBlock} except it uses {@link SendFileBlock} instead of {@link FileBlock}
 *
 * `SendContentBlock` is a subset of `ContentBlock`.
 * This means that you can re-send the `content` from an existing message without any issues:
 *
 * ```ts
 * const existingMessage: MessageSnapshot = ...;
 *
 * const convRef = session.conversation('example_conversation_id');
 * convRef.send({ content: existingMessage.content });
 * ```
 *
 * @public
 */
export declare type SendContentBlock = TextBlock | SendFileBlock | LocationBlock;

/**
 * The version of {@link FileBlock} that is used when sending or editing messages.
 *
 * @remarks
 * When a user receives the message you send with `SendFileBlock`, this block will have turned into one of the {@link FileBlock} variants.
 *
 * For information on how to obtain a file token, see {@link FileToken}.
 *
 * The `SendFileBlock` interface is a subset of the `FileBlock` interface.
 * If you have an existing `FileBlock` received in a message, you can re-use that block to re-send the same attachment:
 *
 * ```ts
 * const existingFileBlock = ...;
 * const imageToShare = existingFileBlock.content[0] as ImageBlock
 *
 * const convRef = session.conversation('example_conversation_id');
 * convRef.send({ content: [imageToShare] });
 * ```
 *
 * @public
 */
export declare interface SendFileBlock {
    type: "file";
    /**
     * The encoded identifier for the file, obtained by uploading a file with {@link Session.sendFile}, or taken from another message.
     */
    fileToken: FileToken;
}

/**
 * Parameters you can pass to {@link ConversationRef.send}.
 *
 * @remarks
 * Properties that are `undefined` will be set to the default.
 *
 * This is the more advanced method for editing a message, giving full control over the message content.
 * You can decide exactly how a text message should be formatted, edit an attachment, or even turn a text message into a location.
 *
 * @public
 */
export declare interface SendMessageParams {
    /**
     * Custom metadata to set on the message.
     * Default = no custom metadata
     */
    custom?: Record<string, string>;
    /**
     * The message that you are replying to.
     * Default = not a reply
     */
    referencedMessage?: string | MessageRef;
    /**
     * The most important part of the message, either some text, a file attachment, or a location.
     *
     * @remarks
     * By default users do not have permission to send {@link LinkNode}, {@link ActionLinkNode}, or {@link ActionButtonNode}, as they can be used to trick the recipient.
     *
     * Currently, each message can only contain a single {@link SendContentBlock}.
     */
    content: [SendContentBlock];
}

/**
 * Parameters you can pass to {@link ConversationRef.send}.
 *
 * @remarks
 * Properties that are `undefined` will be set to the default.
 *
 * This is a simpler version of {@link SendMessageParams} that only supports text messages.
 *
 * @public
 */
export declare interface SendTextMessageParams {
    /**
     * Custom metadata to set on the message.
     * Default = no custom metadata
     */
    custom?: Record<string, string>;
    /**
     * The message that you are replying to.
     * Default = not a reply
     */
    referencedMessage?: string | MessageRef;
    /**
     * The text to send in the message.
     *
     * @remarks
     * This is parsed the same way as the text entered in the message field. For example, `*hi*` will appear as `hi` in bold.
     *
     * See the {@link https://talkjs.com/docs/Features/Messages/Formatting/ | message formatting documentation} for more details.
     */
    text: string;
}

/**
 * Parameters you can pass to {@link ConversationRef.set}.
 *
 * Properties that are `undefined` will not be changed.
 * To clear / reset a property to the default, pass `null`.
 *
 * @public
 */
export declare interface SetConversationParams {
    /**
     * The conversation subject to display in the chat header.
     * Default = no subject, list participant names instead.
     */
    subject?: string | null;
    /**
     * The URL for the conversation photo to display in the chat header.
     * Default = no photo, show a placeholder image.
     */
    photoUrl?: string | null;
    /**
     * System messages which are sent at the beginning of a conversation.
     * Default = no messages.
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are not real messages.
     * This means they do not appear when you list messages using the REST API or JS Data API, and you cannot reply or react to them.
     */
    welcomeMessages?: string[] | null;
    /**
     * Custom metadata you have set on the conversation.
     * This value acts as a patch. Remove specific properties by setting them to `null`.
     * Default = no custom metadata
     */
    custom?: Record<string, string | null> | null;
    /**
     * Your access to the conversation.
     * Default = "ReadWrite" access.
     */
    access?: "Read" | "ReadWrite" | null;
    /**
     * Your notification settings.
     * Default = `true`
     */
    notify?: boolean | "MentionsOnly" | null;
}

/**
 * Parameters you can pass to {@link ParticipantRef.set} or {@link ParticipantRef.edit}.
 *
 * @remarks
 * Properties that are `undefined` will not be changed.
 * To clear / reset a property to the default, pass `null`.
 *
 * @public
 */
export declare interface SetParticipantParams {
    /**
     * The level of access the participant should have in the conversation.
     * Default = "ReadWrite" access.
     */
    access?: "ReadWrite" | "Read" | null;
    /**
     * When the participant should be notified about new messages in this conversation.
     * Default = true.
     *
     * @remarks
     * `false` means no notifications, `true` means notifications for all messages, and `"MentionsOnly"` means that the user will only be notified when they are mentioned with an `@`.
     */
    notify?: boolean | "MentionsOnly" | null;
}

/**
 * Parameters you can pass to {@link UserRef.set}.
 *
 * @remarks
 * Properties that are `undefined` will not be changed.
 * To clear / reset a property to the default, pass `null`.
 *
 * @public
 */
export declare interface SetUserParams {
    /**
     * The user's name which will be displayed on the TalkJS UI
     */
    name?: string;
    /**
     * Custom metadata you have set on the user.
     * This value acts as a patch. Remove specific properties by setting them to `null`.
     * Default = no custom metadata
     */
    custom?: Record<string, string | null> | null;
    /**
     * An {@link https://www.w3.org/International/articles/language-tags/ | IETF language tag}.
     * See the {@link https://talkjs.com/docs/Features/Language_Support/#localization | localization documentation}
     * Default = null, will use the locale set on the dashboard
     */
    locale?: string | null;
    /**
     * An optional URL to a photo which will be displayed as the user's avatar.
     * Default = no photo
     */
    photoUrl?: string | null;
    /**
     * TalkJS supports multiple sets of settings, called "roles". These allow you to change the behavior of TalkJS for different users.
     * You have full control over which user gets which configuration.
     * Default = the `default` role
     */
    role?: string | null;
    /**
     * The default message a person sees when starting a chat with this user.
     * Default = no welcome message
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are
     * not real messages. This means they do not appear when you list messages
     * using the REST API or JS Data API, and you cannot reply or react to them.
     *
     * Note: User welcome messages are only supported by the Classic SDKs, and in
     * the Components-based SDKs, this field is ignored. To show welcome messages
     * in the Components-based SDK, see
     * {@link https://talkjs.com/docs/Guides/React/Welcome_Messages/ | Welcome Messages}.
     *
     * @deprecated
     */
    welcomeMessage?: string | null;
    /**
     * A single email address or an array of email addresses associated with the user.
     * Default = no email addresses
     */
    email?: string | string[] | null;
    /**
     * A single phone number or an array of phone numbers associated with the user.
     * Default = no phone numbers
     */
    phone?: string | string[] | null;
    /**
     * An object of push registration tokens to use when notifying this user.
     *
     * Keys in the object have the format `'provider:token_id'`,
     * where `provider` is either `"fcm"` for Android (Firebase Cloud Messaging),
     * or `"apns"` for iOS (Apple Push Notification Service).
     *
     * The value for each key can either be `true` to register the device for push notifications, or `null` to unregister that device.
     *
     * Setting pushTokens to null unregisters all the previously registered devices.
     *
     * Default = no push tokens
     */
    pushTokens?: Record<string, true | null> | null;
}

/**
 * Allows you to filter conversations in a subscription, only showing those that match this filter.
 *
 * @remarks
 * Multiple conversation filters can be OR-ed together using {@link CompoundFilter}.
 *
 * @example Only include conversations with unread messages
 * ```ts
 * session.subscribeConversations(onSnapshot, {
 *   filter: { isUnread: true }
 * });
 * ```
 *
 * @public
 */
export declare interface SimpleConversationFilter {
    /**
     * Only select conversations that the current user as specific access to.
     *
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `"=="`, `"!="`, `"oneOf"`, and `"!oneOf"`.
     *
     * The operand must be either a string (one of `"ReadWrite"` or `"Read"`) or an array of strings (for the `oneOf` operators).
     *
     * @example Hide conversations that the user cannot send messages to
     * ```json
     * { access: ["!=", "ReadWrite"] }
     * ```
     */
    access?: StringFilter<"ReadWrite" | "Read">;
    /**
     * Only select conversations that have particular custom fields set to particular values.
     *
     * @remarks
     * Every key must correspond to a key in the custom conversation data that you set (by passing
     * `custom` to {@link ConversationBuilder.setAttributes}). It is not necessary for all
     * conversations to have these keys.
     *
     * Each value must be one of the following:
     *
     * A string, equal to `"exists"` or `"!exists"`
     *
     * A 2-element array of `[operator, operand]` structure.  The operand must be either a
     * string or an array of strings (for the `oneOf` operators). Valid operators are:
     * `"=="`, `"!="`, `"oneOf"`, and `"!oneOf"`.
     *
     * @example Only show messages that have no custom `category` set
     * ```json
     * { custom: { category: "!exists" } }
     * ```
     *
     * @example Only show messages of that have the custom category "shoes"
     * ```json
     * { custom: { category: ["==", "shoes"] } }
     * ```
     *
     * @example Only show messages that have a 'topic' of either "inquiry" or "reservation"
     * ```json
     * {
     *   custom: {
     *     topic: ["oneOf", ["inquiry", "reservation"]]
     *   }
     * }
     * ```
     *
     * @example Only show messages about shoes that are marked visible
     * ```json
     * {
     *   custom: {
     *     category: ["==", "shoes"],
     *     visibility: ["==", "visible"]
     *   }
     * }
     * ```
     */
    custom?: CustomFilter;
    /**
     * Set this field to only select conversations that have, or don't have any, unread messages.
     */
    isUnread?: boolean;
    /**
     * Only select conversations that have the subject set to particular values.
     *
     * @remarks
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `"=="`, `"!="`, `"oneOf"`, and `"!oneOf"`.
     *
     * The operand must be either a string or an array of strings (for the `oneOf` operators).
     *
     * @example Only show conversations with "Black leather boots" or "Hair Wax 5 Gallons" as the subject
     * ```json
     * { subject: ["oneOf", ["Black leather boots", "Hair Wax 5 Gallons"]] }
     * ```
     */
    subject?: StringFilter<string | null>;
    /**
     * Only select conversations that have the last message sent in a particular time interval.
     *
     * @remarks
     * If the conversation has no messages, this falls back to using `joinedAt` instead.
     * This matches the default sort order for conversations in a conversation list.
     *
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `">"`, `"<"`, `">="`, `"<="`, `"between"`, and `"!between"`.
     *
     * The operand must be either a number or a 2-element array of numbers (for the `between` operators).
     *
     * @example Only show conversations that had messages sent after the UNIX timestamp 1679298371586
     * ```json
     * { lastActivityAt: [">", 1679298371586] }
     * ```
     */
    lastActivityAt?: NumberFilter;
    /**
     * Only select conversations that have been created in a particular time interval.
     *
     * @remarks
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `">"`, `"<"`, `">="`, `"<="`, `"between"`, and `"!between"`.
     *
     * The operand must be either a number or a 2-element array of numbers (for the `between` operators).
     *
     * @example Only show conversations that were created after the UNIX timestamp 1679298371586
     * ```json
     * { createdAt: [">", 1679298371586] }
     * ```
     */
    createdAt?: NumberFilter;
    /**
     * Only select conversations that have, or do not have messages.
     *
     * @example Only show conversations that have at least one message
     * ```json
     * { hasMessages: true }
     * ```
     *
     * @example Only show empty conversations
     * ```json
     * { hasMessages: false }
     * ```
     */
    hasMessages?: boolean;
    /**
     * Only select conversations that the current user joined in a particular time interval.
     *
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `">"`, `"<"`, `">="`, `"<="`, `"between"`, and `"!between"`.
     *
     * The operand must be either a number or a 2-element array of numbers (for the `between` operators).
     *
     * @example Only show conversations joined after the UNIX timestamp 1679298371586
     * ```json
     * { joinedAt: [">", 1679298371586] }
     * ```
     */
    joinedAt?: NumberFilter;
}

/**
 * Not yet exposed, message filtering is not implemented
 * @hidden
 */
export declare interface SimpleMessageFilter {
    /**
     * Only show messages if the sender's user ID matches this filter
     *
     * @remarks
     * System messages (which have no sender) will ignore this filter.
     * To exclude system messages, use the `type` filter instead.
     *
     * @example Only show messages sent by users with the user ID "user_123"
     * ```json
     * { sender: ["==", "user_123"] }
     * ```
     */
    sender?: StringFilter;
    /**
     * Only show messages of a given type (system message or user message)
     *
     * @example Only show system messages
     * ```json
     * { type: ["==", "SystemMessage"] }
     * ```
     *
     */
    type?: StringFilter<"UserMessage" | "SystemMessage">;
    /**
     * Only show messages that were created in a certain way.
     * See {@link Message.origin} for a list of possible origin values.
     *
     * @example Don't show messages that were sent as replies to email notifications
     * ```json
     * { origin: ["!=", "email"] }
     * ```
     */
    origin?: StringFilter<"rest" | "import" | "email" | "web">;
    /**
     * Only select messages that have particular custom fields set to particular values.
     *
     * @remarks
     * Every key must correspond to a key in the custom message data that you have set. It is not necessary for all
     * messages to have these keys.
     *
     * Each value must be one of the following:
     *
     * A string, equal to `"exists"` or `"!exists"`
     *
     * A 2-element array of `[operator, operand]` structure.  The operand must be either a
     * string or an array of strings (for the `oneOf` operators). Valid operators are:
     * `"=="`, `"!="`, `"oneOf"`, and `"!oneOf"`.
     *
     * @example Only show messages that have no custom `category` set
     * ```json
     * { custom: { category: "!exists" } }
     * ```
     *
     * @example Only show messages of that have the custom category "shoes"
     * ```json
     * {
     *   custom: {
     *     category: ["==", "shoes"]
     *   }
     * }
     * ```
     *
     * @example Only show messages that have a 'topic' of either "inquiry" or "reservation"
     * ```json
     * {
     *   custom: {
     *     topic: ["oneOf", ["inquiry", "reservation"]]
     *   }
     * }
     * ```
     *
     * @example Only show messages about shoes that are marked visible
     * ```json
     * {
     *   custom: {
     *     category: ["==", "shoes"],
     *     visibility: ["==", "visible"
     *   }
     * }
     * ```
     */
    custom?: CustomFilter;
    /**
     * Only select messages that have been sent in a particular time interval.
     *
     * Must be an 2-element array of `[operator, operand]` structure. Valid operators are:
     * `">"`, `"<"`, `">="`, `"<="`, `"between"`, and `"!between"`.
     *
     * The operand must be either a number or a 2-element array of numbers (for the `between` operators).
     *
     * @example Only show messages sent after the UNIX timestamp 1679298371586
     * ```json
     * { createdAt: [">", 1679298371586] }}
     * ```
     */
    createdAt?: NumberFilter;
}

/**
 * The state of a participant subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface SingleParticipantActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the participant, or `null` if they are not a participant in that conversation.
     */
    readonly latestSnapshot: ParticipantSnapshot | null;
}

/**
 * A subscription to a specific participant.
 *
 * @remarks
 * Get a SingleParticipantSubscription by calling {@link ParticipantRef.subscribe}
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface SingleParticipantSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot: ParticipantSnapshot | null`, the current state of the participant.
     * `latestSnapshot` is `null` when the user is not a participant or the conversation does not exist.
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | SingleParticipantActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     */
    readonly connected: Promise<SingleParticipantActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * A snapshot of a user's reaction to a message.
 *
 * @remarks
 * Returned from {@link ReactionsRef.getFirstReactions} and {@link ReactionsRef.subscribe}
 *
 * @public
 */
export declare interface SingleReactionSnapshot {
    /**
     * Which user added the reaction
     */
    readonly user: UserSnapshot;
    /**
     * The timestamp of when the user added this reaction to the message
     */
    readonly createdAt: number;
}

/**
 * @public
 * A two-element array that forms a predicate about a field.
 *
 * @remarks
 * Used in {@link MessagePredicate} and {@link ConversationPredicate}.
 * Possible forms:
 *
 * - `["==", "someValue"]`
 *
 * - `["!=", "someValue"]`
 *
 * - `["oneOf", ["someValue", "someOtherValue"]]`
 *
 * - `["!oneOf", ["someValue", "someOtherValue"]]`
 */
export declare type StringFilter<T = string> = ["==" | "!=", T] | ["oneOf" | "!oneOf", T[]];

export declare type Subscription = {
    unsubscribe: () => void;
};

export declare interface TalkSession {
    /** The unique TalkJS ID that you passed when calling `getTalkSession` */
    readonly appId: string;
    /**
     * A reference to the user this session is connected as
     *
     * @remarks
     * This is immutable. If you want to connect as a different user,
     * call `getTalkSession` again to get a new session.
     *
     * Equivalent to calling `Session.user` with the current user's ID.
     *
     * @see {@link Session.user} which lets you get a reference to any user.
     */
    readonly currentUser: UserRef;
    /**
     * Set the auth token to be used on this session.
     *
     * @remarks
     * This will immediately reauthenticate the websocket connection to TalkJS,
     * overwriting any previous tokens on the session.
     *
     * This does not affect any in-progress requests. As long as the new auth token is valid,
     * your subscriptions will stay active with no gaps or missing data during reauthentication.
     *
     * Note: When you call `getTalkSession` multiple times with the same arguments, the same TalkSession object is reused.
     * This means that when you call setToken in one place, it will set the auth token on
     * all sessions with the same appId and userId as this one.
     */
    setToken(token: string): void;
    /**
     * This property stores the function that is called when a new authentication token is needed.
     *
     * @remarks
     * The `onNeedToken` callback will run any time this session needs a new token.
     * This includes the first time you request data (if you have not called `setToken`), and whenever the auth token is about to expire.
     *
     * If you call `setToken` and leave this callback undefined, token expiry will trigger a critical error and the session will terminate.
     *
     * The callback should fetch a new JWT from your backend and then call {@link setToken} with it.
     * Ensure that the callback retries automatically when experiencing temporary issues such as network problems.
     *
     * If you called `getTalkSession` multiple times with the same arguments,
     * this will affect all sessions using the same appId + userId as this one.
     */
    onNeedToken?: () => void;
    /**
     * Subscribe to unrecoverable errors on the session.
     *
     * @remarks
     * For example, the handler will be called if your authentication token
     * expires and can't be refreshed, or if you try to connect with an invalid app ID.
     *
     * The handler will only be called at most once.
     *
     * Returns a subscription with a `.unsubscribe` method.
     * Call this unsubscribe method when you no longer need to be notified about errors on the session.
     */
    onError(handler: (error: Error) => void): Subscription;
    /**
     * Get a reference to a user
     *
     * @remarks
     * This is the entry-point for all operations that affect a user globally, such as editing their name.
     *
     * Calling this method multiple times with the same ID reuses the same {@link UserRef} object.
     *
     * For operations related to a user's participation in a conversation, do: `session.conversation(<convId>).participant(<userId>)`
     *
     * @see {@link Session.currentUser} which is a short-hand for `session.user(meId)`.
     *
     * @example Initialising a user
     * ```
     * const userRef = session.user("test");
     * userRef.createIfNotExists({ name: "Alice" });
     * ```
     *
     * @example Subscribing to changes
     * ```
     * const userRef = session.user("test");
     * const sub = userRef.subscribe(snapshot => console.log(snapshot));
     * await sub.connected;
     *
     * // Changing the user's name emits a snapshot and triggers the `console.log`
     * await userRef.set({ name: "Bob" });
     *
     * @param id - The ID of the user that you want to reference
     * @returns A {@link UserRef} for the user with that ID
     * @throws If the id is not a string or is an empty string
     * @public
     */
    user(id: string): UserRef;
    /**
     * Get a reference to a conversation
     *
     * @remarks
     * This is the entry-point for all conversation-related operations.
     * This includes operations affecting conversation attributes, but also anything related to messages and participants.
     *
     * Calling this method multiple times with the same ID reuses the same {@link ConversationRef} object.
     *
     * @example Ensure that the conversation exists and you are a participant
     * ```
     * session.conversation("test").createIfNotExists();
     * ```
     *
     * @example Set the conversation's subject
     * ```
     * session.conversation("test").set({ subject: "Power tools" });
     * ```
     *
     * @example Stop receiving notifications for this conversation
     * ```
     * session.conversation("test").set({ notify: false });
     * ```
     *
     * @example Send a message
     * ```
     * session.conversation("test").send("Hello");
     * ```
     *
     * @param id - The ID of the conversation that you want to reference
     * @returns A {@link ConversationRef} for the conversation with that ID
     * @throws If the id is not a string or is an empty string
     * @public
     */
    conversation(id: string): ConversationRef;
    /**
     * Subscribes to your most recently active conversations.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called whenever the conversation snapshots change.
     * This includes when you join or leave a conversation, when the conversation attributes change, and when you load more conversations.
     * It also includes when nested data changes, such as when `snapshot[0].lastMessage.referencedMessage.sender.name` changes.
     * Be careful when doing heavy computation inside `onSnapshot`, and consider caching the result. `onSnapshot` is called extremely often.
     * `loadedAll` is true when `snapshot` contains all your conversations, and false if you could load more.
     *
     * The `snapshot` list is ordered chronologically with the most recently active conversations at the start.
     * The last activity of a conversation is either when the last message was sent or when you joined, whichever is later.
     * In other words, it's the max of `lastMessage.createdAt` and `joinedAt`.
     * If you join a new conversation, or you receive a message in a conversation, that conversation will appear at the start of the list.
     *
     * The snapshot is an empty list if the current user does not exist yet.
     *
     * Initially, you will be subscribed to the 20 most recently active conversations and any conversations that have activity after you subscribe.
     * Call `loadMore` to load additional older conversations. This will trigger `onSnapshot`.
     *
     * You can provide `options` as the first argument.
     * If you provide `options` with a `filter`, only conversations matching the filter will be included in the snapshot.
     * See {@link ConversationFilter} for more details on what filter options are supported.
     *
     * Tip: `ConversationSnapshot` has a `lastMessage` property. Whenever you are sent a message, that message will be at `snapshot[0].lastMessage`.
     * If you just want to react to newly received messages, you can use this instead of calling `ConversationRef.subscribeMessages`.
     * This is much easier and more efficient.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     *
     * @example Subscribe to all your conversations and log them
     * ```ts
     * session.subscribeConversations(snapshots => console.log(snapshots));
     * ```
     *
     * @example Subscribe to conversations with a custom field
     * ```ts
     * session.subscribeConversations({
     *   filter: { custom: { category: ["==", "support"] } }
     * }, onSnapshot);
     * ```
     *
     * @example Subscribe to conversations with recent activity (last 7 days)
     * ```ts
     * const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
     * session.subscribeConversations({
     *   filter: { lastActivityAt: [">", sevenDaysAgo] }
     * }, onSnapshot);
     * ```
     */
    subscribeConversations(onSnapshot?: (snapshot: ConversationSnapshot[], loadedAll: boolean) => void): ConversationListSubscription;
    /**
     * Subscribes to your most recently active conversations, using the specified options.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called whenever the conversation snapshots change.
     * This includes when you join or leave a conversation, when the conversation attributes change, and when you load more conversations.
     * It also includes when nested data changes, such as when `snapshot[0].lastMessage.referencedMessage.sender.name` changes.
     * Be careful when doing heavy computation inside `onSnapshot`, and consider caching the result. `onSnapshot` is called extremely often.
     * `loadedAll` is true when `snapshot` contains all your conversations, and false if you could load more.
     *
     * The `snapshot` list is ordered chronologically with the most recently active conversations at the start.
     * The last activity of a conversation is either when the last message was sent or when you joined, whichever is later.
     * In other words, it's the max of `lastMessage.createdAt` and `joinedAt`.
     * If you join a new conversation, or you receive a message in a conversation, that conversation will appear at the start of the list.
     *
     * The snapshot is an empty list if the current user does not exist yet.
     *
     * Initially, you will be subscribed to the 20 most recently active conversations and any conversations that have activity after you subscribe.
     * Call `loadMore` to load additional older conversations. This will trigger `onSnapshot`.
     *
     * If you provide a `filter` in the options, only conversations matching the filter will be included in the snapshot.
     * See {@link ConversationFilter} for more details on what filter options are supported.
     *
     * Tip: `ConversationSnapshot` has a `lastMessage` property. Whenever you are sent a message, that message will be at `snapshot[0].lastMessage`.
     * If you just want to react to newly received messages, you can use this instead of calling `ConversationRef.subscribeMessages`.
     * This is much easier and more efficient.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     *
     * @example Subscribe to all your conversations and log them
     * ```ts
     * session.subscribeConversations(snapshots => console.log(snapshots));
     * ```
     *
     * @example Subscribe to conversations with a custom field
     * ```ts
     * session.subscribeConversations({
     *   filter: { custom: { category: ["==", "support"] } }
     * }, onSnapshot);
     * ```
     *
     * @example Subscribe to conversations with recent activity (last 7 days)
     * ```ts
     * const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
     * session.subscribeConversations({
     *   filter: { lastActivityAt: [">", sevenDaysAgo] }
     * }, onSnapshot);
     * ```
     */
    subscribeConversations(options: {
        filter?: ConversationFilter;
    }, onSnapshot?: (snapshot: ConversationSnapshot[], loadedAll: boolean) => void): ConversationListSubscription;
    /**
     * Creates a search for messages in all the current user's conversations.
     *
     * @remarks
     * The search feature is available on the Growth plan or higher. On the Basic plan, this method will return an error.
     *
     * Search is a two-step process. After calling `searchMessages`, call {@link MessageSearch.setQuery} to specify a search query and begin the search.
     *
     * As search can be quite slow, there are two different ways of using search:
     *
     * Option 1: Processing each search result as soon as it is received:
     *
     * ```ts
     * const search = session.searchMessages((results, status) => {
     *   console.log("Found a new message. All messages found so far:", results);
     * });
     * search.setQuery("Hello");
     * ```
     *
     * Option 2: Wait until the full page is received (up to 60s delay) before processing:
     *
     * ```ts
     * const search = session.searchMessages();
     * const { results, loadedAll } = await search.setQuery("Hello");
     * console.log("Search completed, first page of messages:", results);
     * ```
     *
     * @param onResults - Callback to run whenever we receive new results or the status changes. Status `searching` means we are actively searching for more messages. `canLoadMore` means that the search is idle, but you can load older results with {@link MessageSearch.loadMore}. `loadedAll` means that there are no more messages to load.
     * @returns A search object. Call {@link MessageSearch.setQuery} to specify the string to search for, and begin receiving results.
     *
     * @example Basic UI integration (search-on-keypress)
     * ```ts
     * const search = session.searchMessages((results, status) => {
     *   render(results, status);
     * });
     *
     * const searchInput = document.querySelector("#searchInput");
     * searchInput.addEventListener("change", () => {
     *   search.setQuery(searchInput.value);
     * });
     * ```
     */
    searchMessages(onResults?: (results: SearchMessageSnapshot[], status: "searching" | "canLoadMore" | "loadedAll") => void): MessageSearch;
    /**
     * Creates a search for all the current user's conversations.
     *
     * @remarks
     * The search feature is available on the Growth plan or higher. On the Basic plan, this method will return an error.
     *
     * Search is a two-step process. After calling `searchConversations`, call {@link ConversationSearch.setQuery} to specify a search query and begin the search.
     *
     * As search can be quite slow, there are two different ways of using search:
     *
     * Option 1: Processing each search result as soon as it is received:
     *
     * ```ts
     * const search = session.searchConversations((results, status) => {
     *   console.log("Found a new conversation. All conversations found so far:", results);
     * });
     * search.setQuery("Hello");
     * ```
     *
     * Option 2: Wait until the full page is received (up to 60s delay) before processing:
     *
     * ```ts
     * const search = session.searchConversations();
     * const { results, loadedAll } = await search.setQuery("Hello");
     * console.log("Search completed, first page of conversations:", results);
     * ```
     *
     * @param onResults - Callback to run whenever we receive new results or the status changes. Status `searching` means we are actively searching for more conversations. `canLoadMore` means that the search is idle, but you can load older results with {@link ConversationSearch.loadMore}. `loadedAll` means that there are no more conversations to load.
     * @returns A {@link ConversationSearch}. Call {@link ConversationSearch.setQuery} to specify the string to search for, and begin receiving results.
     *
     * @example Basic UI integration (search-on-keypress)
     * ```ts
     * const search = session.searchConversations((results, status) => {
     *   render(results, status);
     * });
     *
     * const searchInput = document.querySelector("#searchInput");
     * searchInput.addEventListener("change", () => {
     *   search.setQuery(searchInput.value);
     * });
     * ```
     */
    searchConversations(onResults?: (results: ConversationSnapshot[], status: "searching" | "canLoadMore" | "loadedAll") => void): ConversationSearch;
    /**
     * Upload a generic file without any additional metadata.
     *
     * @remarks
     * This function does not send any message, it only uploads the file and returns a file token.
     * To send the file in a message, pass the file token in a {@link SendFileBlock} when calling {@link ConversationRef.send}.
     *
     * {@link https://talkjs.com/docs/Concepts/Message_Content/#sending-message-content | See the documentation} for more information about sending files in messages.
     *
     * If the file is a video, image, audio file, or voice recording, use one of the other functions like {@link uploadImage} instead.
     *
     * @param data The binary file data. Usually a {@link https://developer.mozilla.org/en-US/docs/Web/API/File | File}.
     * @param metadata Information about the file
     * @returns A file token that can be used to send the file in a message.
     */
    uploadFile(data: Blob, metadata: GenericFileMetadata): Promise<FileToken>;
    /**
     * Upload an image with image-specific metadata.
     *
     * @remarks
     * This is a variant of {@link uploadFile} used for images.
     *
     * @param data The binary image data. Usually a {@link https://developer.mozilla.org/en-US/docs/Web/API/File | File}.
     * @param metadata Information about the image.
     * @returns A file token that can be used to send the image in a message.
     */
    uploadImage(data: Blob, metadata: ImageFileMetadata): Promise<FileToken>;
    /**
     * Upload a video with video-specific metadata.
     *
     * @remarks
     * This is a variant of {@link uploadFile} used for videos.
     *
     * @param data The binary video data. Usually a {@link https://developer.mozilla.org/en-US/docs/Web/API/File | File}.
     * @param metadata Information about the video.
     * @returns A file token that can be used to send the video in a message.
     */
    uploadVideo(data: Blob, metadata: VideoFileMetadata): Promise<FileToken>;
    /**
     * Upload an audio file with audio-specific metadata.
     *
     * @remarks
     * This is a variant of {@link uploadFile} used for audio files.
     *
     * @param data The binary audio data. Usually a {@link https://developer.mozilla.org/en-US/docs/Web/API/File | File}.
     * @param metadata Information about the audio file.
     * @returns A file token that can be used to send the audio file in a message.
     */
    uploadAudio(data: Blob, metadata: AudioFileMetadata): Promise<FileToken>;
    /**
     * Upload a voice recording with voice-specific metadata.
     *
     * @remarks
     * This is a variant of {@link uploadFile} used for voice recordings.
     *
     * @param data The binary audio data. Usually a {@link https://developer.mozilla.org/en-US/docs/Web/API/File | File}.
     * @param metadata Information about the voice recording.
     * @returns A file token that can be used to send the audio file in a message.
     */
    uploadVoice(data: Blob, metadata: VoiceRecordingFileMetadata): Promise<FileToken>;
}

export declare interface TalkSessionOptions {
    appId: string;
    userId: string;
    /**
     * @deprecated Use {@link TalkSession.setToken} instead. This parameter is ignored if you have previously called getTalkSession with the same userId and appId.
     */
    token?: string;
    /**
     * @deprecated Use {@link TalkSession.onNeedToken} and {@link TalkSession.setToken} instead. This parameter is ignored if you have previously called getTalkSession with the same userId and appId.
     */
    tokenFetcher?: () => string | Promise<string>;
}

/**
 * A block of formatted text in a message's content.
 *
 * @remarks
 * Each TextBlock is a tree of {@link TextNode} children describing the structure of some formatted text.
 * Each child is either a plain text string, or a `node` representing some text with additional formatting.
 *
 * For example, if the user typed:
 *
 * > *This first bit* is bold, and *_the second bit_* is bold and italics
 *
 * Then this would become a Text Block with the structure:
 *
 * ```json
 * {
 *   type: "text",
 *   children: [
 *      {
 *       type: "text",
 *       children: [
 *         { type: "bold", children: ["This first bit"] },
 *         " is bold, and ",
 *         {
 *           children: [
 *             { type: "italic", children: ["the second bit"] }
 *           ],
 *           type: "bold",
 *         },
 *         " is bold and italics",
 *       ],
 *     },
 *   ],
 * }
 * ```
 *
 * Rather than relying on the automatic message parsing, you can also specify the `TextBlock` directly using {@link ConversationRef.send} with {@link SendMessageParams}.
 *
 * @public
 */
export declare interface TextBlock {
    readonly type: "text";
    readonly children: TextNode[];
}

/**
 * Any node that can exist inside a {@link TextBlock}.
 *
 * @remarks
 * The simplest `TextNode` is a plain text string.
 * Using "hello" as an example message, the `TextBlock` would be:
 *
 * ```ts
 * {
 *   type: 'text';
 *   children: ['hello'];
 * }
 * ```
 *
 * Other than plain text, there are many different kinds of node which render some text in a specific way or with certain formatting.
 *
 * ```ts
 * type TextNode =
 *     | string
 *     | MarkupNode
 *     | BulletListNode
 *     | BulletPointNode
 *     | CodeSpanNode
 *     | LinkNode
 *     | AutoLinkNode
 *     | ActionLinkNode
 *     | ActionButtonNode
 *     | CustomEmojiNode
 *     | MentionNode;
 * ```
 *
 * If the text node is not a plain string, it will have a `type` field indicating what kind of node it is, and either a property `text: string` or a property `children: TextNode[]`.
 * This will be true for all nodes added in the future as well.
 *
 * @public
 */
export declare type TextNode = string | MarkupNode | BulletListNode | BulletPointNode | CodeSpanNode | LinkNode | AutoLinkNode | ActionLinkNode | ActionButtonNode | CustomEmojiNode | MentionNode;

/**
 * The state of a typing subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface TypingActiveState {
    readonly type: "active";
    /**
     * The most recently received typing indicator snapshot, or `null` if you are not a participant in the conversation (including when the conversation does not exist).
     */
    readonly latestSnapshot: TypingSnapshot | null;
}

/**
 * A snapshot of the typing indicators in a conversation at a given moment in time.
 * Will be either {@link FewTypingSnapshot} when only a few people are typing, or {@link ManyTypingSnapshot} when many people are typing.
 *
 * @remarks
 * Currently {@link FewTypingSnapshot} is used when there are 5 or less people typing in the conversation, and {@link ManyTypingSnapshot} is used when more than 5 people are typing.
 * This limit may change in the future, which will not be considered a breaking change.
 *
 * @example Converting a TypingSnapshot to text
 * ```ts
 * function formatTyping(snapshot: TypingSnapshot): string {
 *   if (snapshot.many) {
 *     return "Several people are typing";
 *   }
 *
 *   const names = snapshot.users.map(user => user.name);
 *
 *   if (names.length === 0) {
 *     return "";
 *   }
 *
 *   if (names.length === 1) {
 *     return names[0] + " is typing";
 *   }
 *
 *   if (names.length === 2) {
 *     return names.join(" and ") + " are typing";
 *   }
 *
 *   // Prefix last name with "and "
 *   names.push("and " + names.pop());
 *   return names.join(", ") + " are typing";
 * }
 * ```
 */
export declare type TypingSnapshot = FewTypingSnapshot | ManyTypingSnapshot;

/**
 * A subscription to the typing status in a specific conversation
 *
 * @remarks
 * Get a TypingSubscription by calling {@link ConversationRef.subscribeTyping}.
 *
 * When there are "many" people typing (meaning you received {@link ManyTypingSnapshot}), the next update you receive will be {@link FewTypingSnapshot} once enough people stop typing.
 * Until then, your {@link ManyTypingSnapshot} is still valid and does not need to changed, so `onSnapshot` will not be called.
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface TypingSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot: TypingSnapshot | null`. It is the current state of the typing indicators, or null if you're not a participant in the conversation
     *
     * When `type` is "error", includes the `error: Error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | TypingActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<TypingActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * The state of a subscription after you have manually unsubscribed
 *
 * @public
 */
export declare interface UnsubscribedState {
    readonly type: "unsubscribed";
}

/**
 * The state of a user subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface UserActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot for the user, or `null` if the user does not exist yet.
     */
    readonly latestSnapshot: UserSnapshot | null;
}

/**
 * The state of a user online subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface UserOnlineActiveState {
    readonly type: "active";
    /**
     * The most recently received snapshot
     */
    readonly latestSnapshot: UserOnlineSnapshot | null;
}

/**
 * A snapshot of a user's online status at a given moment in time.
 *
 * @remarks
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface UserOnlineSnapshot {
    /**
     * The user this snapshot relates to
     */
    readonly user: UserSnapshot;
    /**
     * Whether the user is connected right now
     *
     * @remarks
     * Users are considered connected whenever they have an active websocket connection to the TalkJS servers.
     * In practice, this means:
     *
     * People using the {@link https://talkjs.com/docs/JavaScript_Data_API/ | JS Data API} are considered connected if they are subscribed to something, or if they sent a request in the last few seconds.
     * Creating a `TalkSession` is not enough to appear connected.
     *
     * People using {@link https://talkjs.com/docs/UI_Components/ | Components}, are considered connected if they have a UI open.
     *
     * People using the {@link https://talkjs.com/docs/UI_Components/JavaScript/Classic/ | JavaScript SDK}, {@link https://talkjs.com/docs/UI_Components/React/Classic/ | React SDK}, {@link https://talkjs.com/docs/UI_Components/React_Native/ | React Native SDK}, or {@link https://talkjs.com/docs/UI_Components/Flutter/ | Flutter SDK} are considered connected whenever they have an active `Session` object.
     */
    readonly isConnected: boolean;
}

/**
 * A subscription to the online status of a user
 *
 * @remarks
 * Get a UserOnlineSubscription by calling {@link UserRef.subscribeOnline}.
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface UserOnlineSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot: UserOnlineSnapshot | null`
     * `null` means the user does not exist.
     *
     * When `type` is "error", includes the `error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | UserOnlineActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     *
     * @remarks
     * Wait for this promise if you want to perform some action as soon as the subscription is active.
     *
     * The promise rejects if the subscription is terminated before it connects.
     */
    readonly connected: Promise<UserOnlineActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * References the user with a given user ID.
 *
 * @remarks
 * Used in all Data API operations affecting that user, such as creating the user, fetching or updating user data, or adding a user to a conversation.
 * Created via {@link Session.user}.
 *
 * @public
 */
export declare interface UserRef {
    /**
     * The ID of the referenced user.
     *
     * @remarks
     * Immutable: if you want to reference a different user, get a new UserRef instead.
     */
    readonly id: string;
    /**
     * Fetches a snapshot of the user.
     *
     * @remarks
     * This contains all of a user's public information.
     * Fetching a user snapshot doesn't require any permissions. You can read the public information of any user.
     * Private information, such as email addresses and phone numbers, aren't included in the response.
     *
     * @returns A snapshot of the user's public attributes, or null if the user doesn't exist.
     */
    get(): Promise<UserSnapshot | null>;
    /**
     * Sets properties of this user. The user is created if a user with this ID doesn't already exist.
     *
     * @remarks
     * `name` is required when creating a user. The promise will reject if you don't provide a `name` and the user does not exist yet.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if the request is invalid or if client-side user syncing is disabled.
     */
    set(params: SetUserParams): Promise<void>;
    /**
     * Creates a user with this ID, or does nothing if a user with this ID already exists.
     *
     * @remarks
     * If the user already exists, this operation is still considered successful and the promise will still resolve.
     *
     * @returns A promise that resolves when the operation completes. The promise will reject if client-side user syncing is disabled and the user does not already exist.
     */
    createIfNotExists(params: CreateUserParams): Promise<void>;
    /**
     * Subscribe to this user's state.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called when the user is created or the snapshot changes.
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     *
     * @returns A subscription to the user
     */
    subscribe(onSnapshot?: (event: UserSnapshot | null) => void): UserSubscription;
    /**
     * Subscribe to this user and their online status.
     *
     * @remarks
     * While the subscription is active, `onSnapshot` will be called when the user is created or the snapshot changes (including changes to the nested UserSnapshot).
     *
     * Remember to call `.unsubscribe` on the subscription once you are done with it.
     *
     * @returns A subscription to the user's online status
     */
    subscribeOnline(onSnapshot?: (event: UserOnlineSnapshot | null) => void): UserOnlineSubscription;
}

/**
 * A snapshot of a user's attributes at a given moment in time.
 *
 * @remarks
 * Users also have private information, such as email addresses and phone numbers, but these are only exposed on the {@link https://talkjs.com/docs/REST_API/ | REST API}.
 *
 * Snapshots are immutable and we try to reuse them when possible. You should only re-render your UI when `oldSnapshot !== newSnapshot`.
 *
 * @public
 */
export declare interface UserSnapshot {
    /**
     * The unique ID that is used to identify the user in TalkJS
     */
    readonly id: string;
    /**
     * The user's name, which is displayed on the TalkJS UI
     */
    readonly name: string;
    /**
     * Custom metadata you have set on the user
     */
    readonly custom: Record<string, string>;
    /**
     * An {@link https://www.w3.org/International/articles/language-tags/ | IETF language tag}.
     * For more information, see: {@link https://talkjs.com/docs/Features/Language_Support/#localization | Localization}.
     *
     * When `locale` is null, the app's default locale will be used
     */
    readonly locale: string | null;
    /**
     * An optional URL to a photo that is displayed as the user's avatar
     */
    readonly photoUrl: string | null;
    /**
     * TalkJS supports multiple sets of settings for users, called "roles". Roles allow you to change the behavior of TalkJS for different users.
     * You have full control over which user gets which configuration.
     */
    readonly role: string;
    /**
     * The default message a person sees when starting a chat with this user
     *
     * @remarks
     * Welcome messages are rendered in the UI as messages, but they are not real
     * messages. This means they do not appear when you list messages using the
     * REST API or JS Data API, and you cannot reply or react to them.
     *
     * Note: User welcome messages are only supported by the Classic SDKs, and in
     * the Components-based SDKs, this field is ignored. To show welcome messages
     * in the Components-based SDK, see
     * {@link https://talkjs.com/docs/Guides/React/Welcome_Messages/ | Welcome Messages}.
     *
     * @deprecated
     */
    readonly welcomeMessage: string | null;
}

/**
 * A subscription to a specific user
 *
 * @remarks
 * Get a UserSubscription by calling {@link UserRef.subscribe}
 *
 * Remember to `.unsubscribe` the subscription once you are done with it.
 *
 * @public
 */
export declare interface UserSubscription {
    /**
     * The current state of the subscription
     *
     * @remarks
     * An object with the following fields:
     *
     * `type` is one of "pending", "active", "unsubscribed", or "error".
     *
     * When `type` is "active", includes `latestSnapshot: UserSnapshot | null`. It is the current state of the user, or null if they don't exist.
     *
     * When `type` is "error", includes the `error: Error` field. It is a JS `Error` object explaining what caused the subscription to be terminated.
     */
    state: PendingState | UserActiveState | UnsubscribedState | ErrorState;
    /**
     * Resolves when the subscription starts receiving updates from the server.
     */
    readonly connected: Promise<UserActiveState>;
    /**
     * Resolves when the subscription permanently stops receiving updates from the server.
     *
     * @remarks
     * This is either because you unsubscribed or because the subscription encountered an unrecoverable error.
     */
    readonly terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Unsubscribe from this resource and stop receiving updates.
     *
     * @remarks
     * If the subscription is already in the "unsubscribed" or "error" state, this is a no-op.
     */
    unsubscribe(): void;
}

/**
 * A FileBlock variant for a video attachment, with additional video-specific metadata.
 *
 * @remarks
 * You can identify this variant by checking for `subtype: "video"`.
 *
 * Includes metadata about the height and width of the video in pixels, and the duration of the video in seconds, where available.
 *
 * Videos that you upload with the TalkJS UI will include the dimensions and duration as long as the sender's browser can preview the file.
 * Videos that you upload with the REST API or {@link Session.uploadVideo} will include this metadata if you specified it when uploading.
 * Videos attached in a reply to an email notification will not include any metadata.
 *
 * @public
 */
export declare interface VideoBlock {
    readonly type: "file";
    readonly subtype: "video";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this video in another message.
     */
    readonly fileToken: FileToken;
    /**
     * The URL where you can fetch the file.
     */
    readonly url: string;
    /**
     * The size of the file in bytes.
     */
    readonly size: number;
    /**
     * The name of the video file, including file extension.
     */
    readonly filename: string;
    /**
     * The width of the video in pixels, if known.
     */
    readonly width?: number;
    /**
     * The height of the video in pixels, if known.
     */
    readonly height?: number;
    /**
     * The duration of the video in seconds, if known.
     */
    readonly duration?: number;
}

export declare interface VideoFileMetadata {
    /**
     * The name of the file including extension.
     */
    filename: string;
    /**
     * The width of the video in pixels, if known.
     */
    width?: number;
    /**
     * The height of the video in pixels, if known.
     */
    height?: number;
    /**
     * The duration of the video in seconds, if known.
     */
    duration?: number;
}

/**
 * A FileBlock variant for a voice recording attachment, with additional voice-recording-specific metadata.
 *
 * @remarks
 * You can identify this variant by checking for `subtype: "voice"`.
 *
 * The same file could be uploaded as either a voice block, or as an {@link AudioBlock}.
 * The same data will be available either way, but they will be rendered differently in the UI.
 *
 * Includes metadata about the duration of the recording in seconds, where available.
 *
 * Voice recordings done in the TalkJS UI will always include the duration.
 * Voice recordings that you upload with the REST API or {@link Session.uploadVoice} will include this metadata if you specified it when uploading.
 *
 * Voice recordings will never be taken from a reply to an email notification.
 * Any attached audio file will become an {@link AudioBlock} instead of a voice block.
 *
 * @public
 */
export declare interface VoiceBlock {
    readonly type: "file";
    readonly subtype: "voice";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this voice recording in another message.
     */
    readonly fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    readonly url: string;
    /**
     * The size of the file in bytes
     */
    readonly size: number;
    /**
     * The name of the file, including file extension
     */
    readonly filename: string;
    /**
     * The duration of the voice recording in seconds, if known
     */
    readonly duration?: number;
}

export declare interface VoiceRecordingFileMetadata {
    /**
     * The name of the file including extension.
     */
    filename: string;
    /**
     * The duration of the recording in seconds, if known.
     */
    duration?: number;
}

export { }
