noverachat_dart 0.7.0
noverachat_dart: ^0.7.0 copied to clipboard
Headless NoveraChat client core for Dart & Flutter — WebSocket + REST with optimistic UI, reconnection, and backfill. Pure client logic (events as Streams, sends as Futures); bring your own UI.
example/example.dart
// Minimal end-to-end example: connect → listen → send → disconnect.
//
// This is a plain Dart script (no Flutter). Run it from the package root:
//
// dart run example/example.dart
//
// It needs a running NoveraChat backend and a per-user JWT. Supply them via
// environment variables so nothing secret lives in the source:
//
// NOVERACHAT_ENDPOINT=https://chat.example.com \
// NOVERACHAT_APP_ID=app_9f8k2x \
// NOVERACHAT_TOKEN=<a per-user JWT from YOUR backend> \
// NOVERACHAT_ROOM=room_123 \
// dart run example/example.dart
//
// In a real app you never hard-code the token: `tokenProvider` fetches a fresh
// JWT from your backend on connect and on every reconnect. Here we read one
// from the environment just to keep the example runnable.
import 'dart:io';
import 'package:noverachat_dart/noverachat_dart.dart';
Future<void> main() async {
final endpoint = Platform.environment['NOVERACHAT_ENDPOINT'];
final appId = Platform.environment['NOVERACHAT_APP_ID'];
final token = Platform.environment['NOVERACHAT_TOKEN'];
final roomId = Platform.environment['NOVERACHAT_ROOM'] ?? 'room_123';
if (endpoint == null || appId == null || token == null) {
stderr.writeln(
'Set NOVERACHAT_ENDPOINT, NOVERACHAT_APP_ID and NOVERACHAT_TOKEN '
'(and optionally NOVERACHAT_ROOM) before running this example.',
);
exitCode = 64; // EX_USAGE
return;
}
final chat = NoveraChat(ClientOptions(
appId: appId,
endpoint: endpoint,
// In production this calls YOUR backend to mint a short-lived per-user JWT.
tokenProvider: () async => token,
// Optional: surface WS + REST + state transitions through one sink.
logger: (level, message, [ctx]) => print('[$level] $message'),
));
await chat.connect();
print('connected');
final room = chat.room(roomId);
// Inbound messages from other users arrive on a broadcast Stream.
// Subscribe before you send so you don't miss anything.
final sub = room.onMessage.listen((msg) {
print('← ${msg.senderId}: ${msg.content}');
});
// Optimistic send: `send` returns immediately with a temp id; `messageId`
// completes once the server acks with the real Snowflake id.
final sent = room.send('hello from the Dart example');
final messageId = await sent.messageId;
print('→ sent, server id = $messageId');
// Mark our own last-read position (debounced, monotonic).
room.markRead(messageId);
// Keep the socket open briefly to observe any inbound traffic, then clean up.
await Future<void>.delayed(const Duration(seconds: 5));
await sub.cancel();
await chat.disconnect();
print('disconnected');
}