ebchat library
Embeddable ebchat chat SDK for Flutter, on the first-party livechat protocol.
See ebchat-sdk-protocol-v1.md. Re-exports ebchat_core, so a host imports
only package:ebchat/ebchat.dart.
Classes
- Attachment
-
A message attachment. Covers raw media (image/video/file/voicenote), the
botflow
choicestype (carrying actions),catalogue(carrying products) and botflow content variants. Backed by the raw map so unknown/forward-compat fields survive. §4. - BootstrapConfig
- Public branding + config for a company widget. Mirrors protocol §2.1.
- BootstrapFeatures
- BootstrapLimits
- CartLine
- One product line in the local cart.
- CatalogPage
-
One page of the guest catalog (
GET /livechat/v1/catalog). - CatalogProduct
-
A sellable product as the guest sees it — in a
catalogueattachment, the catalog browser (GET /catalog), or a cart line. Wire shape is snake_case (product_retailer_id,image_url); botflow-node copies may carry camelCase (imageUrl) — both parse. - ChoiceAction
-
A botflow choice/form action. Kept deliberately map-backed and opaque: the
idpayload (a WhatsappButtonId) encodes team / dispatch / branch routing that the client must echo VERBATIM, never reconstruct. Mirrors protocol §4.1. - ChoiceReply
- ConversationClosedEvent
- EbChat
- Entry point for embedding ebchat in a Flutter app. One instance per company.
- EbchatAssets
- Assets shipped inside this package.
- EbchatAttachmentTray
- Horizontal strip of pending attachments above the composer, each removable.
- EbChatBackground
- Protocol §6: background push handling without a live EbChat instance.
- EbChatBackgroundResult
- What EbChatBackground.handleMessage resolved for a background push: everything the host needs to render a local notification and route a tap.
- EbchatCart
-
WhatsApp-style local cart: products accumulate client-side and get submitted
as ONE order message at checkout (
controller.sendOrder). Keyed by retailer id; adding an existing product bumps its quantity. - EbchatCatalogueCard
-
WhatsApp-style product-list card for a
catalogueattachment: a header with the menu name, up to three product rows (thumbnail, name, price, add button), and a "view all" action that opens the full list. - EbchatChatView
- The complete guest chat surface for one conversation: scrolling transcript (bubbles, botflow choices, product/catalogue cards, order receipts), date separators, typing indicator, closed-state banner, and the composer over a WhatsApp-style wallpaper. Renders an EbchatConversationController; the host owns the controller's lifecycle (start/dispose).
- EbchatChoices
-
Renders the button/form actions of a botflow
choicesmessage. Buttons echo the tapped ChoiceAction verbatim via onChoice; a;cancelaction gets secondary styling. Form actions (type == 'form') are labeled by what they ask for (type an answer / share location / upload a photo / attach a file) and surfaced via onForm so the host opens the matching native input. - EbchatComposer
- Message input row: text field + send button, with optional attach/voice hooks the host wires up. Emits typing start/stop as the field gains/loses content so the controller can broadcast it. Pass a focusNode to focus the field programmatically (e.g. a "type your answer" form button).
- EbchatConversationController
- EbChatFormRequest
- A botflow form question handed to a host picker.
- EbchatMessageBubble
-
Renders a single message as a chat bubble. Guest messages align to the
trailing edge with the primary colour; bot/operator to the leading edge.
Text, image, video, voice-note and location attachments render inline;
choicesattachments are handled separately by EbchatChoices, product / catalogue / order messages by their dedicated cards. A quoted reply shows the quoted snippet block above the content. - EbchatOrderBubble
-
Receipt-style bubble for a submitted order (
message.order) — the guest's cart rendered like WhatsApp renders an order message. - EbchatPendingAttachment
- Something the guest has picked or recorded but not sent yet.
- EbChatPickedFile
- A file chosen by the host's picker, ready to upload.
- EbchatProductCard
-
WhatsApp-style single-product card: image, name, price pill, short
description, and an Add-to-Cart action inside the card. Rendered for
botflow product messages (
message.isProductCard). - EbChatPush
- A parsed ebchat push (the FCM data-message payload, protocol §6). The host app owns Firebase — "notification outsourcing" — and passes the raw data map to EbChatPush.parse; ebchat never depends on firebase_messaging itself.
- EbchatQuoteBlock
- The WhatsApp-style quote block: accent bar + author + snippet. Rendered inside a bubble (above the content) and in the composer reply bar.
- EbChatScreen
- Drop-in chat screen. Opens (or resumes) the guest conversation for chat, renders it with the company's theme + language, and transparently opens a fresh conversation when the current one is closed by an operator.
- EbChatScreenState
- Public à la ScaffoldState: hosts that draw their own chrome reach the commerce surface through a GlobalKey.
- EbchatStrings
- Minimal en/ar string set for the guest chat surface. A small, complete bundle — enough to run the widget; a host can supply overrides.
- EbchatTheme
- Visual configuration for the chat widgets, derived from the backend BootstrapConfig (primary color, mascotte, powered-by) with sensible defaults. Host apps may override any field.
- EbchatThemeScope
- Inherited access to the active EbchatTheme.
- EbChatUser
- The end user of the host app as seen by ebchat.
- GeoLocation
- A geographic location as exchanged over the livechat protocol (flat lat/long/label). The backend keys it as pin_lat/pin_long internally; the wire shape the client sees and sends is this. Mirrors §2.6 / §3.2.
- GeoLocationRef
-
Small concrete GeoLocation used by
sendLocationwithout importing the model into call sites. - Guest
- Identity of an authenticated guest.
- GuestIdentity
-
Optional host-supplied identity for the mobile SDK (verified via HMAC when
the company enables it). Mirrors the
identityfield of §2.2. - InlineAudioPlayer
- Inline voice-note player: play/pause, a seekable waveform, and elapsed time.
- InMemorySessionStore
- Non-persistent default. A real host supplies a durable implementation.
- LivechatApiClient
-
Thin, stateless transport over the
/livechat/v1REST API (protocol §2). Holds no session — callers pass the embed key (bootstrap/session) or a guest token (everything else). Higher-level session/token lifecycle lives inEbchatCoreClient. - LivechatConversation
- A guest conversation. Mirrors protocol §3.1.
- LivechatMessage
-
A single message. Mirrors protocol §3.2 and is the shape delivered by both
the REST transcript and the realtime
message.createdevent, so one parser serves both. - LivechatOrder
-
A submitted order carried on a message (
message.order) — rendered as an order-summary bubble on the guest side. - LivechatRealtime
- Transport for the per-conversation realtime channel. The default is polling (EbchatConversationController handles that internally when no transport is supplied); a Pusher/Soketi implementation of this interface can be dropped in without touching the controller.
- LivechatSession
-
Result of
POST /session. Mirrors protocol §2.2. - Mascotte
- MessageCreatedEvent
- MessageSender
- MessageUpdatedEvent
- A message changed — e.g. an answered choices menu had its buttons cleared. Carries the message id + the fields that changed (may be partial).
- OrderItem
-
A line in a guest cart submission. Mirrors the WhatsApp
order.product_itemswire shape so the backend order engine consumes it unchanged. - OrderReply
- PusherConfig
-
Pure helpers for the Pusher wire protocol — no I/O, so they are unit-tested
directly. The backend triggers events as
trigger(channel, eventName, { eventName, eventId, data }), which arrives at the client as a frame{ event, channel, data: "<json>" }where the stringifieddatais that body. The guest payload we care about is its inner.data. Config for connecting to a Pusher-compatible server (hosted Pusher or self-hosted Soketi). For Soketi supply host/port; for hosted Pusher use the cluster host and 443. authUrl is the gateway's/pusher/auth. - PusherLivechatRealtime
-
A LivechatRealtime over the Pusher WebSocket protocol (hosted Pusher or
self-hosted Soketi). Connects, authorizes the private
private-livechat-<conversationId>channel against the gateway's/pusher/authwith the guest JWT, subscribes, and maps events. On any error the stream simply ends — EbchatConversationController should be configured to fall back to polling, or the host can reconnect. - RealtimeConfig
- Pusher/Soketi connection params advertised by bootstrap (§2.1).
- RealtimeEvent
- A guest-facing realtime event on a conversation channel (protocol §5).
- SendMessageRequest
- A guest outbound message. Exactly one of text / attachments / location / choice / order is populated (protocol §2.6). Use the named constructors. quotedMessageId turns the send into a quoted reply (WhatsApp-style).
- SessionStore
- Persists the guest session so a returning visitor resumes and a background isolate (mobile push) can reconnect. Implementations back this with localStorage (web), secure storage (mobile), or memory (tests).
- TypingEvent
Enums
- ConversationStatus
- EbChatFormKind
- What a botflow form question is asking the guest for.
- EbchatPendingStatus
- Where a queued attachment is in its life.
- LivechatConnectionState
- Drives a single guest conversation: message state, optimistic send with idempotent de-dupe, pagination, read/typing, and live updates via either an injected LivechatRealtime transport or built-in polling.
- LivechatDeliveryStatus
- Sender-side progress of one message, newest state last.
- SenderType
-
Who authored a message. Mirrors protocol §3.2
sender.
Functions
-
detectTextDirection(
String text) → TextDirection? - Best-effort base direction for USER CONTENT: the first strong character wins (how WhatsApp lays out mixed-language bubbles). Null → no strong character (digits/emoji only) → inherit the ambient direction.
-
formatDateLabel(
DateTime date, {required DateTime now, required String today, required String yesterday, bool arabic = false}) → String - Date-separator label: Today / Yesterday / "9 Jul 2026".
-
formatMoney(
num value, String? currency) → String - "12 QAR" (or just the number when no currency is known).
-
formatPrice(
num value) → String -
12-> "12",6.5-> "6.5",6.50-> "6.5" — price without trailing zeros. -
formatShortDate(
DateTime date, {bool arabic = false}) → String - Day + month, for timestamps older than a week ("9 Jul").
-
formatTime(
DateTime time) → String - hh:mm in the local timezone for in-bubble timestamps.
-
formatWeekday(
DateTime date, {bool arabic = false}) → String - Short weekday for timestamps inside the past week.
-
productFromAddToCart(
ChoiceAction action, {String? name, String? imageUrl, String? description}) → CatalogProduct - Build the product a botflow Add-to-Cart action refers to, joining the action's routing payload (retailer id, price, currency) with the visuals of the message that carried it (name from the card text, image attachment).
-
quoteAuthor(
LivechatMessage m, EbchatStrings strings) → String - Display name for a quoted message's author ("You" for the guest's own).
-
quoteSnippet(
LivechatMessage m, EbchatStrings strings) → String - One-line preview of a message for quote blocks and the composer reply bar: text (truncated) or a typed placeholder ("📷 Photo", "📍 Location", …).
-
showEbchatCartSheet(
{required BuildContext context, required EbchatCart cart, required EbchatTheme theme, required EbchatStrings strings, required Future< void> onSubmit()}) → Future<void> -
Bottom-sheet cart: lines with quantity steppers, total, and a Send-order
button. Returns via
onSubmit; the host sends the order message and clears the cart on success. -
showEbchatCatalogBrowser(
{required BuildContext context, required EbchatTheme theme, required EbchatStrings strings, required EbchatCatalogLoader loader, required void onAddToCart(CatalogProduct product, int quantity), List< CatalogProduct> ? seed, String? title, EbchatCart? cart, VoidCallback? onOpenCart}) → Future<void> - Full-height catalog browser (the WhatsApp storefront view): searchable, paginated product grid; tapping a product opens a detail pane with a quantity stepper and Add to cart.
-
showEbchatFullscreenImage(
{required BuildContext context, required String url, String? title}) → Future< void> - Full-screen image viewer: pinch/double-tap to zoom, drag to pan, tap or swipe down to dismiss.
-
stripHtml(
String input) → String -
Strip HTML tags/entities from backend-sourced rich text (product
descriptions arrive as
<p>…</p>fragments).
Typedefs
-
EbChatAttachmentPicker
= Future<
EbChatPickedFile?> Function() - Opens the native picker for the composer's attach button. Unlike EbChatFilePicker this answers no particular question — the guest just wants to send something — so it takes no request. Return null when they cancel. EbChatScreen uploads and sends whatever comes back.
-
EbChatAttachmentsPicker
= Future<
List< Function()EbChatPickedFile> > - Multi-select variant: return every file the guest picked (empty = cancel). Preferred over EbChatAttachmentPicker — five photos of a broken product should be one gallery visit, not five.
-
EbchatCatalogLoader
= Future<
CatalogPage> Function({int offset, String? query}) -
Loads one page of the company catalog. Wired to
LivechatApiClient.getCatalogby the host. -
EbChatFilePicker
= Future<
EbChatPickedFile?> Function(EbChatFormRequest request) - Opens the native picker for a media form question. Return null when the guest cancels — nothing is sent and the question stays pending.
-
EbChatLocationResolver
= Future<
GeoLocation?> Function() - Resolves the device's position for a location form question. Return null when permission is denied or no fix is available; the guest is then invited to type their address instead.
-
EbChatRecordCancel
= Future<
void> Function() - Aborts recording and throws the audio away — the guest cancelled.
-
EbChatRecordPause
= Future<
void> Function() - Holds a recording without ending it. Pair with EbChatRecordResume; supply both and the recording bar gains a pause button.
-
EbChatRecordResume
= Future<
void> Function() - Continues a held recording, appending to the same clip.
-
EbChatRecordStart
= Future<
bool> Function() - Starts recording a voice note. Return false when the microphone is refused or unavailable; the composer then stays in its normal text state.
-
EbChatRecordStop
= Future<
EbChatPickedFile?> Function(Duration elapsed) - Stops recording and returns the captured audio, or null to discard it (a recording too short to be worth sending, say). EbChatScreen uploads it as a voicenote and sends it.
-
EbchatVoiceAmplitude
= Stream<
double> Function() - Live input level, 0..1. Drives the recording waveform; without it the bar falls back to a static pattern, since a flat line looks like a dead mic.
-
EbchatVoiceCancel
= Future<
void> Function() - Discard the capture.
-
EbchatVoicePause
= Future<
void> Function() - Hold capture, keeping what has been recorded so far.
-
EbchatVoiceResume
= Future<
void> Function() - Continue a paused capture, appending to the same recording.
-
EbchatVoiceStart
= Future<
bool> Function() - Starts audio capture; false → permission denied / unavailable (stay idle).
-
EbchatVoiceStop
= Future<
void> Function(Duration elapsed) -
Finalize the capture and deliver it (upload + send) —
elapsedstamps the voice note's duration.
Exceptions / Errors
- LivechatApiException
-
Thrown on a non-2xx livechat API response. code is the stable machine
code from the error envelope (protocol §7), e.g.
conversation_closed,invalid_or_expired_token.