React Native Chatbot UI Kit
dialogs_chatbotav_reactnative is a pre-built, themeable chat UI for React Native
— drop in EnxChatWidget or EnxChatScreen and get a complete
messaging experience backed by your EnableX Dialogs bot. It is not just a chat widget: the same
package can upgrade a conversation to a live audio or video call, including a
click-to-call handoff into a full native calling UI, so a single install covers both chat and
calling.
First release of the React Native Chatbot UI Kit, published on npm. See Release Notes for what's included.
View on NPMRequirements
| Requirement | Version |
|---|---|
| React | 18.0 or later |
| React Native | 0.76 or later (built and tested against 0.84) |
| iOS (native) | 15.0 or later |
| Android (native) | minSdkVersion 24 (Android 7.0) or later, compileSdk/targetSdk 35 |
| Node.js | 20.19.4+ recommended (the sample app targets Node 22) |
| Architecture | React Native New Architecture (Fabric/TurboModules) — mandatory on RN 0.82+ |
Installation
Install the SDK and its companion libraries
npm install dialogs_chatbotav_reactnative \
[email protected] \
react-native-image-picker \
@react-native-documents/picker \
@react-native-community/datetimepicker \
lucide-react-native \
react-native-markdown-display \
react-native-svg \
react-native-video
Pin react-native-webview to exactly 13.16.1. Versions 13.16.2 and later ship a TypeScript typing regression that breaks any code referencing the bare WebView type directly (for example useRef<WebView>()) — see Developer Troubleshooting.
Calling dependencies
Audio calls, video calls, and click-to-call are powered by three native modules working
together. All three are mandatory for calling — the feature does not work with only one
or two of them, even though react-native-webview is the only one of the three you
also install yourself:
| Package | Role in calling |
|---|---|
react-native-webview | Renders the in-app video overlay on Android and carries chat/call signaling between the bot page and native code. |
enx-rtc-react-native | The EnableX WebRTC engine — establishes and manages the actual audio/video media session (microphone, camera, network transport). |
enx-uikit-react-native | The EnableX native calling UI — the full native call screen shown for click-to-call / native UIKit sessions (participant view, mute/camera-switch/disconnect controls). |
enx-rtc-react-native and enx-uikit-react-native are installed automatically as dependencies of dialogs_chatbotav_reactnative — you do not add them to your own package.json. They still ship native Kotlin/Swift code, so the Android Gradle step below and a full native rebuild are required regardless.
enx-uikit-react-native additionally declares these as peer dependencies. Install them in your app if you use native (click-to-call / UIKit) video sessions:
npm install react-native-gesture-handler react-native-reanimated \
@react-navigation/native @react-navigation/stack
Minimum versions: react-native-gesture-handler ≥ 2.24.0, react-native-reanimated ≥ 4.2.0, @react-navigation/native and @react-navigation/stack ≥ 7.0.0.
iOS — CocoaPods
cd ios && pod install && cd ..
Rebuild the app after adding native modules (Xcode: Product › Clean Build Folder, then run).
Android — required Gradle configuration
Add the following block to your app-level android/app/build.gradle, inside the
dependencies section (or immediately above it). It excludes a duplicate legacy
library pulled in by enx-rtc-react-native that otherwise fails the build with a
“Duplicate class” error:
configurations.all {
exclude group: 'android.arch.lifecycle', module: 'extensions'
}
See Developer Troubleshooting if you hit build errors even after adding this — it covers two additional known issues and their fixes in detail.
Required Permissions MANDATORY
The chat and calling features rely on the OS permissions below. Declare only what your bot actually uses.
Android — AndroidManifest.xml
| Permission | Needed for |
|---|---|
INTERNET | Always — chat and media load over the network. |
CAMERA | Camera in video chat and photo/video attachments. |
RECORD_AUDIO | Microphone in audio and video calls. |
MODIFY_AUDIO_SETTINGS | Audio routing during calls. |
ACCESS_FINE_LOCATION / ACCESS_COARSE_LOCATION | Only if the bot uses location, or proactiveLocationPermission is enabled. |
Optional hardware flags, so the app can still install on devices without a camera or mic:
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
Full example manifest block:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<application ...>
...
</application>
</manifest>
Camera and microphone are requested when a video session starts from the chat. Location is requested on first use, or up front if you set proactiveLocationPermission={true} on the widget. If the user denies a permission, only the dependent feature is affected — text chat keeps working. On your main activity, android:windowSoftInputMode="adjustResize" keeps the message field visible above the keyboard.
iOS — Info.plist
| Key | Needed for |
|---|---|
NSCameraUsageDescription | Camera in video chat / capture. |
NSMicrophoneUsageDescription | Microphone in audio and video calls. |
NSLocationWhenInUseUsageDescription | Location features inside the chat. |
NSPhotoLibraryUsageDescription | Choosing photos to send in chat. |
NSPhotoLibraryAddUsageDescription | Saving images to the library (if your flow needs it). |
<key>NSCameraUsageDescription</key>
<string>Camera is used for video calls with the support agent.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone is used for audio and video calls with the support agent.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location may be used when the chat requests it.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access lets you attach images in chat.</string>
A missing Info.plist usage-description key crashes the app the moment that capability is used — not a silently-denied prompt. Use HTTPS for your Dialogs host in production; avoid broad “allow all HTTP” App Transport Security exceptions unless your security team requires them.
Credentials
From the EnableX / Dialogs console:
| Field | Description |
|---|---|
botId | Your bot identifier. |
host | Service base URL, e.g. https://dialogs.enablex.io |
Optional EnxBotConfig fields rootPath and callingEnabled — use only if your EnableX deployment guide says so.
Integration Steps
- Install the SDK and its companion libraries, pinning
react-native-webviewto exactly 13.16.1 (see Installation above). - Add the required Android manifest permissions and iOS Info.plist usage-description keys (see Required Permissions above).
- iOS: run
pod install. Android: add the Gradle exclusion forandroid.arch.lifecycle:extensions. - Render
EnxChatWidgetorEnxChatScreenwith yourbotId/host— see the Usage Example. - Set
showCallingOptionsif you want audio/video call buttons in the input bar; implementonAudioCall/onVideoCallto fully own the call UI, or let the widget handle bot-initiated calls automatically. - Do a full clean native rebuild any time the SDK or its native dependencies change version (Android:
./gradlew clean; iOS:pod install+ Clean Build Folder). - Test text chat, attachments, and calling on real iOS and Android devices — see Developer Troubleshooting if a native build fails.
Data Types & Enums
Import everything from the package root: import { EnxChatWidget, EnxChatController, /* ... */ } from 'dialogs_chatbotav_reactnative';
EnxBotConfig
Configuration passed to EnxChatController or the config prop of EnxChatWidget / EnxChatScreen.
| Field | Type | Required | Description |
|---|---|---|---|
botId | string | Yes | Your EnableX bot identifier. |
host | string | Yes | Dialogs service base URL, e.g. https://dialogs.enablex.io |
rootPath | string | No | Only set if your EnableX deployment guide specifies a custom root path. |
callingEnabled | boolean | No | Only set if your EnableX deployment guide specifies it. |
EnxMessageSender
Enum identifying who sent a message.
| Member | Value |
|---|---|
User | "user" |
Bot | "bot" |
EnxMessageType
| Member | Value |
|---|---|
Text | "text" |
Action | "action" |
Suggestion | "suggestion" |
Image | "image" |
File | "file" |
Video | "video" |
Typing | "typing" |
Calendar | "calendar" |
EnxSuggestionType
| Member | Value |
|---|---|
Single | "single" |
Multiple | "multiple" |
EnxConnectionStatus
Exposed as EnxChatController.status; drives the widget's connection banner.
| Member | Value | Meaning |
|---|---|---|
Idle | "idle" | Controller created but initialize() not yet called. |
Loading | "loading" | Initial connection in progress. |
Connected | "connected" | Chat is ready to send/receive. |
Disconnected | "disconnected" | Connection lost. |
Reconnecting | "reconnecting" | Automatic reconnect in progress. |
Error | "error" | Reconnect failed / unrecoverable error. |
EnxChoice
| Field | Type | Description |
|---|---|---|
title | string | Label shown to the user. |
value | string | Underlying value sent to the bot. |
isSelected | boolean? | Pre-selected state for multi-select choices. |
EnxAction
| Field | Type | Description |
|---|---|---|
title | string | Button label. |
url | string? | URL to open, if this action is a link. |
action | string? | Custom action identifier for your own handling. |
EnxMedia
| Field | Type | Description |
|---|---|---|
url | string? | Remote URL of the media. |
fileName | string | Display file name. |
mimeType | string | MIME type, e.g. image/png. |
localUri | string? | Local device URI, for outgoing attachments. |
size | number? | File size in bytes. |
EnxLinkCard
Rich link / company preview card rendered instead of a plain URL + file row.
| Field | Type | Description |
|---|---|---|
url | string | Destination URL. |
imageUrl | string? | Hero image. |
title | string? | Card title. |
description | string? | Card body text. |
buttonTitle | string? | Call-to-action button label. |
EnxMessageDisplayStyle
Type: 'default' | 'systemCentered'. When systemCentered, the message renders as a full-width centered notice chip instead of a side bubble (handover, agent assigned, dropped, etc.).
EnxMessage
The core chat message model. Every message the controller emits or accepts is shaped like this.
| Field | Type | Description |
|---|---|---|
id | string? | Message identifier, if provided by the bot. |
sender | EnxMessageSender | User or Bot. |
type | EnxMessageType | Text, Image, File, Video, Action, Suggestion, Typing, or Calendar. |
timestamp | Date | When the message was created. |
text | string? | Body text. |
subtitle | string? | Secondary line, if any. |
displayStyle | EnxMessageDisplayStyle? | Render as a centered system notice instead of a bubble. |
handoverStatus | string? | Raw handover state from the bot payload. |
media | EnxMedia? | Attached image, file, or video. |
linkCard | EnxLinkCard? | Renders a link preview card instead of a raw URL row. |
choices | EnxChoice[]? | Selectable suggestion chips. |
actions | EnxAction[]? | Action buttons. |
suggestionType | EnxSuggestionType? | Single or Multiple selection mode for choices. |
EnxChatTheme & default themes
| Field | Type | Description |
|---|---|---|
primaryColor | string | Accent color (header, buttons, links). |
userBubbleColor | string | Background color of the current user's message bubbles. |
botBubbleColor | string | Background color of the bot's message bubbles. |
backgroundColor | string | Chat list background. |
userAvatarColor | string | User avatar background. |
botAvatarColor | string | Bot avatar background. |
useMobileClassicLayout | boolean | Switches bubble/layout style to match the EnableX mobile web chat. |
Two ready-made theme constants are exported:
defaultTheme— WhatsApp-style green theme.mobileClassicTheme— matches the EnableX mobile web chat look.
Components
EnxChatWidget
The primary embeddable chat UI. Renders the message list, input bar, connection banner, and (on Android) the hidden WebView bridge or video overlay.
<EnxChatWidget config={{ botId, host }} theme={mobileClassicTheme} />
| Prop | Type | Description |
|---|---|---|
config | EnxBotConfig? | Required if controller is not passed. Bot id + host. |
controller | EnxChatController? | Bring your own controller. If omitted, the widget creates and disposes one automatically. |
theme | Partial<EnxChatTheme>? | Overrides merged onto defaultTheme. |
showCallingOptions | boolean? | Default false. Shows audio/video buttons in the input bar. |
onMessageReceived | (message: EnxMessage) => void | Fired for every inbound message. |
onMessageSent | (message: EnxMessage) => void | Fired for every outbound message. |
onError | (message: string, type: string) => void | Connection or chat errors. |
onBotInfo | (info: Record<string, unknown>) => void | Bot metadata, when available. |
onAudioCall | () => void | User tapped the audio-call button (you own the call UI). |
onVideoCall | () => void | User tapped the video-call button (you own the call UI). |
onVideoCallRequest | (url: string) => void | Bot started a video session. The widget also opens its own full-screen presentation unless you fully own the flow. |
onVideoCallEnded | () => void | Bot ended the video session; the widget's own overlay is already closed by this point. |
onNativeUIKitRequest | (roomToken: string) => void | Bot handed off to a native EnableX UIKit room. |
proactiveLocationPermission | boolean? | Android only, default false. Requests location once on mount instead of waiting for the page to ask. |
EnxChatScreen
A full-screen wrapper around EnxChatWidget with a header (title + optional back button).
| Prop | Type | Description |
|---|---|---|
title | string? | Default "EnX Support". Header title text. |
onBack | () => void | Shows a back button when provided. |
config | EnxBotConfig? | Same as EnxChatWidget. |
controller | EnxChatController? | Same as EnxChatWidget. |
theme | Partial<EnxChatTheme>? | Same as EnxChatWidget. |
showCallingOptions | boolean? | Same as EnxChatWidget. |
ChatList
The scrolling message list used internally by EnxChatWidget. Exported for advanced/custom layouts.
| Prop | Type | Description |
|---|---|---|
messages | EnxMessage[] | Messages to render, oldest first. |
isTyping | boolean | Shows the typing indicator at the bottom. |
theme | EnxChatTheme | Full (non-partial) theme. |
onSuggestionTap | (titles: string[], type: EnxSuggestionType) => void | User tapped a suggestion chip. |
onActionTap | (action: EnxAction) => void | User tapped an action button. |
Accepts a ref of type ChatListHandle, exposing scrollToBottom(animated: boolean): void.
MessageCell
Renders a single message bubble (text, image, video, file, suggestions, actions, or calendar prompt). Exported for custom list implementations.
| Prop | Type | Description |
|---|---|---|
message | EnxMessage | The message to render. |
theme | EnxChatTheme | Full theme. |
onSuggestionTap | (titles: string[], type: EnxSuggestionType) => void | Optional. |
onActionTap | (action: EnxAction) => void | Optional. |
InputBar
The bottom text field, attachment picker, and audio/video call buttons.
| Prop | Type | Description |
|---|---|---|
theme | EnxChatTheme | Full theme. |
enabled | boolean | Disables input while the connection is not ready. |
showCallingOptions | boolean? | Shows the audio/video buttons. |
onSendText | (text: string) => void | User submitted text. |
onSendFile | (payload) => void | User picked a camera, gallery, or document attachment. |
onAudioCall | () => void | Audio call button tapped. |
onVideoCall | () => void | Video call button tapped. |
TypingBubble
Three-dot animated typing indicator.
| Prop | Type | Description |
|---|---|---|
color | string | Dot color. |
ChatMarkdown
Renders bot message text with markdown formatting (links, emphasis, lists).
| Prop | Type | Description |
|---|---|---|
content | string | Markdown source text. |
theme | EnxChatTheme | Full theme — drives link/accent color. |
variant | ChatMarkdownVariant | 'body' | 'subtitle' | 'title' | 'linkTitle' | 'linkDesc' | 'button' | 'compact' |
containerStyle | object? | Extra wrapper style, e.g. horizontal padding. |
textColor | string? | Overrides the default text/link color (e.g. for choice chips). |
EnxChatController
A framework-agnostic connection and message controller. EnxChatWidget creates one internally if you do not supply your own; you can also own an instance yourself and drive fully custom UI off it.
Constructor
new EnxChatController(config: EnxBotConfig)
Properties (read-only getters)
| Property | Type | Description |
|---|---|---|
messages | EnxMessage[] | All messages in the current conversation, oldest first. |
status | EnxConnectionStatus | Current connection state. |
isConnected | boolean | Shorthand for status === Connected. |
isTyping | boolean | True while the bot is composing a reply. |
botInfo | Record<string, unknown> | undefined | Last bot-info payload received. |
conversationId | string | undefined | Current conversation identifier, once assigned. |
errorMessage | string | undefined | Last error message, if any. |
bridge | EnxWebViewBridge | Underlying platform bridge (advanced use — see Advanced). |
Event callbacks (assign directly)
| Callback | Signature | Fires when |
|---|---|---|
onMessageReceived | (message: EnxMessage) => void | A new message arrives. |
onStatusChanged | (status: EnxConnectionStatus) => void | Connection status changes. |
onError | (message: string, type: string) => void | A connection or chat error occurs. |
onBotInfoReceived | (info: Record<string, unknown>) => void | Bot metadata is received. |
onVideoCallRequest | (url: string) => void | Bot sends a video-room URL (audio_video_action: start). |
onVideoCallEnd | () => void | Bot sends audio_video_action: stop. |
onNativeUIKitRequest | (roomToken: string) => void | Bot hands off to a native EnableX UIKit room. |
Methods
| Method | Signature | Description |
|---|---|---|
initialize | (): Promise<void> | Starts the connection. Called automatically by EnxChatWidget. |
sendText | (text: string): Promise<void> | Sends a text message; queued until the connection is ready. |
sendSuggestions | (titles: string[], type: EnxSuggestionType): Promise<void> | Sends one or more selected suggestion chips. |
sendChoice | (choice: EnxChoice): Promise<void> | Convenience wrapper for a single-select choice. |
sendMultiChoice | (choices: EnxChoice[]): Promise<void> | Convenience wrapper for multi-select choices. |
sendFile | (data: {base64, fileName, mimeType, localUri?, size?}): Promise<void> | Sends an attachment; queued until the connection is ready. |
resetConversation | (): Promise<void> | Clears local messages and asks the backend to start a new conversation. |
reconnect | (): Promise<void> | Manually retries the connection. |
clearMessages | (): void | Clears local messages only (no backend call). |
dispose | (): Promise<void> | Tears down the connection and listeners. Call this when you own the controller yourself. |
subscribe | (listener: () => void): () => void | Low-level subscription used internally by useControllerVersion; returns an unsubscribe function. |
Hooks
useControllerVersion
function useControllerVersion(controller: EnxChatController): number
Subscribes a component to an EnxChatController and forces a re-render whenever its state changes. Returns an incrementing version number (the value itself is not meaningful — only the fact that it changed).
const version = useControllerVersion(controller);
// component re-renders on every controller.messages / status / isTyping change
Media & Permission Helpers
cachedImageSource
function cachedImageSource(uri: string): ImageURISource
Returns an Image source. Remote HTTP(S) URLs get { cache: 'default' } so the platform HTTP cache (honoring Cache-Control from the server) is used; local/data URIs pass through unchanged.
cachedVideoSource
function cachedVideoSource(uri: string): { uri: string; isNetwork?: boolean; shouldCache?: boolean }
Returns a react-native-video source. Remote HTTP(S) URLs get isNetwork: true and shouldCache: true for disk-cached repeat playback; local/content URIs pass through unchanged.
requestCameraAndMicrophoneForMedia
function requestCameraAndMicrophoneForMedia(): Promise<void>
Android only (no-op on iOS, where the system prompt is triggered automatically). Requests CAMERA and RECORD_AUDIO together. Called automatically by EnxChatWidget immediately before a video call starts; denial is silent — the video UI may still open and show its own message.
requestLocationForWebView
function requestLocationForWebView(): Promise<void>
Android only. Requests ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION together. Call this yourself only if you opted into proactiveLocationPermission on the widget; otherwise the WebView requests location natively when the chat page calls navigator.geolocation.
Message Parsing Utilities
Lower-level helpers used internally to interpret the raw bridge payload. Most integrations do not need to call these directly — EnxChatController already applies them.
parseBridgeMessage
function parseBridgeMessage(rawData: unknown): EnxMessage[]
Converts a raw bridge payload into zero or more EnxMessage objects.
extractVideoCallUrl
function extractVideoCallUrl(rawData: unknown, botDisplayName?: string): string | undefined
Extracts a video-room URL from a raw bridge payload, if present.
extractVideoCallRoomToken
function extractVideoCallRoomToken(rawData: unknown): string | undefined
Extracts a native EnableX UIKit room token from a raw bridge payload, if present.
isAudioVideoStopPayload
function isAudioVideoStopPayload(rawData: unknown): boolean
True if the payload represents the bot ending an audio/video session (audio_video_action: stop).
EnxWebViewBridge
The platform bridge that connects the chat page to native code — a hidden WebView on Android, or the native EnxChatBridge module on iOS. Accessed via controller.bridge. Most apps never need to call this directly; it is documented here for advanced integrations that fully replace the default widget UI.
| Member | Type | Description |
|---|---|---|
usesNativePath | boolean | True on iOS when the native EnxChatBridge module is available (WKWebView is owned natively, not by React Native). |
attachWebViewRef | (ref) => void | Android only. Attaches the hidden WebView ref so the bridge can inject JavaScript into it. |
initializeAfterPageLoad | (): void | Android only. Call from the WebView's onLoadEnd. |
initializeNative | (): void | iOS only. Starts the native bridge module. |
resetWebViewSession | (): void | Resets bridge state so the next mount re-initializes cleanly. |
formatMultiSuggestionWireText
function formatMultiSuggestionWireText(values: string[]): string
Formats a list of selected multi-suggestion titles into the JSON-array wire text the bot echoes back. Used internally to de-duplicate the echo against the locally-rendered user message.
Usage Example
Simplest — pass config directly
The widget creates and owns its own EnxChatController, and disposes it automatically when it unmounts.
import React from 'react';
import { View } from 'react-native';
import { EnxChatWidget, mobileClassicTheme } from 'dialogs_chatbotav_reactnative';
export function SupportChat() {
return (
<View style={{ flex: 1 }}>
<EnxChatWidget
config={{
botId: 'YOUR_BOT_ID',
host: 'https://dialogs.enablex.io',
}}
theme={mobileClassicTheme}
/>
</View>
);
}
Own the controller yourself
Use EnxChatController when you need one instance for longer than a single screen, or want to wire extra app logic around it. Call dispose() when you are done — typically in a useEffect cleanup function.
import React, { useEffect, useRef } from 'react';
import { View } from 'react-native';
import { EnxChatController, EnxChatWidget, mobileClassicTheme } from 'dialogs_chatbotav_reactnative';
export function SupportChat() {
const controllerRef = useRef(
new EnxChatController({
botId: 'YOUR_BOT_ID',
host: 'https://dialogs.enablex.io',
}),
);
useEffect(() => {
const c = controllerRef.current;
return () => { void c.dispose(); };
}, []);
return (
<View style={{ flex: 1 }}>
<EnxChatWidget controller={controllerRef.current} theme={mobileClassicTheme} />
</View>
);
}
Full screen with a title bar and back button
import { EnxChatScreen, mobileClassicTheme } from 'dialogs_chatbotav_reactnative';
<EnxChatScreen
title="Support"
onBack={() => { /* e.g. navigation.goBack() */ }}
config={{ botId: 'YOUR_BOT_ID', host: 'https://dialogs.enablex.io' }}
theme={mobileClassicTheme}
showCallingOptions
/>
Audio / video calling from the chat bar
Set showCallingOptions to show call actions in the input bar. Implement
onAudioCall and onVideoCall to open your own calling flow if you want
to override the default behavior. When the bot itself starts a video session, the widget
requests camera/microphone permission and opens the call automatically — as a full-screen
native view on iOS, or a WebView / native UIKit overlay on Android — unless you handle
onVideoCallRequest yourself.
This entire flow — audio calls, video calls, and click-to-call handoff to a native room
— runs on top of enx-rtc-react-native (the WebRTC media engine) and
enx-uikit-react-native (the native call screen), with react-native-webview
carrying signaling and rendering the Android in-app overlay. All three must be present and
correctly built for calling to work; see Calling dependencies
above, and Developer Troubleshooting if a build fails.
Widget Configuration Reference
The most commonly used EnxChatWidget props — see Components above for the complete, exhaustive reference.
| Prop | Description |
|---|---|
config | Bot id and host — required if you do not pass controller. |
controller | Your own EnxChatController. If omitted, the widget builds one from config. |
theme | mobileClassicTheme, defaultTheme, or your own partial theme object. |
showCallingOptions | Show audio/video actions; use with onAudioCall / onVideoCall. |
onBotInfo | Called with bot metadata (e.g. display name) when available. |
onMessageReceived / onMessageSent | Fired when messages arrive or are sent. |
onError | Connection or chat errors (message, type). |
onVideoCallRequest | Bot started a video session; handle the URL yourself, or rely on the default full-screen presentation. |
onVideoCallEnded | Bot ended the video session. |
proactiveLocationPermission | Android only, default false. If true, location is requested when the chat opens instead of waiting until it is needed. |
Feature Support (v1.0.0)
| Feature | Supported | Notes |
|---|---|---|
| Drop-in chat components | Yes | EnxChatWidget (embeddable) and EnxChatScreen (full screen with title bar and back button). |
| Rich message types | Yes | Text, images, video, files, calendar prompts, single/multi-select suggestions, and action buttons. |
| Markdown rendering | Yes | Links, emphasis, and lists inside bot messages via ChatMarkdown. |
| Rich link/company preview cards | Yes | Rendered for URLs shared by the bot via EnxLinkCard. |
| Typing indicator & system notices | Yes | Day separators and WhatsApp-style centered system notices (handover, agent assigned, etc.). |
| Theming | Yes | Two ready-made color themes (defaultTheme, mobileClassicTheme) plus full theme overrides. |
| Attachments | Yes | Camera, gallery, or document picker; HTTP-cache-aware image loading and disk-cached video playback for repeat views. |
| Message de-duplication | Yes | Automatic de-duplication of echoed user messages coming back from the bot connection. |
| Audio/video calling | Yes | Call entry points in the input bar (showCallingOptions, onAudioCall, onVideoCall). |
| Bot-initiated video sessions | Yes | Full-screen native video call on iOS, in-app WebView overlay on Android, or a native EnableX UIKit room view for click-to-call handoff. |
| Automatic call permission requests | Yes | Camera/microphone permission requested immediately before a call starts. |
| Framework-agnostic controller | Yes | EnxChatController can be owned and driven independently of the widget UI. |
| Full TypeScript types | Yes | Every exported component, hook, and data model is fully typed. |
| UI customization API | No | Not available in v1.0 — theming covers colors/layout only, not structural customization. |
Known Issues in Upstream Dependencies
These are pre-existing issues in third-party packages this SDK depends on. They are documented here so you are not blocked by them — fixes for each are covered in Developer Troubleshooting below.
- Android build fails with a CMake “add_subdirectory” error. On React Native New Architecture builds,
enx-uikit-react-native's Android build script incorrectly registers itself for native TurboModule/Fabric codegen even though it ships no codegen spec files. See fix. - Android build fails with “Duplicate class” errors.
enx-rtc-react-nativepulls in the long-abandonedandroid.arch.lifecycle:extensionslibrary, whose classes duplicate ones already shipped by AndroidX. See fix. - TypeScript error referencing
react-native-webview'sWebViewtype. Versions 13.16.2+ ship a typing regression that breaks any code referencing the bareWebViewtype. This SDK pins to 13.16.1. See fix.
Breaking changes: none — this is the first public release.
Developer Troubleshooting
Android build fails: CMake “add_subdirectory” error mentioning enx-uikit-react-native
Cause: enx-uikit-react-native's Android build script registers the module for New Architecture codegen even though it ships no codegen spec files, which breaks the native build:
CMake Error ... add_subdirectory given source
".../node_modules/enx-uikit-react-native/android/build/generated/source/codegen/jni/"
which is not an existing directory.
Fix — install patch-package and remove the offending Gradle block:
- Install
patch-packageas a dev dependency:npm install -D patch-package - Open
node_modules/enx-uikit-react-native/android/build.gradleand delete this block entirely (do not just comment it out — see the note below):if (isNewArchitectureEnabled()) { react { jsRootDir = file("../src/") libraryName = "EnxUikitReactNative" codegenJavaPackageName = "com.enxuikitreactnative" } }
Delete the lines outright rather than commenting them out. React Native's autolinking scans this file with a plain text regex that still matches a commented-out libraryName line.
- Generate a patch and wire it to auto-apply on every install:
npx patch-package enx-uikit-react-native # add to package.json scripts: "postinstall": "patch-package" - Commit the generated
patches/folder to version control. - Clean the stale autolinking cache and rebuild:
rm -rf android/build android/app/build android/app/.cxx cd android && ./gradlew :app:assembleDebug
Android build fails: “Duplicate class” errors mentioning support-compat
Cause: enx-rtc-react-native depends on the long-abandoned android.arch.lifecycle:extensions library, whose classes duplicate ones already provided by AndroidX.
Fix: add this exclusion to your app-level android/app/build.gradle (see Installation):
configurations.all {
exclude group: 'android.arch.lifecycle', module: 'extensions'
}
TypeScript error: “No overload matches this call” on <WebView />
Cause: react-native-webview 13.16.2 and later ship a typing regression — the WebView class's generic default became undefined instead of {}, which makes WebViewProps & undefined resolve to never for any code referencing the bare WebView type (for example useRef<WebView>()).
Fix: pin react-native-webview to exactly 13.16.1 in your app's package.json:
"react-native-webview": "13.16.1"
Then reinstall so the exact version resolves in your lockfile:
npm install [email protected] --save-exact
“Install via USB” / INSTALL_FAILED_USER_RESTRICTED on Android
Cause: some OEM Android skins (Xiaomi/MIUI, Samsung, Vivo, Oppo, etc.) block sideloaded installs unless an extra developer option is enabled.
Fix: on the device, enable Settings → Developer options → Install via USB, then retry.
Before You Ship
- Confirm
botIdandhostpoint at your production EnableX / Dialogs environment. - Match permissions and iOS usage descriptions to what your bot actually uses (see Required Permissions).
- Test on real Android and iOS devices: text chat, attachments, location, and video if you enable those flows.
- Prefer HTTPS for your Dialogs host; avoid overly broad ATS or cleartext exceptions in production unless required.
- Do a full clean native rebuild (Android:
./gradlew clean; iOS:pod install+ Clean Build Folder) any time the SDK or its native dependencies change version.