Documentation

    Listening for Events

    The Co-Browsing API Flutter SDK exposes all events as Dart Streams. Subscribe to them for reactive event handling.

    Listening for Events

    import 'dart:async';
    import 'package:upscopeio_flutter_sdk/upscopeio_flutter_sdk.dart';
    
    class MyWidget extends StatefulWidget {
      const MyWidget({super.key});
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      final List<StreamSubscription> _subscriptions = [];
    
      @override
      void initState() {
        super.initState();
    
        _subscriptions.add(
          Upscope.instance.connectionState.listen((state) {
            switch (state) {
              case ConnectionState.inactive:
                print('Inactive');
              case ConnectionState.connecting:
                print('Connecting...');
              case ConnectionState.connected:
                print('Connected');
              case ConnectionState.reconnecting:
                print('Reconnecting...');
              case ConnectionState.error:
                print('Error');
            }
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onSessionStarted.listen((_) {
            print('Session started');
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onSessionEnded.listen((reason) {
            switch (reason) {
              case SessionEndReason.userStopped:
                print('User ended session');
              case SessionEndReason.agentStopped:
                print('Agent ended session');
              case SessionEndReason.timeout:
                print('Session timed out');
              case SessionEndReason.error:
                print('Session error');
            }
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onCustomMessageReceived.listen((msg) {
            print('Message from ${msg.observerId}: ${msg.message}');
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onError.listen((error) {
            print('Error: ${error.code} - ${error.message}');
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onObserverJoined.listen((observer) {
            print('Observer joined: ${observer.name ?? observer.id}');
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onObserverLeft.listen((observerId) {
            print('Observer left: $observerId');
          }),
        );
    
        _subscriptions.add(
          Upscope.instance.onObserverCountChanged.listen((count) {
            print('Observers: $count');
          }),
        );
      }
    
      @override
      void dispose() {
        for (final sub in _subscriptions) {
          sub.cancel();
        }
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return const SizedBox.shrink();
      }
    }
    

    Event Reference

    StreamTypeDescription
    connectionStateConnectionStateConnection state changed.
    onSessionStartedString?A screen sharing session has started. Emits the agent's name, if available.
    onSessionEndedSessionEndReasonA session has ended. Reason indicates why (userStopped, agentStopped, timeout, or error).
    onCustomMessageReceivedCustomMessageA custom message was received from an observer. Includes message and observerId.
    onErrorUpscopeErrorAn SDK error occurred. Includes code and message.
    onObserverJoinedObserverAn agent started observing the session. The Observer includes id, name, screen dimensions, and focus state.
    onObserverLeftStringAn agent stopped observing the session. Emits the observer ID.
    onObserverCountChangedintThe total number of active observers changed.

    Using StreamBuilder

    For reactive UI updates, use StreamBuilder instead of manual subscriptions:

    StreamBuilder<ConnectionState>(
      stream: Upscope.instance.connectionState,
      builder: (context, snapshot) {
        if (!snapshot.hasData) return const SizedBox.shrink();
        return Text('Status: ${snapshot.data!.name}');
      },
    )