# OddSockets Flutter SDK

A comprehensive real-time communication SDK for Flutter applications, providing mobile-optimized features for chat, presence tracking, file sharing, and more.

## Features

### 🚀 Core Features
- **Real-time Messaging** - Send and receive messages instantly
- **Presence Tracking** - Monitor user online/offline status
- **File Upload/Download** - Share images, videos, documents with progress tracking
- **Push Notifications** - Firebase Cloud Messaging integration
- **Background Sync** - Offline message queuing and automatic sync
- **Connection Management** - Auto-reconnection with exponential backoff

### 📱 Mobile-Specific Features
- **Connectivity Monitoring** - Detect network changes (WiFi, Mobile, etc.)
- **Background Tasks** - WorkManager integration for background operations
- **Local Notifications** - Show notifications when app is in foreground
- **File Caching** - Intelligent caching with automatic cleanup
- **Image Processing** - Automatic compression and thumbnail generation
- **Camera Integration** - Direct camera access for photo/video capture

### 🎨 UI Components
- **Chat Widget** - Ready-to-use chat interface
- **Presence Widget** - User status indicators
- **Connection Status Widget** - Network connectivity display

## Installation

Add this to your `pubspec.yaml`:

```yaml
dependencies:
  oddsockets_flutter: ^1.0.0
```

## Quick Start

### 1. Initialize the SDK

```dart
import 'package:oddsockets_flutter/oddsockets_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize OddSockets client
  final client = OddSocketsClient.instance;
  await client.initialize(ConnectionConfig(
    apiKey: 'your-api-key',
    userId: 'user-123',
    endpoint: 'https://api.oddsockets.com',
    enableBackgroundSync: true,
    enablePushNotifications: true,
  ));
  
  runApp(MyApp());
}
```

### 2. Connect and Send Messages

```dart
class ChatScreen extends StatefulWidget {
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final OddSocketsClient _client = OddSocketsClient.instance;
  
  @override
  void initState() {
    super.initState();
    _connectAndJoinChannel();
  }
  
  Future<void> _connectAndJoinChannel() async {
    await _client.connect();
    await _client.joinChannel('general');
    
    // Listen for messages
    _client.messageStream.listen((message) {
      setState(() {
        // Update UI with new message
      });
    });
  }
  
  Future<void> _sendMessage(String text) async {
    await _client.sendMessage('general', text);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Chat')),
      body: OddSocketsChatWidget(
        channelId: 'general',
        userId: 'user-123',
        onMessageSent: (message) {
          print('Message sent: ${message.content}');
        },
      ),
    );
  }
}
```

### 3. File Upload with Progress

```dart
Future<void> uploadFile(File file) async {
  final fileService = FileService.instance;
  
  // Listen for upload progress
  fileService.uploadProgressStream.listen((progress) {
    print('Upload progress: ${progress.percentage}%');
  });
  
  try {
    final request = await FileUploadRequest.fromFile(
      file,
      channelId: 'general',
      options: FileUploadOptions(
        enableCompression: true,
        maxWidth: 1920,
        maxHeight: 1080,
        quality: 85,
      ),
    );
    
    final result = await fileService.uploadFile(request);
    print('File uploaded: ${result.url}');
  } catch (e) {
    print('Upload failed: $e');
  }
}
```

### 4. Presence Tracking

```dart
class UserPresenceWidget extends StatefulWidget {
  final String userId;
  
  @override
  _UserPresenceWidgetState createState() => _UserPresenceWidgetState();
}

class _UserPresenceWidgetState extends State<UserPresenceWidget> {
  PresenceData? _presenceData;
  
  @override
  void initState() {
    super.initState();
    _subscribeToPresence();
  }
  
  void _subscribeToPresence() {
    final client = OddSocketsClient.instance;
    
    client.presenceStream.listen((update) {
      if (update.presence.userId == widget.userId) {
        setState(() {
          _presenceData = update.presence;
        });
      }
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return OddSocketsPresenceWidget(
      userId: widget.userId,
      presenceData: _presenceData,
      showStatus: true,
      showLastSeen: true,
    );
  }
}
```

### 5. Push Notifications

```dart
Future<void> setupNotifications() async {
  final notificationService = NotificationService.instance;
  
  await notificationService.initialize(
    config: NotificationConfig(
      showForegroundNotifications: true,
      enableSound: true,
      enableVibration: true,
    ),
  );
  
  // Listen for notification taps
  notificationService.messageStream.listen((message) {
    // Handle notification tap - navigate to chat, etc.
    Navigator.pushNamed(context, '/chat', arguments: message.channelId);
  });
  
  // Register FCM token with server
  notificationService.tokenStream.listen((token) {
    // Send token to your server for push notifications
    _registerTokenWithServer(token);
  });
}
```

