ebchat-mobile-flutter-sdk

Pub

Flutter chat screen for EBChat Andorid and IOS projects.

  • Uses Android SDK Version 12.5.1.
  • The minimum Android SDK minSdkVersion required is 21.
  • Uses iOS SDK Version 13.0.0.
  • The minimum iOS target version required is 13.

Permission

Files, camera and micro must be inculded in the package. If you wich to allow your users to send their current location ask for location permission also

Usage

Import package:ebchat/ebchat.dart and use the methods in EBChatService class.

main.dart:

import 'package:ebchat/ebchat.dart';
import 'package:flutter/material.dart';
import 'ebchat_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({
    Key? key,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MyHomePage();
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  //CLIENT
  String initalEbchatKey = "EBCHATKEY";
  StreamChatClient? ebchatClient;
  @override
  void didChangeDependencies() async {
    connectEBchatClient(initalEbchatKey);
    super.didChangeDependencies();
  }

  Future<void> connectEBchatClient(
    String? ebchatKey,
  ) async {
    if (ebchatClient != null) {
      EBChatService.disposeEbchatClient();
    }
    ebchatClient = await EBChatService.getWebsocketClient(ebchatKey!);
    setState(() {
      ebchatClient;
    });
    return;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EBCHAT Widget DEMO',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      builder: (context, child) {
        return Scaffold(
          body: ebchatClient != null
              ? StreamChat(
                  client: ebchatClient!,
                  streamChatThemeData: StreamChatThemeData(
                    messageListViewTheme: const StreamMessageListViewThemeData(
                      backgroundColor: Color(0xFFF8F8F8),
                    ),
                    channelListViewTheme: const StreamChannelListViewThemeData(
                      backgroundColor: Color(0xFFF8F8F8),
                    ),
                  ),
                  child: child,
                )
              : const Center(
                  child: Text("Please double check you EBCHATKEY"),
                ),
        );
      },
      home: Builder(builder: (context) {
        return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8.0),
                child: ElevatedButton(
                  onPressed: () => connectEBchatClient(initalEbchatKey).then(
                    (value) => Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => EbChatScreen(
                            ebchatClient: ebchatClient,
                            currentEbchatKey: initalEbchatKey),
                      ),
                    ),
                  ),
                  child: SizedBox(
                    height: 50,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: const [
                        Icon(Icons.chat),
                        SizedBox(
                          width: 7,
                        ),
                        Text("EBCHAT WIDGET",
                            style: TextStyle(
                                color: Colors.white,
                                fontWeight: FontWeight.w500,
                                fontSize: 13))
                      ],
                    ),
                  ),
                ),
              ),
            ]);
      }),
    );
  }
}


ebchat_screen.dart:

import 'package:ebchat/ebchat.dart';
import 'package:flutter/material.dart';

class EbChatScreen extends StatefulWidget {
  EbChatScreen(
      {Key? key, required this.ebchatClient, required this.currentEbchatKey})
      : super(key: key);
  StreamChatClient? ebchatClient;
  String currentEbchatKey;
  @override
  State<EbChatScreen> createState() => _EbChatScreenState();
}

class _EbChatScreenState extends State<EbChatScreen> {
  User? currentUser;
  String azureMapsApiKey = "AZUREMAPSKEY";
  //VAR FOR NOTIFICATIONS
  bool isFlutterLocalNotificationsInitialized = false;
  var flutterLocalNotificationsPlugin;

  @override
  void initState() {
    initilizeClient();

    ///IF YOU ARE USING FIREBASE TO HANDLE NOTIFICATION
    ///
    ///initializeFirebaseNotification();
    ///
    super.initState();
  }

  Future<void> initilizeClient() async {
    //TODO: THIS is an example how to access the stream and the client anywhere in the code
    StreamChatCoreState ebchatStream = StreamChatCore.of(context);
    currentUser = User(id: "johnnyTEST", name: "john", extraData: const {
      //TODO: THIS FIELD IS REQUIRED
      "email": "john@john.com",
      //TODO: you can store your user extrat attribute
      "phone": "+9743333333",
    });
    String getStreamToken = await ChatSerivice.getStreamUserToken(
        currentUser!.id, widget.currentEbchatKey);

    await ebchatStream.client.connectUser(
      User(id: currentUser!.id),
      getStreamToken,
    );
    ebchatStream.client
        .on(
      EventType.messageNew,
      EventType.notificationMessageNew,
    )
        .listen((event) {
      showNotifcation(event, context);
    });

    return;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        backgroundColor: const Color(0xff214496),
      ),
      body: widget.ebchatClient != null && currentUser != null
          ? EBChatWidget(
              key: Key(currentUser!.id),
              ebchatToken: widget.currentEbchatKey,
              client: widget.ebchatClient!,
              currentUser: currentUser!,
              azureMapsApiKey: azureMapsApiKey,
            )
          : const Center(
              child: CircularProgressIndicator(),
            ),
    );
  }

  //HANDLE NOTIFICATION

  void showNotifcation(Event event, BuildContext context) {
    if (![
      EventType.messageNew,
      EventType.notificationMessageNew,
    ].contains(event.type)) {
      return;
    }
    if (event.message == null) return;
    //TODO: add your logic to handle notifications
  }
}

