orki_webchat 0.1.0
orki_webchat: ^0.1.0 copied to clipboard
Official Flutter SDK for the Orki webchat — a WebView widget hosting the Orki chat UI, plus a headless OrkiChatClient for custom chat UIs. Supports authenticated identity via tenant-signed JWTs (setUs [...]
example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:orki_webchat/orki_webchat.dart';
// Android emulator reaches the host machine via 10.0.2.2. The vite dev server
// proxies /extchat and /public to the local Orki stack. A physical phone on the
// same LAN would use the host's LAN IP instead.
const String kBaseUrl = String.fromEnvironment('ORKI_BASE_URL', defaultValue: 'http://10.0.2.2:5173');
const String kTenantId = String.fromEnvironment('ORKI_TENANT_ID', defaultValue: '');
const String kIntegrationId = String.fromEnvironment('ORKI_INTEGRATION_ID', defaultValue: '');
// Dev-only helper endpoint on the host that mints a tenant-signed JWT (stands in
// for "your backend"). A real app calls its own authenticated API for this.
const String kMintUrl = String.fromEnvironment('ORKI_MINT_URL', defaultValue: 'http://10.0.2.2:8787/jwt');
void main() => runApp(const DemoApp());
class DemoApp extends StatelessWidget {
const DemoApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Orki Webchat Demo',
theme: ThemeData(colorSchemeSeed: const Color(0xFF1A73E8), useMaterial3: true),
home: const ChatScreen(),
);
}
class ChatScreen extends StatefulWidget {
const ChatScreen({super.key});
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final controller = OrkiWebchatController();
final events = <String>[];
void _log(String line) {
// Also to logcat so an automated run can assert on events.
// ignore: avoid_print
print('ORKI_DEMO_EVENT $line');
setState(() {
events.insert(0, line);
if (events.length > 6) events.removeLast();
});
}
Future<void> _signIn({bool refresh = false}) async {
try {
final response = await http.get(Uri.parse(kMintUrl));
final jwt = (jsonDecode(response.body) as Map<String, dynamic>)['jwt'] as String;
refresh ? controller.updateToken(jwt) : controller.setUser(jwt);
_log(refresh ? 'sent updateToken' : 'sent setUser');
} catch (e) {
_log('mint failed: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Orki Webchat Demo'),
actions: [
IconButton(tooltip: 'Sign in', icon: const Icon(Icons.login), onPressed: () => _signIn()),
IconButton(tooltip: 'Refresh token', icon: const Icon(Icons.refresh), onPressed: () => _signIn(refresh: true)),
IconButton(tooltip: 'Logout', icon: const Icon(Icons.logout), onPressed: () {
controller.logout();
_log('sent logout');
}),
],
),
body: Column(
children: [
Expanded(
child: OrkiWebchatWidget(
baseUrl: kBaseUrl,
tenantId: kTenantId,
integrationId: kIntegrationId,
language: 'en',
controller: controller,
onEvent: (event) => _log(event.toString()),
),
),
if (events.isNotEmpty)
Container(
width: double.infinity,
color: Colors.black87,
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final e in events)
Text(e, style: const TextStyle(color: Colors.greenAccent, fontSize: 11, fontFamily: 'monospace')),
],
),
),
],
),
);
}
}