sm_ai_support 1.0.6 copy "sm_ai_support: ^1.0.6" to clipboard
sm_ai_support: ^1.0.6 copied to clipboard

A comprehensive Flutter package for integrating AI-powered customer support with real-time chat, media sharing, and multi-language support.

πŸš€ SM AI Support #

pub package License: MIT Flutter Dart

A comprehensive Flutter package for integrating AI-powered customer support into your mobile applications

Real-time chat β€’ Media sharing β€’ Multi-language β€’ Tenant-based customization

Features β€’ Installation β€’ Quick Start β€’ Documentation β€’ Examples


✨ Features #

🎯 Core Functionality #

  • πŸ’¬ Real-time Chat - WebSocket-powered instant messaging with delivery status and typing indicators
  • πŸ€– AI-Powered Support - Intelligent responses and automated assistance
  • πŸ“± Advanced Media Support - Share images, videos, files, and documents
    • Automatic image compression and optimization
    • Chunked file upload for large files
    • Support for multiple file types (PDF, DOC, DOCX, XLS, XLSX, images, videos)
    • Upload progress tracking with cancellation support
  • 🌍 Multi-language - Built-in English and Arabic support with RTL layout
  • πŸ‘€ Flexible Authentication - Anonymous and authenticated user flows with auto-login support
  • πŸš€ Auto-Login - Seamless authentication for existing app users without OTP
  • πŸ“Š Session Management - Organized conversation history with persistence and search

🏒 Enterprise Ready #

  • πŸ—οΈ Multi-tenant Architecture - Perfect for SaaS applications
  • 🎨 Dynamic Theming - Automatic branding fetch from tenant configuration
  • πŸ” Secure Communications - End-to-end encryption and HMAC signatures
  • πŸ“ˆ Analytics Ready - Built-in tracking and monitoring capabilities
  • ⚑ High Performance - Optimized for large-scale deployments

🎨 User Experience #

  • πŸ“± Responsive Design - Optimized for all screen sizes and orientations
  • 🎭 Customizable UI - Tenant-specific branding and color schemes
  • ✨ Smooth Animations - Polished transitions and loading states
  • β™Ώ Accessibility - Screen reader compatibility and semantic labels
  • πŸŒ™ Theme Support - Light and dark mode compatibility

πŸ“¦ Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  sm_ai_support: ^0.0.1

Then run:

flutter pub get

Platform Requirements #

Platform Minimum Version
Flutter 1.17.0+
Dart 3.8.1+
iOS 12.0+
Android API 21+ (Android 5.0)

Required Permissions #

Android (android/app/src/main/AndroidManifest.xml):

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- Storage permissions for Android 12 and below -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Media permissions for Android 13 and above -->
<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" />

Android Queries (Add to android/app/src/main/AndroidManifest.xml inside <manifest> tag):

<queries>
    <!-- Required for file_picker to pick files -->
    <intent>
        <action android:name="android.intent.action.GET_CONTENT"/>
    </intent>
    <!-- Required for open_filex to open files -->
    <intent>
        <action android:name="android.intent.action.VIEW"/>
        <data android:mimeType="*/*"/>
    </intent>
    <!-- Camera intent -->
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE"/>
    </intent>
</queries>

iOS (ios/Runner/Info.plist):

<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos for support</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select images for support</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone for audio messages</string>

πŸš€ Quick Start #

1. Import the package #

import 'package:sm_ai_support/sm_ai_support.dart';

2. Basic Implementation #

import 'package:flutter/material.dart';
import 'package:sm_ai_support/sm_ai_support.dart';

class SupportPage extends StatelessWidget {
  const SupportPage({super.key});

  @override
  Widget build(BuildContext context) {
    return SMSupport(
      parentContext: context,
      smSupportData: SMSupportData(
        appName: 'Your App Name',
        locale: SMSupportLocale.en, // or SMSupportLocale.ar
        tenantId: 'your_tenant_id',
        apiKey: 'your_api_key_here', // Required for authentication
        secretKey: 'your_secret_key_here', // Required: For HMAC request signing
        baseUrl: 'https://your-api-server.com/api/core', // REST API base URL
        socketBaseUrl: 'wss://your-api-server.com/ws', // WebSocket base URL
      ),
    );
  }
}

3. Navigate to Support #

// From anywhere in your app
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SupportPage()),
);


