socrits 0.3.0
socrits: ^0.3.0 copied to clipboard
Socrits SDK for Flutter - video & voice calls, call invitations (ring/accept), and in-app chat. Drop-in prebuilt UI kit plus a low-level core client.
example/lib/main.dart
// Minimal call app on the Socrits UIKit — the whole call flow in two lines.
//
// Connect, then `SocritsCallUI.instance.attach(...)` once: incoming calls ring,
// navigate to the call screen on accept, and tear down automatically. Place a
// call with `SocritsCallUI.instance.call(...)` or a `SocritsCallButton`.
//
// Run: flutter run (fill in your base URL + API key + a user id)
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:socrits/socrits.dart';
final navKey = GlobalKey<NavigatorState>();
void main() => runApp(const SocritsExampleApp());
class SocritsExampleApp extends StatelessWidget {
const SocritsExampleApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
navigatorKey: navKey, // lets SocritsCallUI show the ring + call screens
title: 'Socrits example',
theme: ThemeData.dark(useMaterial3: true),
home: const ConnectScreen(),
);
}
class ConnectScreen extends StatefulWidget {
const ConnectScreen({super.key});
@override
State<ConnectScreen> createState() => _ConnectScreenState();
}
class _ConnectScreenState extends State<ConnectScreen> {
// NOTE: for a trial only. In production your BACKEND mints the token
// (POST /v1/session with the API key) — never ship the key in the app.
final _baseUrl = TextEditingController(text: 'https://api.socrits.com');
final _apiKey = TextEditingController(text: 'sk_live_...');
final _userId = TextEditingController();
final _target = TextEditingController();
String _status = 'not connected';
bool _connected = false;
Future<String> _fetchToken() async {
final res = await http.post(
Uri.parse('${_baseUrl.text.trim()}/v1/session'),
headers: {'Content-Type': 'application/json', 'x-api-key': _apiKey.text.trim()},
body: jsonEncode({'userId': _userId.text.trim(), 'userName': _userId.text.trim()}),
);
return (jsonDecode(res.body) as Map<String, dynamic>)['token'] as String;
}
Future<void> _connect() async {
setState(() => _status = 'connecting…');
try {
final token = await _fetchToken();
final sc = Socrits(baseUrl: _baseUrl.text.trim());
await sc.connect(userToken: token);
// ── The entire call integration: wire it once. ──
SocritsCallUI.instance.attach(
client: sc,
navigatorKey: navKey,
selfName: _userId.text.trim(),
);
setState(() {
_connected = true;
_status = 'online as ${_userId.text.trim()}';
});
} catch (e) {
setState(() => _status = 'error: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Socrits example')),
body: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: [
TextField(controller: _baseUrl, decoration: const InputDecoration(labelText: 'Base URL')),
TextField(controller: _apiKey, decoration: const InputDecoration(labelText: 'API key (trial only)')),
TextField(controller: _userId, decoration: const InputDecoration(labelText: 'Your user ID')),
const SizedBox(height: 12),
FilledButton(onPressed: _connected ? null : _connect, child: const Text('Connect')),
const SizedBox(height: 6),
Text(_status, style: const TextStyle(fontFamily: 'monospace')),
const Divider(height: 40),
TextField(controller: _target, decoration: const InputDecoration(labelText: 'Call user ID')),
const SizedBox(height: 12),
Row(
children: [
// Start a call — SocritsCallUI shows the ring + call screens.
FilledButton.icon(
onPressed: _connected
? () => SocritsCallUI.instance.call(userId: _target.text.trim(), mode: CallMode.video)
: null,
icon: const Icon(Icons.videocam),
label: const Text('Video'),
),
const SizedBox(width: 12),
OutlinedButton.icon(
onPressed: _connected
? () => SocritsCallUI.instance.call(userId: _target.text.trim(), mode: CallMode.voice)
: null,
icon: const Icon(Icons.call),
label: const Text('Voice'),
),
],
),
const SizedBox(height: 24),
// …or a drop-in button that starts the call itself:
if (_connected)
Row(
children: [
const Text('Or a drop-in button: '),
SocritsCallButton(inviteeUserId: _target.text.trim(), isVideo: true),
],
),
],
),
),
);
}
}