@contegris/rn-intellicon-chat-sdk-expo
v1.1.1
Published
Intellicon Chat SDK - Expo adapter (full media support with Expo native modules)
Readme
@contegris/rn-intellicon-chat-sdk-expo
Full-featured chat SDK for Expo with complete media support
Built on expo-audio, expo-video, expo-image-picker, and more.
Overview
The Expo package extends the core SDK with full media support using Expo native modules. Perfect for Expo managed workflow projects that need audio recording, video playback, document handling, and more.
When to Use This Package
✅ Use Expo Package if:
- You're using Expo managed workflow (SDK 51+)
- You need media attachments (images, videos, audio, documents)
- You want easy configuration via config plugins
- You're building a development build (not Expo Go)
❌ Don't use Expo Package if:
- You're using React Native CLI → Use
@contegris/rn-intellicon-chat-sdk-cli - You only need text → Use
@contegris/rn-intellicon-chat-sdk - You're using Expo Go → This package requires development build
Features
All Core Features +
- ✅ Audio Recording with live waveform animation (28 bars)
- ✅ Audio Playback with seek controls and waveform visualization
- ✅ Image Capture via camera with quality controls
- ✅ Image Selection from gallery with multi-select
- ✅ Video Capture and playback with fullscreen modal
- ✅ Document Picker for any file type
- ✅ Emoji Keyboard with custom theme support
- ✅ Upload Progress tracking with cancel/retry
- ✅ Reliable Audio Playback with
AVAudioPlayerDelegatefor accurate completion detection - ✅ File Size Validation (10MB images, 50MB videos, 20MB audio, 25MB documents)
Expo Modules Used
| Module | Purpose | Version |
|--------|---------|---------|
| expo-audio | Audio recording/playback | >=0.4.0 |
| expo-video | Video playback | >=1.0.0 |
| expo-image-picker | Camera/gallery access | >=15.0.0 |
| expo-document-picker | File selection | >=12.0.0 |
| expo-file-system | File operations | >=17.0.0 |
| rn-emoji-keyboard | Emoji selection | >=1.7.0 |
Installation
Step 1: Install Package
npm install @contegris/rn-intellicon-chat-sdk-expo
# Also install Expo modules
npx expo install expo-audio expo-document-picker expo-file-system expo-image-picker expo-video rn-emoji-keyboardStep 2: Configure app.json
Add config plugins to app.json:
{
"expo": {
"plugins": [
[
"expo-image-picker",
{
"photosPermission": "Allow $(PRODUCT_NAME) to access photos to send images in chat.",
"cameraPermission": "Allow $(PRODUCT_NAME) to use camera to capture images for chat."
}
],
[
"expo-audio",
{
"microphonePermission": "Allow $(PRODUCT_NAME) to record voice messages."
}
],
[
"expo-document-picker",
{
"iCloudContainerEnvironment": "Production"
}
]
]
}
}Step 3: Rebuild Development Build
IMPORTANT: This package does NOT work with Expo Go. You must use a development build.
# Clean and rebuild
npx expo prebuild --clean
# iOS
npx expo run:ios
# Android
npx expo run:androidQuick Start
import React from 'react';
import { Chat } from '@contegris/rn-intellicon-chat-sdk-expo';
export default function App() {
return (
<Chat
user={{
participantId: 'user-123',
name: 'John Doe',
}}
config={{
baseUrl: 'https://democc.contegris.com:443',
appId: 'your-app-id',
title: 'Customer Support',
}}
onFeedbackSubmit={() => {
// Called when user submits the post-conversation rating
// e.g. navigation.goBack()
}}
/>
);
}That's it! Users can now:
- Send text messages
- Capture/select images
- Capture/select videos
- Record/send audio messages
- Pick/send documents
- Use emoji keyboard
Media Features
Image Attachments
Capture from Camera:
- Quality: 0.8 (80% quality to reduce file size)
- Max size: 10 MB (validated before upload)
- Format: JPEG
Select from Gallery:
- Multi-select: Yes (selects one at a time in current implementation)
- Quality: 0.8
- Max size: 10 MB
Display:
- Thumbnail in chat
- Tap to open lightbox modal
- Pinch to zoom
- Close button
Video Attachments
Capture:
- Duration: Unlimited (up to 50 MB file size limit)
- Quality: Configurable via expo-image-picker
Playback:
- Thumbnail preview in chat
- Tap to open fullscreen modal
- Native video controls (play/pause/seek)
- Close button
Max size: 50 MB
Audio Messages
Recording:
- Long-press microphone button to record
- Live waveform animation (28 bars)
- Real-time duration counter
- Recording indicator (pulsing red dot)
- Cancel or Send options
Recording Config:
- Format: MPEG-4 AAC
- Bitrate: 128 kbps
- Sample rate: 44.1 kHz
- Channels: Stereo
Playback:
- Waveform visualization
- Play/pause button
- Seek by tapping waveform
- Duration display (current/total)
- Only one audio plays at a time
Preview:
- After recording, can preview before sending
- Play/pause controls
- Send or delete options
Max size: 20 MB
Document Attachments
Selection:
- Any file type supported
- Picker interface: Native system picker
- iCloud support: Yes (configured via plugin)
Display:
- File type icon with extension badge
- Color-coded by type (PDF=red, DOC=blue, etc.)
- File name (up to 3 lines)
- Download button
- Open in external viewer
Max size: 25 MB
Supported Types:
- Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT
- Archives: ZIP, RAR, 7Z
- Media: MP3, MP4, MOV, AVI (can be sent as documents)
- Blocked: .exe, .apk, .sh, .bat (security)
Emoji Keyboard
Features:
- Inline panel (slides up from input)
- Categories: Smileys, People, Animals, Food, etc.
- Search functionality
- Recently used
- Skin tone support
- Custom theme colors
Configuration:
theme={{
messageInput: {
emojiIconColor: '#6B7280', // Emoji button color
},
}}Theming
All theme properties from the core package work with Expo. Customize colors, fonts, gradients, and component styles.
Complete Theme Reference
import { Chat, type ChatTheme } from '@contegris/rn-intellicon-chat-sdk-expo';
const theme: ChatTheme = {
// ─── Global Font ────────────────────────────────────────────────────────
fontFamily: 'Inter', // Default: 'Outfit' | null for system font
// ─── Background ─────────────────────────────────────────────────────────
backgroundColor: '#0F172A', // Solid fallback color
backgroundImage: 'https://...', // Wallpaper URI (local or remote)
backgroundGradientColors: ['#1E293B', '#0F172A'], // ≥2 stops (overrides image/bg)
backgroundGradientDirection: 'diagonal', // 'horizontal' | 'vertical' | 'diagonal'
backgroundOverlay: 'rgba(0,0,0,0.2)', // Semi-transparent tint layer
// ─── Loading & Error States ─────────────────────────────────────────────
loaderColor: '#60A5FA',
loaderSize: 'large', // 'small' | 'large'
LoadingComponent: MyCustomLoader, // Replace entire loading screen
ErrorComponent: MyErrorScreen, // Replace entire error screen
errorTextStyle: { color: '#EF4444', fontSize: 15 },
errorContainerStyle: { backgroundColor: '#0F172A' },
// ─── Layout ─────────────────────────────────────────────────────────────
containerStyle: { flex: 1 }, // SafeAreaView style
listContentStyle: { flexGrow: 1 }, // FlatList contentContainerStyle
listPaddingVertical: 12, // Message list vertical padding
listPaddingHorizontal: 0, // Message list horizontal padding
// ─── Pagination (Load More) ─────────────────────────────────────────────
loadMoreThreshold: 0.15, // FlatList onEndReachedThreshold (0–1)
loadMoreLoaderColor: '#60A5FA',
showLoadMoreSpinner: true,
// ─── AppBar ─────────────────────────────────────────────────────────────
appBar: {
enabled: true, // Show/hide AppBar
bgColor: '#1E293B',
gradientColors: ['#1E3A8A', '#3B82F6'], // Overrides bgColor
gradientDirection: 'horizontal',
titleStyle: { color: '#F1F5F9', fontSize: 18, fontWeight: '700' },
iconColor: '#60A5FA',
centerTitle: false,
},
// ─── Message Bubbles ────────────────────────────────────────────────────
bubbleStyle: {
agent: {
bgColor: '#334155',
textStyle: { color: '#F1F5F9', fontSize: 14 },
audioMessage: {
sliderColor: '#60A5FA',
inactiveColor: '#475569',
playPauseIconColor: '#60A5FA',
downloadIconColor: '#60A5FA',
durationStyle: { color: '#94A3B8', fontSize: 12 },
},
videoMessage: {
playButtonColor: '#60A5FA',
},
documentMessage: {
downloadIconColor: '#60A5FA',
copyIconColor: '#94A3B8',
attachmentIconColor: '#CBD5E1',
textStyle: { color: '#F1F5F9', fontSize: 13, fontWeight: '600' },
},
},
visitor: {
bgColor: '#2563EB',
textStyle: { color: '#FFFFFF', fontSize: 14 },
audioMessage: {
sliderColor: '#FFFFFF',
inactiveColor: '#93C5FD',
playPauseIconColor: '#FFFFFF',
downloadIconColor: '#FFFFFF',
durationStyle: { color: '#DBEAFE', fontSize: 12 },
},
videoMessage: {
playButtonColor: '#FFFFFF',
},
documentMessage: {
downloadIconColor: '#FFFFFF',
copyIconColor: '#DBEAFE',
attachmentIconColor: '#EFF6FF',
textStyle: { color: '#FFFFFF', fontSize: 13, fontWeight: '600' },
},
},
},
// ─── Date Separator ─────────────────────────────────────────────────────
dateSeparator: {
containerStyle: {
alignSelf: 'center',
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 12,
backgroundColor: 'rgba(30,41,59,0.85)',
},
textStyle: { color: '#94A3B8', fontSize: 12, fontWeight: '500' },
},
// ─── Message Input Bar ──────────────────────────────────────────────────
messageInput: {
bgColor: '#1E293B',
inputContainerStyle: { borderRadius: 20 },
hintStyle: { color: '#64748B', fontSize: 14, fontStyle: 'italic' },
messageTextStyle: { color: '#F8FAFC', fontSize: 14 },
emojiIconColor: '#64748B',
attachmentIconColor: '#64748B',
attachmentModalBgColor: '#334155',
micInactiveIconColor: '#64748B',
micActiveIconColor: '#EF4444',
micSendBgColor: '#2563EB',
sendIconColor: '#FFFFFF',
sendVoiceMessageIconColor: '#60A5FA',
deleteVoiceMessageIconColor: '#EF4444',
},
// ─── Feedback / Rating Widget ───────────────────────────────────────────
feedback: {
containerStyle: { backgroundColor: '#334155' },
activeColor: '#60A5FA',
inactiveColor: '#475569',
textActiveColor: '#FFFFFF',
textInactiveColor: '#94A3B8',
},
};
<Chat user={user} config={config} theme={theme} />Quick Start Examples
Minimal Theme (Dark Mode)
const theme: ChatTheme = {
fontFamily: 'Inter',
backgroundColor: '#0F172A',
appBar: { bgColor: '#1E293B', iconColor: '#60A5FA' },
};Light Mode
const theme: ChatTheme = {
backgroundColor: '#FFFFFF',
appBar: {
bgColor: '#F8FAFC',
titleStyle: { color: '#0F172A' },
iconColor: '#2563EB',
},
bubbleStyle: {
agent: { bgColor: '#F1F5F9', textStyle: { color: '#0F172A' } },
visitor: { bgColor: '#2563EB', textStyle: { color: '#FFFFFF' } },
},
messageInput: { bgColor: '#F8FAFC', sendIconColor: '#2563EB' },
};Media-Specific Styling
const theme: ChatTheme = {
bubbleStyle: {
agent: {
audioMessage: {
sliderColor: '#10B981', // Custom waveform color
playPauseIconColor: '#10B981',
durationStyle: { color: '#6EE7B7', fontSize: 11 },
},
videoMessage: {
playButtonColor: '#EF4444', // Red play button
},
documentMessage: {
downloadIconColor: '#3B82F6',
attachmentIconColor: '#93C5FD',
},
},
},
};For the default theme definition, see theme.types.ts.
Permissions
iOS (Info.plist)
Configured automatically via config plugins:
<key>NSMicrophoneUsageDescription</key>
<string>Allow app to record voice messages.</string>
<key>NSCameraUsageDescription</key>
<string>Allow app to capture images for chat.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Allow app to access photos to send images.</string>Android (AndroidManifest.xml)
Configured automatically via config plugins:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />Runtime Permission Handling
The SDK automatically requests permissions when needed:
// Example: Recording audio
// 1. User taps microphone button
// 2. SDK checks permission
// 3. If not granted, shows system dialog
// 4. If denied, shows toast: "Microphone permission required"Configuration
Same as core package. See Core Package Configuration.
Additional Media Config:
File size limits are enforced by the upload validator:
// Default limits (configurable via UploadManager)
{
maxFileSizeBytes: 100 * 1024 * 1024, // 100MB default
// Specific limits per type:
// Images: 10 MB
// Videos: 50 MB
// Audio: 20 MB
// Documents: 25 MB
}API Reference
Chat Component Props
interface ChatProps {
user: User;
config: Config;
customData?: Record<string, unknown>;
theme?: ChatTheme;
downloadFile?: (params: { url: string; stopLoading: () => void; type: 'image' | 'video' | 'document'; fileName?: string }) => void;
onFeedbackSubmit?: () => void;
onPerformanceReport?: (report: PerformanceReport) => void;
showLogToggle?: boolean;
keyboardVerticalOffset?: number;
goBack?: () => void;
}| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| user | User | ✅ Yes | N/A | User identification object |
| config | Config | ✅ Yes | N/A | Server configuration |
| customData | Record<string, unknown> | ❌ No | undefined | Arbitrary metadata sent to server |
| theme | ChatTheme | ❌ No | DEFAULT_CHAT_THEME | Visual customization (50+ tokens) |
| downloadFile | (params: { url: string; stopLoading: () => void; type: 'image' \| 'video' \| 'document'; fileName?: string }) => void | ❌ No | undefined | Custom handler for media downloads (image, video, document) |
| onFeedbackSubmit | () => void | ❌ No | undefined | Called after the user submits feedback/rating. Use to navigate away or close the chat screen. |
| onPerformanceReport | (report: PerformanceReport) => void | ❌ No | undefined | Callback for APM integration |
| showLogToggle | boolean | ❌ No | false | Show debug toggle button (dev only) |
| keyboardVerticalOffset | number | ❌ No | 0 | Keyboard vertical offset for KeyboardAvoidingView on iOS |
| goBack | () => void | ❌ No | undefined | When provided, renders a back arrow in the AppBar. Use to navigate back (e.g., navigation.goBack()). |
Exports
// Expo-specific components
export { Chat } // Main chat wrapper (with media support)
export { AudioBubble } // Audio message with expo-audio
export { VideoBubble } // Video message with expo-video
export { DocumentBubble } // Document picker + download (expo-file-system)
export { ImageBubble } // Image viewer with expo-file-system download