πŸ“– Documentation #

Configuration Options #

SMSupportData Parameters

Parameter Type Required Description Default
appName String βœ… Your application name -
locale SMSupportLocale βœ… Language preference (en/ar) -
tenantId String βœ… Your unique tenant identifier -
apiKey String βœ… API key for authentication (stored securely) -
secretKey String βœ… Secret key for HMAC request signing (stored securely) -
baseUrl String βœ… Base URL for REST API endpoints (e.g., https://api.example.com/api/core) -
socketBaseUrl String βœ… Base URL for WebSocket connections (e.g., wss://api.example.com/ws) -
customer CustomerData? ❌ Optional customer data for automatic login null

Available Locales

// English interface (LTR)
SMSupportLocale.en

// Arabic interface (RTL)
SMSupportLocale.ar

Advanced Configuration #

Secure Configuration

SMSupport(
  parentContext: context,
  smSupportData: SMSupportData(
    appName: 'My App',
    locale: SMSupportLocale.en,
    tenantId: 'tenant_123',
    apiKey: 'your_secure_api_key', 
    secretKey: 'your_hmac_secret',
    baseUrl: 'https://your-api-server.com/api/core', 
    socketBaseUrl: 'wss://your-api-server.com/ws',
  ),
)

Security Features

The package automatically handles secure storage of sensitive data and request signing:

  • API Key: Stored using flutter_secure_storage for secure authentication
  • Secret Key: Used for HMAC-SHA256 request signing to ensure request integrity
  • HMAC Signatures: All API requests are automatically signed with HMAC-SHA256
  • Automatic Cleanup: Keys are cleared when the app is uninstalled
  • Secure Storage: Uses platform-specific secure storage (iOS Keychain, Android EncryptedSharedPreferences)
// Check if configuration is initialized
final hasApiKey = await SMConfig.hasAPIKey();
final hasSecretKey = await SMConfig.hasSecretKey();

// Get stored keys (if needed for debugging)
final apiKey = await SMConfig.getAPIKey();
final secretKey = await SMConfig.getSecretKey();

// Clear individual keys
await SMConfig.clearAPIKey();
await SMConfig.clearSecretKey();

// Clear all secure data (for logout/reset)
await SMConfig.clearAllSecureData();

HMAC Request Signing:

All HTTP requests are automatically signed using HMAC-SHA256. The signature is computed from:

  • Request timestamp (Unix timestamp in seconds)
  • HTTP method (GET, POST, etc.)
  • Request path
  • Request body (for POST/PUT requests)

The signature is sent in the X-Signature header, and the timestamp in the X-Timestamp header. This ensures:

  • Request authenticity
  • Protection against replay attacks
  • Request integrity verification

Auto-Login Feature

The package supports automatic user authentication without requiring OTP verification. This is useful when you already have authenticated users in your app and want to seamlessly integrate the support system.

Basic Auto-Login:

import 'package:sm_ai_support/sm_ai_support.dart';

SMSupport(
  parentContext: context,
  smSupportData: SMSupportData(
    appName: 'My App',
    locale: SMSupportLocale.en,
    tenantId: 'tenant_123',
    apiKey: 'your_api_key',
    secretKey: 'your_secret_key',
    baseUrl: 'https://your-api-server.com/api/core',
    socketBaseUrl: 'wss://your-api-server.com/ws',
    // Auto-login with customer data
    customer: CustomerData(
      countryCode: '+966',  // Country code (e.g., +1, +44, +966)
      phone: '501234567',   // Phone number without country code
      name: 'John Doe',     // Customer name
    ),
  ),
)

How Auto-Login Works:

  1. When you provide customer data in SMSupportData, the package automatically authenticates the user during initialization
  2. The API endpoint /in-app/auto-login is called with:
    • phone: Combined country code + phone number (e.g., "+966501234567")
    • name: Customer name
  3. On successful authentication:
    • User receives an authentication token (same as OTP verification)
    • Token is securely stored for future sessions
    • Any anonymous sessions are automatically assigned to the authenticated user
    • User can immediately access all authenticated features
  4. If auto-login fails:
    • Error is logged but doesn't block initialization
    • User can still use the support system as an anonymous user

Real-World Example:

class UserSupportPage extends StatelessWidget {
  final User currentUser; // Your app's user model

  const UserSupportPage({super.key, required this.currentUser});

  @override
  Widget build(BuildContext context) {
    return SMSupport(
      parentContext: context,
      smSupportData: SMSupportData(
        appName: 'My App',
        locale: SMSupportLocale.en,
        tenantId: 'tenant_123',
        apiKey: 'your_api_key',
        secretKey: 'your_secret_key',
        baseUrl: 'https://your-api-server.com/api/core',
        socketBaseUrl: 'wss://your-api-server.com/ws',
        // Seamlessly login with existing user data
        customer: CustomerData(
          countryCode: currentUser.countryCode,
          phone: currentUser.phoneNumber,
          name: currentUser.fullName,
        ),
      ),
    );
  }
}

Benefits:

  • πŸš€ Seamless Experience: No need for users to authenticate again
  • πŸ”„ Session Continuity: Preserves conversation history across sessions
  • πŸ” Secure: Uses the same authentication mechanism as OTP verification
  • ⚑ Fast: Instant authentication without user interaction
  • 🎯 Flexible: Falls back gracefully if authentication fails

CustomerData Model:

CustomerData({
  required String countryCode,  // Country code with + (e.g., "+1", "+966")
  required String phone,        // Phone number without country code
  required String name,         // Customer's full name
})

πŸ’‘ Examples #

Complete Integration Example #

import 'package:flutter/material.dart';
import 'package:sm_ai_support/sm_ai_support.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SM AI Support Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('My Awesome App'),
        actions: [
          // Support button in app bar
          IconButton(
            icon: const Icon(Icons.support_agent),
            onPressed: () => _openSupport(context),
            tooltip: 'Get Support',
          ),
        ],
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.home, size: 100, color: Colors.blue),
            SizedBox(height: 20),
            Text(
              'Welcome to My App!',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            Text('Need help? Tap the support icon above.'),
          ],
        ),
      ),
      // Floating support button
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () => _openSupport(context),
        icon: const Icon(Icons.chat),
        label: const Text('Support'),
      ),
    );
  }

  void _openSupport(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => SMSupport(
          parentContext: context,
          smSupportData: SMSupportData(
            appName: 'My Awesome App',
            locale: SMSupportLocale.en,
            tenantId: 'your_tenant_id',
            apiKey: 'your_api_key_here',
            secretKey: 'your_secret_key_here', // Required
            baseUrl: 'https://your-api-server.com/api/core',
            socketBaseUrl: 'wss://your-api-server.com/ws',
          ),
        ),
      ),
    );
  }
}

