@namespace("chat.1") protocol chatUi { import idl "../keybase1" as keybase1; import idl "../gregor1" as gregor1; import idl "../stellar1" as stellar1; import idl "common.avdl"; import idl "unfurl.avdl"; import idl "commands.avdl"; record UIPagination { string next; string previous; int num; boolean last; } record UIInboxSmallTeamRow { ConvIDStr convID; string name; gregor1.Time time; union { null, string } snippet; SnippetDecoration snippetDecoration; union { null, string } draft; boolean isMuted; boolean isTeam; } enum UIInboxBigTeamRowTyp { LABEL_1, CHANNEL_2 } record UIInboxBigTeamChannelRow { ConvIDStr convID; string teamname; string channelname; union { null, string } draft; boolean isMuted; } record UIInboxBigTeamLabelRow { string name; TLFIDStr id; } variant UIInboxBigTeamRow switch (UIInboxBigTeamRowTyp state) { case LABEL: UIInboxBigTeamLabelRow; case CHANNEL: UIInboxBigTeamChannelRow; } record UIInboxReselectInfo { // we use this to defeat any race conditions, the UI can double check it actually has this selected ConvIDStr oldConvID; union { null, ConvIDStr } newConvID; } record UIInboxLayout { int totalSmallTeams; array smallTeams; array bigTeams; union { null, UIInboxReselectInfo } reselectInfo; array widgetList; } record UnverifiedInboxUIItemMetadata { string channelName; string headline; string headlineDecorated; string snippet; SnippetDecoration snippetDecoration; array writerNames; array resetParticipants; } record UnverifiedInboxUIItem { ConvIDStr convID; TLFIDStr tlfID; TopicType topicType; boolean isPublic; boolean isDefaultConv; string name; keybase1.TLFVisibility visibility; ConversationStatus status; ConversationMembersType membersType; ConversationMemberStatus memberStatus; TeamType teamType; union{ null, ConversationNotificationInfo } notifications; gregor1.Time time; ConversationVers version; LocalConversationVers localVersion; union { null, RetentionPolicy } convRetention; union { null, RetentionPolicy } teamRetention; MessageID maxMsgID; MessageID maxVisibleMsgID; MessageID readMsgID; union { null , UnverifiedInboxUIItemMetadata } localMetadata; union { null, string } draft; union { null, ConversationFinalizeInfo } finalizeInfo; array supersedes; array supersededBy; ConversationCommandGroups commands; } record UnverifiedInboxUIItems { array items; boolean offline; } enum UIParticipantType { NONE_0, USER_1, // Keybase or SBS PHONENO_2, EMAIL_3 } record UIParticipant { UIParticipantType type; string assertion; boolean inConvName; union { null, string } fullName; union { null, string } contactName; // if set this is an imptofu conversation with someone in our contacts } record UIPinnedMessage { UIMessage message; string pinnerUsername; } record InboxUIItem { ConvIDStr convID; TLFIDStr tlfID; TopicType topicType; boolean isPublic; boolean isEmpty; boolean isDefaultConv; string name; string snippet; SnippetDecoration snippetDecoration; string channel; string headline; string headlineDecorated; union { null, string } draft; keybase1.TLFVisibility visibility; array participants; array resetParticipants; ConversationStatus status; ConversationMembersType membersType; ConversationMemberStatus memberStatus; TeamType teamType; gregor1.Time time; union { null, ConversationNotificationInfo } notifications; union { null, ConversationCreatorInfoLocal } creatorInfo; ConversationVers version; LocalConversationVers localVersion; MessageID maxMsgID; MessageID maxVisibleMsgID; MessageID readMsgID; union { null, RetentionPolicy } convRetention; union { null, RetentionPolicy } teamRetention; union { null, ConversationSettingsLocal } convSettings; // Finalized convo stuff (KBFS only) union { null, ConversationFinalizeInfo } finalizeInfo; array supersedes; array supersededBy; // Command support ConversationCommandGroups commands; ConversationCommandGroups botCommands; map botAliases; // Pinned message union { null, UIPinnedMessage} pinnedMsg; } record InboxUIItemError { ConversationErrorType typ; string message; string unverifiedTLFName; // Only set if typ is for rekeying. union { null, ConversationErrorRekey} rekeyInfo; UnverifiedInboxUIItem remoteConv; } record InboxUIItems { array items; boolean offline; } record UIChannelNameMention { string name; ConvIDStr convID; } record UIAssetUrlInfo { string previewUrl; string fullUrl; boolean fullUrlCached; string mimeType; union { null, string } videoDuration; boolean inlineVideoPlayable; } record UIPaymentInfo { union { null, stellar1.AccountID } accountID; // "GXXXXXXX..." string amountDescription; // "1,323.1234567 XLM" string worth; // "$123.23" string worthAtSendTime; // "$123.23 CLP", amount in current user's display currency if this is a pure XLM tx stellar1.BalanceDelta delta; // NONE/INCREASE/DECREASE (e.g. INCREASE for "+ 1,323.1234567 XLM" amount above) string note; // secret note stellar1.PaymentID paymentID; // opaque paymentID stellar1.PaymentStatus status; // NONE, PENDING, CLAIMABLE, COMPLETED, ERROR, UNKNOWN string statusDescription; // "pending", "completed", "error" string statusDetail; boolean showCancel; // true if cancel is an option for this payment string fromUsername; string toUsername; // for path payments string sourceAmount; stellar1.Asset sourceAsset; string issuerDescription; } record UIRequestInfo { string amount; string amountDescription; union { null, stellar1.Asset } asset; union { null, stellar1.OutsideCurrencyCode } currency; string worthAtRequestTime; stellar1.RequestStatus status; } record UIMessageUnfurlInfo { MessageID unfurlMessageID; string url; UnfurlDisplay unfurl; boolean isCollapsed; } record UIMessageValid { MessageID messageID; gregor1.Time ctime; union { null, string } outboxID; MessageBody messageBody; union { null, string } decoratedTextBody; string bodySummary; string senderUsername; string senderDeviceName; keybase1.DeviceTypeV2 senderDeviceType; gregor1.UID senderUID; gregor1.DeviceID senderDeviceID; boolean superseded; union { null, UIAssetUrlInfo } assetUrlInfo; union { null, gregor1.Time } senderDeviceRevokedAt; array atMentions; ChannelMention channelMention; array channelNameMentions; boolean isEphemeral; boolean isEphemeralExpired; union { null, string} explodedBy; gregor1.Time etime; // reactionText -> [Reaction(username, reactionMsgID)...] ReactionMap reactions; boolean hasPairwiseMacs; array paymentInfos; union { null, UIRequestInfo } requestInfo; array unfurls; boolean isCollapsed; union { null, FlipGameIDStr } flipGameID; boolean isDeleteable; boolean isEditable; union { null, UIMessage } replyTo; union { null, MessageID} pinnedMessageID; // Non-empty if this message is keyed for a bot string botUsername; } record UIMessageOutbox { OutboxState state; string outboxID; MessageType messageType; string body; union { null, string } decoratedTextBody; gregor1.Time ctime; double ordinal; boolean isEphemeral; union { null, FlipGameIDStr} flipGameID; union { null, UIMessage } replyTo; // For attachments string filename; string title; union { null, MakePreviewRes } preview; } record UIMessageJourneycard { double ordinal; // Position in conversation. A float like {msgID:4,offset:1} -> "4.001" JourneycardType cardType; MessageID highlightMsgID; // Message ID to highlight in MSG_ATTENTION boolean openTeam; // Whether the team is open. Can be erroneously false due to caching. Only filled for ADD_PEOPLE. } enum MessageUnboxedState { VALID_1, ERROR_2, OUTBOX_3, PLACEHOLDER_4, JOURNEYCARD_5 } variant UIMessage switch (MessageUnboxedState state) { case VALID: UIMessageValid; case ERROR: MessageUnboxedError; case OUTBOX: UIMessageOutbox; case PLACEHOLDER: MessageUnboxedPlaceholder; case JOURNEYCARD: UIMessageJourneycard; } record UIMessages { array messages; union { null, UIPagination } pagination; } record UITeamMention { boolean inTeam; boolean open; union { null, string } description; union { null, int } numMembers; array publicAdmins; union { null, ConvIDStr } convID; } enum UITextDecorationTyp { PAYMENT_0, ATMENTION_1, CHANNELNAMEMENTION_2, MAYBEMENTION_3, LINK_4, MAILTO_5, KBFSPATH_6 } enum UIMaybeMentionStatus { UNKNOWN_0, USER_1, TEAM_2, NOTHING_3 } record UILinkDecoration { string url; string punycode; } variant UIMaybeMentionInfo switch (UIMaybeMentionStatus status) { case UNKNOWN: void; case USER: void; case TEAM: UITeamMention; case NOTHING: void; } variant UITextDecoration switch (UITextDecorationTyp typ) { case PAYMENT: TextPayment; case ATMENTION: string; case CHANNELNAMEMENTION: UIChannelNameMention; case MAYBEMENTION: MaybeMention; case LINK: UILinkDecoration; case MAILTO: UILinkDecoration; case KBFSPATH: KBFSPath; } void chatAttachmentDownloadStart(int sessionID); void chatAttachmentDownloadProgress(int sessionID, long bytesComplete, long bytesTotal) oneway; void chatAttachmentDownloadDone(int sessionID); void chatInboxLayout(int sessionID, string layout); // layout is JSON of UIInboxLayout void chatInboxUnverified(int sessionID, string inbox); // inbox is JSON of array void chatInboxConversation(int sessionID, string convs); // convs is JSON of array void chatInboxFailed(int sessionID, ConversationID convID, InboxUIItemError error); enum UIChatThreadStatusTyp { NONE_0, SERVER_1, VALIDATING_2, VALIDATED_3 } variant UIChatThreadStatus switch (UIChatThreadStatusTyp typ) { case NONE: void; case SERVER: void; case VALIDATING: int; case VALIDATED: void; } void chatThreadCached(int sessionID, union { null, string } thread); // thread is JSON of UIMessages void chatThreadFull(int sessionID, string thread); void chatThreadStatus(int sessionID, UIChatThreadStatus status); void chatSearchHit(int sessionID, ChatSearchHit searchHit); void chatSearchDone(int sessionID, int numHits); record UIChatSearchConvHit { ConvIDStr convID; TeamType teamType; string name; gregor1.Time mtime; } record UIChatSearchConvHits { array hits; boolean unreadMatches; } record UIChatSearchTeamHits { array hits; boolean suggestedMatches; } void chatSearchInboxStart(int sessionID); void chatSearchInboxHit(int sessionID, ChatSearchInboxHit searchHit); void chatSearchInboxDone(int sessionID, ChatSearchInboxDone res); void chatSearchIndexStatus(int sessionID, ChatSearchIndexStatus status); void chatSearchConvHits(int sessionID, UIChatSearchConvHits hits); void chatSearchTeamHits(int sessionID, UIChatSearchTeamHits hits); boolean chatConfirmChannelDelete(int sessionID, string channel); // Chat Stellar send confirm screen UI record UIChatPayment { string username; string fullName; string xlmAmount; union { null, string } error; union { null, string } displayAmount; } record UIChatPaymentSummary { string xlmTotal; string displayTotal; array payments; } void chatStellarShowConfirm(int sessionID); boolean chatStellarDataConfirm(int sessionID, UIChatPaymentSummary summary); boolean chatStellarDataError(int sessionID, keybase1.Status error); void chatStellarDone(int sessionID, boolean canceled); record GiphySearchResult { string targetUrl; string previewUrl; int previewWidth; int previewHeight; boolean previewIsVideo; } record GiphySearchResults { array results; string galleryUrl; } void chatGiphySearchResults(int sessionID, ConvIDStr convID, GiphySearchResults results); void chatGiphyToggleResultWindow(int sessionID, ConvIDStr convID, boolean show, boolean clearInput); void chatShowManageChannels(int sessionID, string teamname); enum UICoinFlipPhase { COMMITMENT_0, REVEALS_1, COMPLETE_2, ERROR_3 } record UICoinFlipErrorParticipant { string user; string device; } record UICoinFlipAbsenteeError { array absentees; } enum UICoinFlipErrorTyp { GENERIC_0, ABSENTEE_1, TIMEOUT_2, ABORTED_3, DUPREG_4, DUPCOMMITCOMPLETE_5, DUPREVEAL_6, COMMITMISMATCH_7 } variant UICoinFlipError switch (UICoinFlipErrorTyp typ) { case GENERIC: string; case ABSENTEE: UICoinFlipAbsenteeError; case TIMEOUT: void; case ABORTED: void; case DUPREG: UICoinFlipErrorParticipant; case DUPCOMMITCOMPLETE: UICoinFlipErrorParticipant; case DUPREVEAL: UICoinFlipErrorParticipant; case COMMITMISMATCH: UICoinFlipErrorParticipant; } enum UICoinFlipResultTyp { NUMBER_0, SHUFFLE_1, DECK_2, HANDS_3, COIN_4 } record UICoinFlipHand { string target; array hand; } variant UICoinFlipResult switch (UICoinFlipResultTyp typ) { case NUMBER: string; case SHUFFLE: array; case DECK: array; case HANDS: array; case COIN: bool; // heads? } record UICoinFlipParticipant { string uid; string deviceID; string username; string deviceName; string commitment; union { null, string } reveal; } record UICoinFlipStatus { FlipGameIDStr gameID; UICoinFlipPhase phase; string progressText; string resultText; string commitmentVisualization; string revealVisualization; array participants; union { null, UICoinFlipError } errorInfo; union { null, UICoinFlipResult } resultInfo; } void chatCoinFlipStatus(int sessionID, array statuses); record UICommandMarkdown { string body; union { null, string} title; } void chatCommandMarkdown(int sessionID, ConvIDStr convID, union { null, UICommandMarkdown } md); void chatMaybeMentionUpdate(int sessionID, string teamName, string channel, UIMaybeMentionInfo info); void chatLoadGalleryHit(int sessionID, UIMessage message); // Location support @typedef("uint64") @lint("ignore") record LocationWatchID {} enum UIWatchPositionPerm { BASE_0, ALWAYS_1 } LocationWatchID chatWatchPosition(int sessionID, ConversationID convID, UIWatchPositionPerm perm); void chatClearWatch(int sessionID, LocationWatchID id); // Slash command feedback enum UICommandStatusDisplayTyp { STATUS_0, WARNING_1, ERROR_2 } enum UICommandStatusActionTyp { APPSETTINGS_0 } void chatCommandStatus(int sessionID, ConvIDStr convID, string displayText, UICommandStatusDisplayTyp typ, array actions); enum UIBotCommandsUpdateStatusTyp { UPTODATE_0, UPDATING_1, FAILED_2, BLANK_3 } record UIBotCommandsUpdateSettings { map settings; } variant UIBotCommandsUpdateStatus switch (UIBotCommandsUpdateStatusTyp typ) { case UPTODATE: UIBotCommandsUpdateSettings; case UPDATING: void; case FAILED: void; case BLANK: void; } void chatBotCommandsUpdateStatus(int sessionID, ConvIDStr convID, UIBotCommandsUpdateStatus status); void triggerContactSync(int sessionID); }