inverge_websocket 1.0.1
inverge_websocket: ^1.0.1 copied to clipboard
Flutter SDK for the Inverge WebSocket service: room-based realtime over Socket.IO with an app-wide provider, context.socket, and auto room re-join.
inverge_websocket #
Flutter client SDK for the Inverge WebSocket service.
Room-based realtime messaging over Socket.IO with an app-wide provider,
context.socket access from any page, automatic reconnect and room re-join,
ack futures, and a connection-status stream.
- 🌐 Service: https://inverge.net/services/websocket
- 📊 Dashboard (usage & billing): https://wss.inverge.net
Features #
- 🔌 One-line app-wide setup with
WebSocketInitializer. - 📍
context.socketanywhere — plusInvergeWebSocket.instancefor blocs/services. - 🏠 Room helpers:
joinRoom/leaveRoom(and bulk), with automatic re-join after a reconnect (a fresh socket has no room membership — this fixes the classic "events stop after reconnect" bug). - ✅ Ack futures:
await socket.joinRoom(...),await socket.emitWithAck(...). - 📶
ConnectionStatusstream for reactive UI. - 🔁 Reconnect on app resume; optional disconnect on background.
- 🧭
Roomhelper to build recipient-scoped names (order:8821).
Install #
dependencies:
inverge_websocket: ^1.0.0
Quick start #
Wrap your app once near the root:
import 'package:inverge_websocket/inverge_websocket.dart';
WebSocketInitializer(
config: const InvergeWebSocketConfig(
baseUrl: 'https://websocket.inverge.net',
apiKey: 'your_api_key',
),
child: MaterialApp.router(routerConfig: appRouter),
);
Then use it from any page via context.socket:
@override
void initState() {
super.initState();
context.socket.joinRoom(Room.scoped('order', order.id));
context.socket.on('order.updated', _onUpdate);
}
@override
void dispose() {
context.socket.off('order.updated', _onUpdate);
context.socket.leaveRoom(Room.scoped('order', order.id));
super.dispose();
}
From a bloc/service (no BuildContext), use the singleton:
InvergeWebSocket.instance.emit('typing', {'orderId': 8821});
Rooms #
final socket = context.socket;
await socket.joinRoom('order:8821'); // returns the server ack
await socket.joinRooms(['order:8821', 'ops']);
await socket.leaveRoom('order:8821');
socket.joinedRooms; // currently tracked rooms
Joined rooms are remembered and re-joined automatically after a reconnect
(disable with rejoinRoomsOnReconnect: false). Calling joinRoom while
disconnected is fine — it joins on the next connect.
Scope rooms by recipient, not by topic. A room is a delivery list — join a room only if you want every message sent there. Use
Room.scoped('order', id)rather than one big room filtered by event name.
Events & acks #
socket.on('order.updated', (data) { /* ... */ });
socket.once('welcome', (data) { /* ... */ });
socket.off('order.updated'); // remove all handlers for event
socket.emit('typing', {'orderId': 8821}); // fire-and-forget
final ack = await socket.emitWithAck('ping', {}); // await the server ack
Connection status #
StreamBuilder<ConnectionStatus>(
stream: context.socket.statusStream,
initialData: context.socket.status,
builder: (context, snap) => Text(snap.data!.name),
);
context.socket.isConnected; // bool
context.socket.id; // current socket id (or null)
Configuration #
| Option | Default | Description |
|---|---|---|
baseUrl |
— | Service origin, e.g. https://websocket.inverge.net. |
apiKey |
— | Tenant key, sent in the handshake auth payload. |
transports |
['websocket','polling'] |
Socket.IO transports. |
autoConnect |
true |
Connect on initialize. |
reconnection |
true |
Enable Socket.IO reconnection. |
reconnectionAttempts |
5 |
Max attempts. |
reconnectionDelay |
1000ms |
Delay between attempts. |
connectTimeout |
20s |
Handshake timeout. |
ackTimeout |
10s |
Default timeout for ack emits. |
rejoinRoomsOnReconnect |
true |
Re-join tracked rooms after reconnect. |
enableLogging |
false |
Log lifecycle/room ops via debugPrint. |
extraAuth |
{} |
Extra fields merged into the handshake auth. |
query |
{} |
Extra connection query params. |
Lifecycle & ownership #
WebSocketInitializer(config: ...) creates and owns the client — it
connects on start, reconnects on resume, and disposes on teardown. To manage the
client yourself, build it and pass it in:
final client = InvergeWebSocket.initialize(config);
WebSocketInitializer.client(client: client, child: app);
Migrating from a hand-rolled manager #
Replace your singleton WebSocketManager + context.socket with this package:
WebSocketManager.instance→InvergeWebSocket.instance(orcontext.socket).- Hardcoded
Env.socketBaseUrl/Env.socketApiKey→InvergeWebSocketConfig. - Room joins now survive reconnects automatically, and join/leave return futures.
License #
MIT.