Multi-language Support #

class LocalizedSupportPage extends StatelessWidget {
  final bool isArabic;
  
  const LocalizedSupportPage({super.key, this.isArabic = false});

  @override
  Widget build(BuildContext context) {
    return SMSupport(
      parentContext: context,
      smSupportData: SMSupportData(
        appName: isArabic ? 'ΨͺΨ·Ψ¨ΩŠΩ‚ΩŠ Ψ§Ω„Ψ±Ψ§Ψ¦ΨΉ' : 'My Awesome App',
        locale: isArabic ? SMSupportLocale.ar : SMSupportLocale.en,
        tenantId: 'your_tenant_id',
        apiKey: 'your_api_key_here',
        secretKey: 'your_secret_key_here', // Required
        baseUrl: 'https://your-api-server.com/api/core',
        socketBaseUrl: 'wss://your-api-server.com/ws',
      ),
    );
  }
}

Real-World Integration Example #

class ProductionSupportPage extends StatelessWidget {
  final String userLocale;
  
  const ProductionSupportPage({super.key, required this.userLocale});

  @override
  Widget build(BuildContext context) {
    return SMSupport(
      parentContext: context,
      smSupportData: SMSupportData(
        appName: 'Production App',
        locale: userLocale == 'ar' ? SMSupportLocale.ar : SMSupportLocale.en,
        tenantId: 'prod_tenant_123',
        apiKey: const String.fromEnvironment('SM_SUPPORT_API_KEY'),
        secretKey: const String.fromEnvironment('SM_SUPPORT_SECRET_KEY'),
        baseUrl: const String.fromEnvironment(
          'SM_SUPPORT_BASE_URL',
          defaultValue: 'https://api.example.com/api/core',
        ),
        socketBaseUrl: const String.fromEnvironment(
          'SM_SUPPORT_SOCKET_URL',
          defaultValue: 'wss://api.example.com/ws',
        ),
      ),
    );
  }
}