IMPORTANT NOTES

  1. Handle notification using firebase
 void initializeFirebaseNotification() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;
    await setupLocalNotifications();
    await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );
    setAppToken(messaging).then((value) => messageListener(context));
  }

  Future<void> setAppToken(FirebaseMessaging messaging) async {
    String? token;
    token = await messaging.getToken();
    if (token != null) {
      await widget.ebchatClient!.addDevice(token, PushProvider.firebase);
    }
  }

  void messageListener(BuildContext context) {
    FirebaseMessaging.instance
        .getInitialMessage()
        .then((RemoteMessage? message) {
      if (message != null) {
        handleNotification(message, widget.ebchatClient!);
      }
    });
    FirebaseMessaging.onMessageOpenedApp.listen(onBackgroundMessageForMobile);
    FirebaseMessaging.onBackgroundMessage(onBackgroundMessageForMobile);
    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      Map<String, dynamic> data = message.data;
      if (data.containsKey('stream')) {
        data = Map<String, dynamic>.from(data["stream"]);
      }
      String? messageId = data['messageId'];

      if (messageId != null) {
        handleNotification(message, widget.ebchatClient!);
      }
    });
  }

  void handleNotification(
    RemoteMessage message,
    StreamChatClient chatClient,
  ) async {
    Map<String, dynamic> data = message.data;
    if (data.containsKey('stream')) {
      data = Map<String, dynamic>.from(data["stream"]);
    }
    if (data['type'] == 'message.new') {
      final messageId = data['id'];
      final response = await chatClient.getMessage(messageId);

      Channel channel =
          chatClient.channel("messaging", id: response.channel!.id);
      await channel.watch();
      flutterLocalNotificationsPlugin.show(
        generateUniqueRoomChatId(response.channel!.id),
        'New message from ${response.message.user!.name}',
        response.message.text,
        const NotificationDetails(
            android: AndroidNotificationDetails(
          'new_message',
          'New message notifications channel',
        )),
      );
    }
  }

  Future<void> setupLocalNotifications() async {
    if (isFlutterLocalNotificationsInitialized) {
      return;
    }
    flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('app_icon');
    DarwinInitializationSettings initializationSettingsDarwin =
        DarwinInitializationSettings(
            onDidReceiveLocalNotification: onDidReceiveLocalNotification);
    InitializationSettings initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsDarwin,
    );
    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse: (payload) {},
    );
    isFlutterLocalNotificationsInitialized = true;
  }

  Future<void> onBackgroundMessageForMobile(RemoteMessage? message) async {
    //TODO: We suggest to store this key. This key is very important 
    String? get_stream_ebchat_key=ChatSerivice.getEBchatWebSocket();
    if(get_stream_ebchat_key!=null && get_stream_ebchat_key!="")
    {final chatClient = StreamChatClient(get_stream_ebchat_key);
    //TODO: don't forget to store user id and token so you could connect him when reciving a background notification
    List<String> infos = await Config.getInfoFromSharedPref();
    if (infos[0].isNotEmpty) {
      await chatClient.connectUser(
        User(id: infos[0]),
        infos[1],
      );
      await Firebase.initializeApp(
          options: DefaultFirebaseOptions.currentPlatform);
      await setupLocalNotifications();
      handleNotification(message, chatClient);
    }}
  }

  void onDidReceiveLocalNotification(
      int? id, String? title, String? body, String? payload) async {
    // display a dialog with the notification details, tap ok to go to another page
  }

  int generateUniqueRoomChatId(String? a) {
    int length = a!.length;
    String? k = "";
    for (int x = 0; x < length - 1; x++) {
      if (int.tryParse(a[x].toString()) == null) {
        k = k! + a.codeUnitAt(x).toString();
      } else {
        k = k! + a[x].toString();
      }
    }
    return int.parse(k!.substring(1, 9));
  }
  1. Dispose or disconnect when logging out
//TODO: to dispose the client when you are done
  @override
  void dispose() {
     if (widget.ebchatClient != null) {
      StreamChatCore.of(context).client.disconnectUser().then((value) {
        widget.ebchatClient!.dispose();
        StreamChatCore.of(context).dispose();
        EBChatService.disposeEbchatClient();
      });
    }
    super.dispose();
  }
}

Libraries

ebchat