### 6. Background Sync

```dart
Future<void> setupBackgroundSync() async {
  final backgroundService = BackgroundService.instance;
  
  await backgroundService.initialize(
    config: BackgroundConfig(
      enableBackgroundSync: true,
      syncInterval: Duration(minutes: 15),
      maxOfflineMessages: 1000,
      requiresBatteryNotLow: true,
    ),
  );
  
  // Monitor connectivity
  backgroundService.connectivityStream.listen((result) {
    if (result != ConnectivityResult.none) {
      print('Connected via: ${result.toString()}');
    } else {
      print('No internet connection');
    }
  });
  
  // Monitor sync status
  backgroundService.syncStatusStream.listen((status) {
    switch (status) {
      case BackgroundSyncStatus.syncing:
        print('Syncing offline data...');
        break;
      case BackgroundSyncStatus.completed:
        print('Sync completed successfully');
        break;
      case BackgroundSyncStatus.failed:
        print('Sync failed');
        break;
    }
  });
}
```

## Architecture

### Core Components

- **OddSocketsClient** - Main SDK client with singleton pattern
- **ConnectionConfig** - Configuration for connections and features
- **Models** - Message, Presence, FileUpload data models
- **Services** - Notification, Background, File management services
- **Widgets** - Pre-built UI components for common use cases

### Mobile Optimizations

- **Singleton Pattern** - Efficient resource management
- **Stream-based Architecture** - Reactive programming with RxDart
- **Background Processing** - WorkManager for offline operations
- **Connectivity Awareness** - Automatic handling of network changes
- **Battery Optimization** - Configurable background task constraints

## Configuration Options

### Connection Configuration

```dart
ConnectionConfig(
  apiKey: 'your-api-key',
  userId: 'user-123',
  endpoint: 'https://api.oddsockets.com',
  wsEndpoint: 'wss://ws.oddsockets.com',
  enableAutoReconnect: true,
  maxReconnectAttempts: 5,
  reconnectDelay: Duration(seconds: 5),
  connectionTimeout: Duration(seconds: 30),
  enableHeartbeat: true,
  heartbeatInterval: Duration(seconds: 30),
  enableBackgroundSync: true,
  enablePushNotifications: true,
  enablePresenceTracking: true,
  enableFileUploads: true,
)
```

### File Upload Configuration

```dart
FileUploadOptions(
  generateThumbnail: true,
  maxWidth: 1920,
  maxHeight: 1080,
  quality: 85,
  enableCompression: true,
  enableEncryption: false,
  maxFileSize: 10 * 1024 * 1024, // 10MB
  allowedMimeTypes: ['image/jpeg', 'image/png'],
)
```

### Notification Configuration

```dart
NotificationConfig(
  showForegroundNotifications: true,
  enableSound: true,
  enableVibration: true,
  channelId: 'oddsockets_messages',
  channelName: 'OddSockets Messages',
  importance: NotificationImportance.high,
)
```

## Error Handling

```dart
try {
  await client.connect();
} on OddSocketsException catch (e) {
  switch (e.code) {
    case 'INVALID_API_KEY':
      // Handle invalid API key
      break;
    case 'CONNECTION_FAILED':
      // Handle connection failure
      break;
    case 'NETWORK_UNAVAILABLE':
      // Handle network issues
      break;
    default:
      // Handle other errors
      break;
  }
} catch (e) {
  // Handle unexpected errors
  print('Unexpected error: $e');
}
```

## Best Practices

### 1. Resource Management
- Always dispose of streams and controllers
- Use singleton pattern for services
- Implement proper error handling

### 2. Performance
- Enable file compression for uploads
- Use appropriate cache settings
- Monitor background sync frequency

### 3. User Experience
- Show connection status to users
- Provide offline indicators
- Handle network transitions gracefully

### 4. Security
- Validate API keys on server
- Use HTTPS/WSS endpoints
- Implement proper authentication

## Platform Support

- ✅ **Android** - Full feature support
- ✅ **iOS** - Full feature support  
- ⚠️ **Web** - Limited (no background sync, notifications)
- ⚠️ **Desktop** - Limited (no mobile-specific features)

## Dependencies

- `socket_io_client` - WebSocket connections
- `firebase_messaging` - Push notifications
- `flutter_local_notifications` - Local notifications
- `connectivity_plus` - Network monitoring
- `workmanager` - Background tasks
- `shared_preferences` - Local storage
- `path_provider` - File system access
- `http` - HTTP requests
- `image` - Image processing
- `crypto` - Cryptographic functions

## Example App

See the complete example in the `example/` directory for a full implementation of a chat application with all SDK features.

## Support

For issues, questions, or contributions, please visit our [GitHub repository](https://github.com/oddsockets/flutter-sdk).

## License

MIT License - see LICENSE file for details.