// Usage with environment variables:
// flutter run --dart-define=SM_SUPPORT_API_KEY=your_key \
//             --dart-define=SM_SUPPORT_SECRET_KEY=your_secret \
//             --dart-define=SM_SUPPORT_BASE_URL=https://api.example.com/api/core \
//             --dart-define=SM_SUPPORT_SOCKET_URL=wss://api.example.com/ws

πŸ—οΈ Architecture #

Package Structure #

sm_ai_support/
β”œβ”€β”€ πŸ“± Core Components
β”‚   β”œβ”€β”€ 🎨 UI Widgets & Themes
β”‚   β”œβ”€β”€ 🌐 Network Layer (Dio + Socket.IO)
β”‚   β”œβ”€β”€ πŸ’Ύ Data Models & Storage
β”‚   β”œβ”€β”€ πŸ” Security & Authentication (HMAC + Secure Storage)
β”‚   └── πŸ“€ Media Upload (Chunked & Streaming)
β”œβ”€β”€ πŸš€ Features
β”‚   β”œβ”€β”€ πŸ’¬ Real-time Chat (WebSocket)
β”‚   β”œβ”€β”€ πŸ“ Media Management (Image, Video, File)
β”‚   β”œβ”€β”€ πŸ“Š Session Handling
β”‚   └── 🏷️ Category System
└── 🌍 Internationalization
    β”œβ”€β”€ πŸ‡ΊπŸ‡Έ English (LTR)
    └── πŸ‡ΈπŸ‡¦ Arabic (RTL)

Key Dependencies #

  • State Management: flutter_bloc - BLoC pattern for reactive state management
  • Networking: dio - HTTP client with interceptors and request signing
  • WebSocket: socket_io_client - Real-time bidirectional communication
  • Secure Storage: flutter_secure_storage - Platform-specific encrypted storage
  • Media Handling: image_picker, file_picker, cached_network_image
  • Video Playback: video_player, chewie - Video player with controls
  • Localization: flutter_localizations, intl - Multi-language support

State Management #

The package uses BLoC pattern for reactive state management:

  • SMSupportCubit - Main application state
  • SingleSessionCubit - Individual chat session state
  • Automatic state persistence and restoration

Network Architecture #

  • REST API (Dio) - Configuration, authentication, file uploads with HMAC signing
  • WebSocket (Socket.IO) - Real-time messaging, typing indicators, and status updates
  • Automatic Reconnection - Handles network interruptions gracefully
  • Request Signing - All requests are automatically signed with HMAC-SHA256
  • Error Handling - Comprehensive error handling with user-friendly messages
  • Retry Logic - Automatic retry for failed requests with exponential backoff

πŸ”§ Advanced Features #

Security Features #

  • πŸ”’ HMAC-SHA256 Signatures - Automatic request signing for authentication and integrity
  • πŸ” Secure Storage - Platform-specific encrypted storage (iOS Keychain, Android EncryptedSharedPreferences)
  • πŸ›‘οΈ Input Validation - XSS and injection protection
  • πŸ”‘ API Key Management - Secure credential storage and retrieval
  • ⏱️ Replay Attack Prevention - Timestamp-based request validation
  • πŸ“± Transport Security - HTTPS/WSS encrypted communications

Media Upload Features #

  • πŸ“€ Chunked Upload - Large files are automatically split into chunks for reliable upload
  • πŸ“Š Progress Tracking - Real-time upload progress with percentage and cancel option
  • πŸ–ΌοΈ Image Optimization - Automatic compression and resizing for faster uploads
  • πŸ“Ή Video Support - Upload and playback of video files with custom player
  • πŸ“„ Document Support - PDF, DOC, DOCX, XLS, XLSX file uploads
  • ⚑ Upload Queue - Multiple files can be queued and uploaded sequentially
  • πŸ”„ Retry Logic - Automatic retry on failed uploads with exponential backoff
  • ❌ Cancellation - Users can cancel ongoing uploads at any time

Performance Optimizations #

  • ⚑ Lazy Loading - On-demand resource loading
  • πŸ–ΌοΈ Image Caching - Efficient media management with cached_network_image
  • πŸ“¦ Minimal Dependencies - Optimized package size
  • πŸ”„ Connection Pooling - Optimized network usage with Dio
  • πŸ“± Memory Management - Efficient handling of large media files
  • βš™οΈ Background Processing - Media compression and upload in isolates

