v_chat_flutter

The recommended Flutter entry point for the V Chat end-user SDK. Release candidate 0.1.0-rc.6 supports Flutter >=3.38.0 and Dart >=3.10.0-0 <4.0.0.

This package exports v_chat_core and composes its REST/realtime client with Drift persistence, Flutter application lifecycle handling, and connectivity monitoring. It does not contain chat UI; add v_chat_sdk when you want the complete umbrella with optional widgets.

Installation

flutter pub add v_chat_flutter

Pin the exact release-candidate version in production applications and review the changelog before upgrading.

Credential boundary

Flutter code uses only short-lived app-user tokens obtained from your own authenticated backend. Never embed a V Chat application credential, dashboard session secret, or private signing key in a mobile, desktop, or web build.

Implement TokenProvider around your customer-backend token endpoint:

import 'package:v_chat_flutter/v_chat_flutter.dart';

final class BackendTokenProvider implements TokenProvider {
  BackendTokenProvider(this.fetchToken);

  final Future<AuthToken> Function({required bool forceRefresh}) fetchToken;

  @override
  Future<AuthToken> getToken({required bool forceRefresh}) {
    return fetchToken(forceRefresh: forceRefresh);
  }
}

The backend must authenticate the current application user and derive userId server-side. Do not accept an arbitrary user ID from the device and mint a token for it.

Quick start

final sdk = await VChatFlutterSdk.create(
  options: VChatClientOptions(
    appId: '00000000-0000-4000-8000-000000000001',
    apiBaseUri: Uri.parse('https://api.example.com'),
  ),
  tokenProvider: BackendTokenProvider(loadCurrentUserVChatToken),
  databaseName: 'vchat-current-profile',
);

sdk.lifecycleBinding.attach();

try {
  await sdk.client.connectUser(userId: currentUserId);

  final conversations = await sdk.client.queryCurrentUserConversations(
    limit: 25,
  );
  renderConversations(conversations.items);

  await sdk.client.connectRealtime();
} on VChatException catch (error) {
  renderSafeChatError(code: error.code, retriable: error.retriable);
} finally {
  await sdk.dispose();
}

Create one VChatFlutterSdk per logical signed-in app-user session. Await dispose() during logout, profile switching, or application-service shutdown; it detaches lifecycle observation, disposes the client, and closes the owned Drift database.

VChatClientOptions requires a UUID application ID and an HTTPS API base URI. Plain HTTP is rejected except for an explicitly enabled loopback development endpoint.

Client lifecycle

  1. Create the SDK and attach lifecycleBinding after Flutter bindings are available.
  2. Call connectUser(userId: ...) with the identity represented by the token provider.
  3. Use REST/cache APIs and optionally call connectRealtime().
  4. Use disconnect(clearLocalData: true) when logout must remove that exact user's cached data.
  5. Await sdk.dispose() when the SDK instance will not be reused.

Backgrounding suspends eligible realtime work; foregrounding resumes only a lifecycle that was actually suspended. Connectivity changes can wake bounded reconnect work, but mutations are never silently retried or queued for replay.

Main APIs

The sdk.client exposes both flat methods and stable resource facades:

Area Common entry points
Channels createChannel, getChannel, updateChannel, channel(identity)
Memberships queryCurrentUserMemberships, cached query and refresh methods
Messages sendMessage, queryMessages, update/delete, replies and threads
Reactions add/remove own reaction, list reaction users
Attachments client.attachments upload intent, transfer, complete, download, delete
Conversations client.conversations, unread summary, mark channel/thread read
Realtime connect/disconnect, channel subscriptions, typed event listeners, recovery
Activity connection-local presence and typing controllers on a subscription
Push client.push preferences, registrations, and notification routing
Privacy current-user export/delete job lifecycle when token capability allows it

Realtime follows the released realtime ticket and acknowledged authorized channel subscriptions contract. SDK-FL-010 typed durable events update the exact scoped cache before host callbacks; a subscription remains connection-local and reconnect restoration rechecks authorization.

Handles perform no I/O when created. Cached results may be stale and are never proof of current authorization or server completeness. Remote cursors remain opaque; pass them back unchanged.

Detailed source-confirmed examples live in v_chat_core and the repository's examples/v_chat_example application.

Custom database and connectivity

VChatFlutterSdk.create accepts these optional host integrations:

  • databaseName selects the package-owned Drift database name;
  • databaseExecutor supplies a custom Drift QueryExecutor when the host owns database setup;
  • connectivityMonitor supplies a custom VChatConnectivityMonitor; and
  • logger and clock provide safe diagnostics and deterministic time behavior.

When databaseExecutor is supplied, the SDK assumes ownership and closes it through sdk.dispose(). Do not share or reuse that executor after passing it to the SDK, and keep its platform setup compatible with Drift. Connectivity values are transport hints only. A connectivity hint does not prove Internet reachability. Ticket, socket, timeout, and reconnect behavior remain authoritative.

Push integration

The package is provider-neutral. Your host application still owns native permission prompts, Firebase/APNs configuration, token discovery, background handlers, and notification presentation. Adapt those provider callbacks through VChatPushTokenSource and, optionally, VChatPushNotificationSource:

final pushBinding = VChatPushIntegrationBinding(
  push: sdk.client.push,
  installationId: stableInstallationId,
  tokenSource: hostTokenSource,
  notificationSource: hostNotificationSource,
  onRoute: handleAcceptedVChatRoute,
  onDiagnostic: recordSafePushDiagnostic,
);

await pushBinding.attach();

// Before the authenticated user is logged out:
await pushBinding.revokeBeforeLogout();
await pushBinding.disposeAsync();

The binding serializes token updates, routes only the released content-light payload, and uses scoped durable receipt IDs to suppress duplicates. It never asks the SDK to persist provider tokens outside the released device-registration contract.

Errors, cancellation, and logging

Catch VChatException and its typed subclasses: configuration, validation, authentication, API, transport, protocol, storage, and lifecycle. Use stable code, retriable, retryAfter, and requestId fields for recovery; do not show raw server messages or log token-bearing objects.

Every relevant operation accepts VChatRequestOptions with an optional timeout, request ID, and VChatCancellationToken. Cancel obsolete page or screen work through VChatCancellationSource.

The default logger is a no-op. Custom loggers must remain redacted: never record tokens, application credentials, message text, attachment signed URLs, arbitrary payloads, or private notification data.

Platform expectations

The package is structured for Android, iOS, macOS, Windows, Linux, and web, subject to the selected Drift and connectivity plugin implementations. Run the target platform's integration/build checks before claiming production support; a Dart or widget test alone does not prove native database, network, lifecycle, or background-push behavior.

Support and security

Read the repository support, security, privacy, and realtime documentation before production adoption.

Libraries

v_chat_flutter