seenn_flutter

Flutter SDK for Seenn - Real-time job progress tracking with Live Activity (iOS), and Ongoing Notification (Android) support.

pub package pub downloads License: MIT

Features

  • Real-time Updates - Polling with automatic reconnection
  • iOS Live Activity - Lock Screen and Dynamic Island progress
  • Android Ongoing Notification - Persistent notification with progress bar
  • Provisional Push - iOS 12+ quiet notifications without permission prompt
  • ETA Countdown - Smart time estimates with confidence scores
  • Parent-Child Jobs - Hierarchical job relationships
  • Reactive Streams - RxDart-powered state management
  • Error Codes - Standardized error handling with SeennErrorCode
  • Input Validation - Client-side validation before native calls

Installation

dependencies:
  seenn_flutter: ^0.8.4

Quick Start

import 'package:seenn_flutter/seenn_flutter.dart';

// Initialize
final seenn = Seenn(SeennConfig(
  publicKey: 'pk_live_xxx',
  baseUrl: 'https://api.seenn.io',
));

// Connect for a user
await seenn.connect(userId: 'user_123');

// Subscribe to a job
final tracker = seenn.jobs.subscribe('job_abc');

tracker.onProgress.listen((update) {
  print('Progress: ${update.progress}%');
  print('ETA: ${update.etaFormatted}');
});

tracker.onComplete.listen((job) {
  print('Job completed!');
});

iOS Live Activity

// Start Live Activity
await seenn.liveActivity.startActivity(
  jobId: 'job_abc',
  title: 'Processing video...',
);

// Auto-sync with job updates
seenn.jobs.stream('job_abc').listen((job) {
  if (job != null) {
    seenn.liveActivity.updateActivity(
      jobId: job.id,
      progress: job.progress,
      message: job.message,
    );
  }
});

iOS Setup

Add to ios/Runner/Info.plist:

<key>NSSupportsLiveActivities</key>
<true/>

Provisional Push (iOS 12+)

Request push notifications without showing a permission prompt:

import 'package:seenn_flutter/seenn_flutter.dart';

// Check current status
final status = await LiveActivity.getPushAuthorizationStatus();
print(status.status);        // PushAuthorizationStatus.provisional
print(status.isProvisional); // true if quiet notifications

// Request provisional push (no prompt!)
final granted = await LiveActivity.requestProvisionalPushAuthorization();
if (granted) {
  print('Provisional push enabled');
}

// Later: upgrade to full push when ready
if (status.canRequestFullAuthorization) {
  await LiveActivity.upgradeToStandardPush(); // Shows prompt
}

Note: Provisional notifications appear silently in Notification Center only. Users can "Keep" or "Turn Off" from their first notification.

Error Handling

All Live Activity operations return results with error codes for programmatic handling:

import 'package:seenn_flutter/seenn_flutter.dart';

print('SDK Version: $sdkVersion'); // '0.8.4'

final result = await LiveActivity.start(
  jobId: 'job_123',
  title: 'Processing...',
  jobType: 'video',
);

if (!result.success) {
  switch (result.code) {
    case SeennErrorCode.platformNotSupported:
      print('Not on iOS');
      break;
    case SeennErrorCode.invalidJobId:
      print('Invalid job ID');
      break;
    case SeennErrorCode.bridgeNotRegistered:
      print('Native setup incomplete');
      break;
    default:
      print('Error [${result.code}]: ${result.error}');
  }
}

Android Ongoing Notification

// Start notification
await seenn.ongoingNotification.startNotification(
  jobId: 'job_abc',
  title: 'Processing',
  message: 'Starting...',
);

// Update progress
await seenn.ongoingNotification.updateNotification(
  jobId: 'job_abc',
  progress: 50,
  message: 'Halfway there...',
);

// End notification
await seenn.ongoingNotification.endNotification(
  jobId: 'job_abc',
  title: 'Complete',
  message: 'Your video is ready!',
);

Cross-Platform Notifications

Use JobNotificationService for unified iOS + Android handling:

// Automatically uses Live Activity on iOS, Ongoing Notification on Android
await seenn.jobNotification.startNotification(
  jobId: 'job_abc',
  title: 'Processing',
  message: 'Starting...',
);

// Sync with job updates
await seenn.jobNotification.syncWithJob(job);

ETA Countdown

// Get countdown stream
final countdown = etaCountdownStream(
  job: job,
  intervalMs: 1000,
);

countdown.listen((state) {
  print('Remaining: ${state.formatted}'); // "2:34"
  print('Past due: ${state.isPastDue}');
  print('Confidence: ${state.confidence}'); // 0.0 - 1.0
});

Parent-Child Jobs

// Get parent jobs
final parents = seenn.jobs.parents;

// Get children of a parent
final children = seenn.jobs.childrenOf('parent_job_id');

// Stream child progress
tracker.onChildProgress.listen((update) {
  print('${update.completed}/${update.total} complete');
  print('${update.failed} failed');
});

Job Filtering

// By status
final active = seenn.jobs.active;
final completed = seenn.jobs.byStatus(JobStatus.completed);

// Reactive streams
seenn.jobs.active$.listen((jobs) {
  print('Active jobs: ${jobs.length}');
});

Connection Management

// Check connection state
seenn.connection$.listen((state) {
  print('Connected: ${state.isConnected}');
});

// Manual reconnect
await seenn.reconnect();

// Disconnect
await seenn.disconnect();

Documentation

Requirements

  • Flutter >= 3.10.0
  • Dart >= 3.0.0
  • iOS 16.2+ (for Live Activity with push updates)
  • Android API 21+ (for Ongoing Notification)

Why iOS 16.2? While Live Activities were introduced in iOS 16.1, the push token API (pushType: .token) and ActivityContent struct required for remote backend updates were added in iOS 16.2.

License

MIT License - see LICENSE for details.

Libraries

seenn_flutter
Seenn Flutter SDK Real-time job progress tracking with Polling, Live Activity (iOS), and Ongoing Notification (Android) support.