Monitoring & Analytics #

  • πŸ“Š Usage Metrics - Built-in analytics hooks
  • πŸ› Error Tracking - Comprehensive error reporting
  • πŸ“ˆ Performance Monitoring - Real-time performance metrics
  • πŸ” Debug Tools - Development and testing utilities

πŸ› οΈ Development #

Running the Example #

cd example
flutter pub get
flutter run

Testing #

flutter test

Contributing #

We welcome contributions! Please see our Contributing Guide for details.


πŸ“š API Reference #

Core Classes #

SMSupport Widget

The main widget that provides the support interface.

SMSupport({
  required BuildContext parentContext,
  required SMSupportData smSupportData,
  Key? key,
})

SMSupportData Model

Configuration data for the support system.

SMSupportData({
  required String appName,          // Your application name
  required SMSupportLocale locale,  // UI language (en or ar)
  required String tenantId,         // Your tenant identifier
  required String apiKey,           // API authentication key
  required String secretKey,        // HMAC signing secret key
  required String baseUrl,          // REST API base URL (e.g., 'https://api.example.com/api/core')
  required String socketBaseUrl,    // WebSocket base URL (e.g., 'wss://api.example.com/ws')
  CustomerData? customer,           // Optional: Auto-login customer data
})

CustomerData Model

Customer data for automatic authentication.

CustomerData({
  required String countryCode,  // Country code with + (e.g., "+1", "+966")
  required String phone,        // Phone number without country code
  required String name,         // Customer's full name
})

// Example:
const customer = CustomerData(
  countryCode: '+966',
  phone: '501234567',
  name: 'John Doe',
);

// Provides fullPhoneNumber getter: "+966501234567"
print(customer.fullPhoneNumber);

Services #

SMConfig

Manages secure configuration and API keys.

// Check if configuration is initialized
final hasApiKey = await SMConfig.hasAPIKey();
final hasSecretKey = await SMConfig.hasSecretKey();

// Get stored keys (if needed)
final apiKey = await SMConfig.getAPIKey();
final secretKey = await SMConfig.getSecretKey();

// Clear individual keys
await SMConfig.clearAPIKey();
await SMConfig.clearSecretKey();

// Clear all secure data (for logout/reset)
await SMConfig.clearAllSecureData();

AuthManager

Handles user authentication and session management.

// Initialize authentication system
await AuthManager.init();

WebSocketService

Manages real-time communication for chat functionality.

final wsService = WebSocketService();
// WebSocket connection is handled automatically by the package

πŸ” Troubleshooting #

Common Issues #

Build Errors

Problem: Compilation errors after installation

# Solution: Clean and rebuild
flutter clean
flutter pub get
flutter run

Network Issues

Problem: Connection timeouts or SSL errors

// Solution: Ensure proper configuration with all required parameters
SMSupportData(
  appName: 'My App',
  locale: SMSupportLocale.en,
  tenantId: 'your_tenant_id',
  apiKey: 'valid_api_key_here',        // Required
  secretKey: 'valid_secret_key_here',   // Required
  baseUrl: 'https://api.example.com/api/core',  // Required
  socketBaseUrl: 'wss://api.example.com/ws',     // Required
)

Localization Issues

Problem: Text not displaying in correct language

// Solution: Ensure proper locale setup in your main app
MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en', 'US'),
    Locale('ar', 'SA'),
  ],
  // ... rest of config
)

Permission Issues

Problem: Camera or file picker not working

Solution: Ensure you've added the required permissions (see Required Permissions section above)

For runtime permissions:

// The package automatically handles permission requests
// Just ensure the permissions are declared in your manifest files

Problem: Image picker crashes on Android 13+

Solution: Add the new photo picker permissions:

<!-- Android 13+ -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

Upload Issues

Problem: File upload fails or times out

Solution:

  • Check your network connection
  • Verify your API key and secret key are correct
  • Ensure your server's upload size limits are sufficient
  • For large files, the package automatically uses chunked upload

πŸ“„ License #

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments #

  • Built with ❀️ by the [Unicode Team]
  • Powered by Flutter and Dart

πŸ“ˆ Changelog #

See CHANGELOG.md for a detailed history of changes.


⬆ Back to Top

Made with ❀️ by the Unicode Team