karam_messenger 0.1.0 copy "karam_messenger: ^0.1.0" to clipboard
karam_messenger: ^0.1.0 copied to clipboard

Karam messenger for Flutter: presents Karam's hosted customer-support messenger in a secured WebView, with identity, deep links and unread counts.

example/lib/main.dart

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:karam_messenger/karam_messenger.dart';

/// Your messenger app id (Karam portal → Settings → Developers).
const karamAppId = 'app_replace_with_your_app_id';

/// YOUR backend endpoint that returns a Karam identity token for the signed-in
/// user (signed with the app's identity secret — never ship the secret in the
/// app). See the README for the token format.
final identityTokenEndpoint = Uri.parse(
  'https://your-backend.example.com/karam/identity-token',
);

void main() {
  KaramMessenger.instance.init(
    const KaramMessengerConfig(
      appId: karamAppId,
      colorScheme: MessengerColorScheme.system,
    ),
  );
  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'Karam Messenger',
    theme: ThemeData(colorSchemeSeed: Colors.indigo),
    darkTheme: ThemeData(
      colorSchemeSeed: Colors.indigo,
      brightness: Brightness.dark,
    ),
    // One host, around the app's navigator.
    builder: (context, child) => KaramMessengerHost(child: child!),
    home: const HomeScreen(),
  );
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final _messenger = KaramMessenger.instance;
  final _conversationId = TextEditingController();
  late final StreamSubscription<MessengerEvent> _events;
  String? _userId;
  int? _unread;
  String? _status;

  @override
  void initState() {
    super.initState();
    _events = _messenger.events.listen((event) {
      // The user has probably read something: refresh the badge.
      if (event is MessengerDismissedEvent) unawaited(_refreshUnread());
      if (event is MessengerErrorEvent) {
        setState(() => _status = 'Messenger error: ${event.code}');
      }
    });
  }

  @override
  void dispose() {
    unawaited(_events.cancel());
    _conversationId.dispose();
    super.dispose();
  }

  /// Asks the host backend for a fresh token. The SDK calls this only when it
  /// needs one and never stores the result.
  Future<String> _fetchIdentityToken(String userId) async {
    final response = await http.post(
      identityTokenEndpoint,
      headers: {'content-type': 'application/json'},
      // A real app authenticates this request with ITS OWN session instead
      // of sending a user id.
      body: jsonEncode({'userId': userId}),
    );
    if (response.statusCode != 200) {
      throw Exception('token endpoint answered ${response.statusCode}');
    }
    return (jsonDecode(response.body) as Map<String, Object?>)['token']!
        as String;
  }

  void _signIn() {
    const userId = 'demo-user-42';
    _messenger.identify(tokenProvider: () => _fetchIdentityToken(userId));
    setState(() {
      _userId = userId;
      _status = null;
    });
    unawaited(_refreshUnread());
  }

  Future<void> _signOut() async {
    await _messenger.logout();
    setState(() {
      _userId = null;
      _unread = null;
      _status = null;
    });
  }

  Future<void> _refreshUnread() async {
    if (_userId == null) return;
    try {
      final count = await _messenger.getUnreadCount();
      if (mounted) setState(() => _unread = count);
    } on KaramMessengerException catch (error) {
      // `cancelled`: the user changed while the request was in flight.
      if (error.code == KaramMessengerErrorCode.cancelled || !mounted) return;
      setState(() => _status = 'Unread count: ${error.code.wireName}');
    }
  }

  void _openConversation() {
    try {
      _messenger.present(conversationId: _conversationId.text.trim());
    } on KaramMessengerException catch (error) {
      setState(() => _status = error.message);
    }
  }

  @override
  Widget build(BuildContext context) {
    final signedIn = _userId != null;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Karam Messenger'),
        actions: [
          IconButton(
            tooltip: 'Refresh unread count',
            onPressed: signedIn ? _refreshUnread : null,
            icon: Badge(
              isLabelVisible: (_unread ?? 0) > 0,
              label: Text('${_unread ?? 0}'),
              child: const Icon(Icons.chat_bubble_outline),
            ),
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(24),
        children: [
          SwitchListTile(
            title: const Text('Signed in'),
            subtitle: Text(signedIn ? 'As $_userId' : 'Anonymous visitor'),
            value: signedIn,
            onChanged: (on) => on ? _signIn() : _signOut(),
          ),
          const SizedBox(height: 16),
          FilledButton.icon(
            onPressed: _messenger.present,
            icon: const Icon(Icons.support_agent),
            label: const Text('Open messenger'),
          ),
          const SizedBox(height: 32),
          TextField(
            controller: _conversationId,
            decoration: const InputDecoration(
              labelText: 'Conversation id',
              hintText: '3f0c7a2e-5b1d-4c8e-9a7f-2d6b8e1c4a90',
            ),
          ),
          const SizedBox(height: 12),
          OutlinedButton(
            onPressed: _openConversation,
            child: const Text('Open conversation'),
          ),
          if (_status != null) ...[
            const SizedBox(height: 24),
            Text(
              _status!,
              style: TextStyle(color: Theme.of(context).colorScheme.error),
            ),
          ],
        ],
      ),
    );
  }
}
0
likes
140
points
22
downloads

Documentation

API reference

Publisher

verified publisherkaramai.co

Weekly Downloads

Karam messenger for Flutter: presents Karam's hosted customer-support messenger in a secured WebView, with identity, deep links and unread counts.

Homepage
Repository (GitHub)
View/report issues

Topics

#chat #customer-support #messenger #webview

License

MIT (license)

Dependencies

file_selector, flutter, http, image_picker, shared_preferences, url_launcher, webview_flutter, webview_flutter_android, webview_flutter_platform_interface, webview_flutter_wkwebview

More

Packages that depend on karam_messenger