/**
 * A node in a {@link TextBlock} that renders its children as a clickable {@link https://talkjs.com/docs/Features/Customizations/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 {
    type: "actionButton";
    /**
     * The name of the custom action to invoke when the button is clicked.
     */
    action: string;
    /**
     * The parameters to pass to the custom action when the button is clicked.
     */
    params: Record<string, string>;
    children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that renders its children as a clickable {@link https://talkjs.com/docs/Features/Customizations/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 {
    type: "actionLink";
    /**
     * The name of the custom action to invoke when the link is clicked.
     */
    action: string;
    /**
     * The parameters to pass to the custom action when the link is clicked.
     */
    params: Record<string, string>;
    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 {
    type: "file";
    subtype: "audio";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this file in another message.
     */
    fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    url: string;
    /**
     * The size of the file in bytes
     */
    size: number;
    /**
     * The name of the audio file, including file extension
     */
    filename: string;
    /**
     * The duration of the audio in seconds, if known
     */
    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/Reference/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 {
    type: "autoLink";
    /**
     * The URL to open when a user clicks this node.
     */
    url: string;
    /**
     * The text to display in the link.
     */
    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 {
    type: "bulletList";
    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 {
    type: "bulletPoint";
    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 {
    type: "codeSpan";
    text: string;
}

/**
 * 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 {
    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).
     */
    latestSnapshot: ConversationSnapshot | null;
}

/**
 * The state of a conversation list subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ConversationListActiveState {
    type: "active";
    /**
     * The most recently received snapshot for the conversations
     */
    latestSnapshot: ConversationSnapshot[];
    /**
     * True if `latestSnapshot` contains all conversations you are in.
     * Use {@link ConversationListSubscription.loadMore} to load more.
     */
    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.
 *
 * @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.
     */
    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.
     */
    terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older conversations
     *
     * @remarks
     * Calling `loadMore` multiple times in parallel will still only load one page of conversations.
     *
     * @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 conversation with a given conversation ID, from the perspective of the current user.
 *
 * @remarks
 * Used in all Data API operations affecting that conversation, such as fetching or updating conversation attributes.
 * Created via {@link Session.conversation|Session.conversation()}.
 *
 * @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 {@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 {@linkcode ParticipantRef} for that user's participation in this conversation
     * @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.
     * To fetch the most recent messages in this conversation, use {@link ConversationRef.subscribeMessages} instead.
     *
     * @param id - The ID of the user that you want to reference
     * @returns A {@linkcode UserRef} for the user with that ID
     * @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 your participation in it.
     *
     * @remarks
     * The conversation is created if a conversation with this ID doesn't already exist.
     * You are added as a participant if you are not already a participant in the conversation.
     *
     * @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
     * Initially, you will be subscribed to the 30 most recent messages and any new messages.
     * Call `loadMore` to load additional older messages.
     *
     * Whenever `Subscription.state.type` is "active" and a message is sent, edited, deleted, or you load more messages, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     * `loadedAll` is true when the snapshot contains all the messages in the conversation.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     */
    subscribeMessages(onSnapshot?: (snapshot: MessageSnapshot[] | null, loadedAll: boolean) => void): MessageSubscription;
    /**
     * Subscribes to the participants in the conversation.
     *
     * @remarks
     * Initially, you will be subscribed to the 10 participants who joined most recently, and any new participants.
     * Call `loadMore` to load additional older participants.
     *
     * Whenever `Subscription.state.type` is "active" and a participant is created, edited, deleted, or you load more participants, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     * `loadedAll` is true when the snapshot contains all the participants in the conversation.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     */
    subscribeParticipants(onSnapshot?: (snapshot: ParticipantSnapshot[] | null, loadedAll: boolean) => void): ParticipantSubscription;
    /**
     * Subscribes to the conversation.
     *
     * @remarks
     * Whenever `Subscription.state.type` is "active" and something about the conversation changes, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     * 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)
     */
    subscribe(onSnapshot?: (snapshot: ConversationSnapshot | null) => void): ConversationSubscription;
    /**
     * Subscribes to the typing status of the conversation.
     *
     * @remarks
     * Whenever `Subscription.state.type` is "active" and the typing status changes, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     * This includes changes to nested data, such as when a user who is typing changes their name.
     *
     * The snapshot is null if you are not a participant in the conversation (including when the conversation doesn't exist)
     *
     * Note that if there are "many" people typing and another person starts to type, `onSnapshot` will not be called.
     * This is because your existing {@link ManyTypingSnapshot} is still valid and did not change when the new person started to type.
     */
    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();
     *
     *   // Don't mark as typing more than once every 5s
     *   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>;
}

/**
 * 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
     */
    id: string;
    /**
     * Contains the conversation subject, or `null` if the conversation does not have a subject specified.
     */
    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.
     */
    photoUrl: string | null;
    /**
     * One or more welcome messages that will display to the user as a SystemMessage
     */
    welcomeMessages: string[];
    /**
     * Custom metadata you have set on the conversation
     */
    custom: Record<string, string>;
    /**
     * The date that the conversation was created, as a unix timestamp in milliseconds.
     */
    createdAt: number;
    /**
     * The date that the current user joined the conversation, as a unix timestamp in milliseconds.
     */
    joinedAt: number;
    /**
     * The last message sent in this conversation, or null if no messages have been sent.
     */
    lastMessage: MessageSnapshot | null;
    /**
     * The number of messages in this conversation that the current user hasn't read.
     */
    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.
     */
    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.
     */
    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.
     */
    isUnread: boolean;
    /**
     * The current user's permission level in this conversation.
     */
    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 `@`.
     */
    notify: boolean | "MentionsOnly";
}

/**
 * A subscription to a specific conversation.
 *
 * @remarks
 * Get a ConversationSubscription by calling {@link ConversationRef.subscribe}
 *
 * @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.
     */
    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.
     */
    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.
     */
    welcomeMessages?: string[];
    /**
     * 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>;
    /**
     * 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.html | localization documentation}
     * Default = the locale selected 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
     */
    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/Message_Features/Emoji_Reactions/#custom-emojis | custom emoji}.
 *
 * @public
 */
export declare interface CustomEmojiNode {
    type: "customEmoji";
    /**
     * The name of the custom emoji to show.
     */
    text: string;
}

/**
 * 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 you have 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 you have 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/Message_Features/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 {
    type: "error";
    /**
     * The error that caused the subscription to be terminated
     */
    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.
     */
    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.
     */
    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/Reference/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 & {
    __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 {
    type: "file";
    /**
     * Never set for generic file blocks.
     */
    subtype?: undefined;
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this file in another message.
     */
    fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    url: string;
    /**
     * The size of the file in bytes
     */
    size: number;
    /**
     * The name of the file, including file extension
     */
    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 or got garbage collected.
 *
 * The `token` and `tokenFetcher` properties are ignored if there is already a session for that user in the registry.
 */
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 {
    type: "file";
    subtype: "image";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this image in another message.
     */
    fileToken: FileToken;
    /**
     * The URL where you can fetch the file.
     */
    url: string;
    /**
     * The size of the file in bytes.
     */
    size: number;
    /**
     * The name of the image file, including file 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;
}

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 {
    type: "link";
    /**
     * The URL to open when the node is clicked.
     */
    url: string;
    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 {
    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
     */
    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
     */
    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.
     */
    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>`
     */
    type: "bold" | "italic" | "strikethrough";
    children: TextNode[];
}

/**
 * A node in a {@link TextBlock} that is used when a user is {@link https://talkjs.com/docs/Features/Message_Features/Mentions/ | mentioned}.
 *
 * @remarks
 * Used when a user types `@name` and selects the user they want to mention.
 *
 * @public
 */
export declare interface MentionNode {
    type: "mention";
    /**
     * The ID of the user who is mentioned.
     */
    id: string;
    /**
     * The name of the user who is mentioned.
     */
    text: string;
}

/**
 * The state of a messages subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface MessageActiveState {
    type: "active";
    /**
     * The most recently received snapshot for the user, or `null` if the user does not exist yet.
     */
    latestSnapshot: MessageSnapshot[] | null;
    /**
     * True if `latestSnapshot` contains all messages in the conversation.
     * Use {@link MessageSubscription.loadMore} to load more.
     */
    loadedAll: boolean;
}

/**
 * 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;
    /**
     * Fetches a snapshot of the message.
     *
     * @remarks
     * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#cached-fetch | Cached Fetch}
     *
     * @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 they are already not a participant.
     *
     * @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>;
}

/**
 * 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
     */
    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.
     */
    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.
     */
    sender: UserSnapshot | null;
    /**
     * Custom metadata you have set on the message
     */
    custom: Record<string, string>;
    /**
     * Time at which the message was sent, as a unix timestamp in milliseconds
     */
    createdAt: number;
    /**
     * Time at which the message was last edited, as a unix timestamp in milliseconds.
     * `null` if the message has never been edited.
     */
    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.
     */
    referencedMessage: ReferencedMessageSnapshot | null;
    /**
     * Where this message originated from:
     *
     * - "web" = Message sent via the UI or via {@link ConversationBuilder.sendMessage}
     *
     * - "rest" = Message sent via the REST API's "send message" endpoint or {@link ConversationRef.send}
     *
     * - "import" = Message sent via the REST API's "import messages" endpoint
     *
     * - "email" = Message sent by replying to an email notification
     */
    origin: "web" | "rest" | "import" | "email";
    /**
     * 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.
     */
    plaintext: string;
    /**
     * The main body of the message, as a list of blocks that are rendered top-to-bottom.
     */
    content: ContentBlock[];
}

/**
 * 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.
 *
 * @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.
     */
    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.
     */
    terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older messages
     *
     * @remarks
     * Calling `loadMore` multiple times in parallel will still only load one page of messages.
     *
     * @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;
}

/**
 * The state of a participants subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface ParticipantActiveState {
    type: "active";
    /**
     * The most recently received snapshot for the participants, or `null` if you are not a participant in that conversation.
     */
    latestSnapshot: ParticipantSnapshot[] | null;
    /**
     * True if `latestSnapshot` contains all participants in the conversation.
     * Use {@link ParticipantSubscription.loadMore} to load more.
     */
    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.
     *
     * @remarks
     * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
     *
     * @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.
     *
     * @remarks
     * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
     *
     * @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.
     *
     * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching}
     *
     * @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>;
}

/**
 * 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
     */
    user: UserSnapshot;
    /**
     * The level of access this participant has in the conversation.
     */
    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 `@`.
     */
    notify: boolean | "MentionsOnly";
    /**
     * The date that this user joined the conversation, as a unix timestamp in milliseconds.
     */
    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.
 *
 * @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.
     */
    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.
     */
    terminated: Promise<UnsubscribedState | ErrorState>;
    /**
     * Expand the window to include older participants
     *
     * @remarks
     * Calling `loadMore` multiple times in parallel will still only load one page of participants.
     *
     * @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 {
    type: "pending";
}

/**
 * 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
     */
    id: string;
    /**
     * Referenced messages are always "UserMessage" because you cannot reply to a system message.
     */
    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
     */
    sender: UserSnapshot;
    /**
     * Custom metadata you have set on the message
     */
    custom: Record<string, string>;
    /**
     * Time at which the message was sent, as a unix timestamp in milliseconds
     */
    createdAt: number;
    /**
     * Time at which the message was last edited, as a unix timestamp in milliseconds.
     * `null` if the message has never been edited.
     */
    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.
     */
    referencedMessageId: string | null;
    /**
     * Where this message originated from:
     *
     * - "web" = Message sent via the UI or via {@link ConversationBuilder.sendMessage}
     *
     * - "rest" = Message sent via the REST API's "send message" endpoint or {@link ConversationRef.send}
     *
     * - "import" = Message sent via the REST API's "import messages" endpoint
     *
     * - "email" = Message sent by replying to an email notification
     */
    origin: "web" | "rest" | "import" | "email";
    /**
     * 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.
     */
    plaintext: string;
    /**
     * The main body of the message, as a list of blocks that are rendered top-to-bottom.
     */
    content: ContentBlock[];
}

export declare function registerPolyfills({ WebSocket }: {
    WebSocket: object;
}): void;

/**
 * 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 you have set on the user.
     * 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 you have set on the user.
     * 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/Message_Features/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.
     */
    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 = `ReadWrite` access.
     *
     * @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.html | localization documentation}
     * Default = the locale selected on the dashboard
     */
    locale?: string;
    /**
     * 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
     */
    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;
}

export declare type Subscription = {
    unsubscribe: () => void;
};

export declare interface TalkSession {
    /**
     * 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;
    /**
     * 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.
     * 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(session.me.id)`.
     *
     * @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 {@linkcode UserRef} for the user with that ID
     * @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.
     *
     * @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 {@linkcode ConversationRef} for the conversation with that ID
     * @public
     */
    conversation(id: string): ConversationRef;
    /**
     * Subscribes to your most recently active conversations.
     *
     * @remarks
     * 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.
     *
     * If an older conversation receives a new message, or you are added to a conversation, it will appear at the start of the list.
     * Call `loadMore` to load additional older conversations.
     *
     * Whenever `Subscription.state.type` is "active" and something changes in your conversations, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     * `loadedAll` is true when the snapshot contains all your conversations.
     *
     * If the current user does not exist yet, the snapshot will be an empty list.
     */
    subscribeConversations(onSnapshot?: (snapshot: ConversationSnapshot[], loadedAll: boolean) => void): ConversationListSubscription;
    /**
     * 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 {@linkcode SendFileBlock} when calling {@linkcode ConversationRef.send}.
     *
     * {@link https://talkjs.com/docs/Reference/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 {@linkcode uploadImage} instead.
     *
     * @param data The binary file data. Usually a {@linkcode 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 {@linkcode uploadFile} used for images.
     *
     * @param data The binary image data. Usually a {@linkcode 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 {@linkcode uploadFile} used for videos.
     *
     * @param data The binary video data. Usually a {@linkcode 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 {@linkcode uploadFile} used for audio files.
     *
     * @param data The binary audio data. Usually a {@linkcode 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 {@linkcode uploadFile} used for voice recordings.
     *
     * @param data The binary audio data. Usually a {@linkcode 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;
    token?: string;
    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 the automatic message parsing, you can also specify the `TextBlock` directly using {@link ConversationRef.send} with {@link SendMessageParams}.
 *
 * @public
 */
export declare interface TextBlock {
    type: "text";
    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 {
    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).
     */
    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 doesn not need to changed, so `onSnapshot` will not be called.
 *
 * @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.
     */
    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.
     */
    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 {
    type: "unsubscribed";
}

/**
 * The state of a user subscription when it is actively listening for changes
 *
 * @public
 */
export declare interface UserActiveState {
    type: "active";
    /**
     * The most recently received snapshot for the user, or `null` if the user does not exist yet.
     */
    latestSnapshot: UserSnapshot | null;
}

/**
 * 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.
     *
     * Supports {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#automatic-batching | Automatic Batching} and {@link https://talkjs.com/docs/Reference/JavaScript_Data_API/Performance/#cached-fetch | Cached Fetch}
     *
     * @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
     * Whenever `Subscription.state.type` is "active" and the user is created or their attributes change, `onSnapshot` will fire and `Subscription.state.latestSnapshot` will be updated.
     *
     * @returns A subscription to the user
     */
    subscribe(onSnapshot?: (event: UserSnapshot | null) => void): UserSubscription;
}

/**
 * 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/Reference/REST_API/Getting_Started/Introduction/ | 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
     */
    id: string;
    /**
     * The user's name, which is displayed on the TalkJS UI
     */
    name: string;
    /**
     * Custom metadata you have set on the user
     */
    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.html | Localization}.
     *
     * When `locale` is null, the app's default locale will be used
     */
    locale: string | null;
    /**
     * An optional URL to a photo that is displayed as the user's avatar
     */
    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.
     */
    role: string;
    /**
     * The default message a person sees when starting a chat with this user
     */
    welcomeMessage: string | null;
}

/**
 * A subscription to a specific user
 *
 * @remarks
 * Get a UserSubscription by calling {@link UserRef.subscribe}
 *
 * @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.
     */
    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.
     */
    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 {
    type: "file";
    subtype: "video";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this video in another message.
     */
    fileToken: FileToken;
    /**
     * The URL where you can fetch the file.
     */
    url: string;
    /**
     * The size of the file in bytes.
     */
    size: number;
    /**
     * The name of the video file, including file 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;
}

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 recording 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 {
    type: "file";
    subtype: "voice";
    /**
     * An encoded identifier for this file. Use in {@link SendFileBlock} to send this voice recording in another message.
     */
    fileToken: FileToken;
    /**
     * The URL where you can fetch the file
     */
    url: string;
    /**
     * The size of the file in bytes
     */
    size: number;
    /**
     * The name of the file, including file extension
     */
    filename: string;
    /**
     * The duration of the voice recording in seconds, if known
     */
    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 { }
