logo
On this page

Conversation component

The conversation component of the In-app Chat Kit provides the chat list and chat features.

Note
The Conversation component has already integrated the Message component. If you don't need the conversation list, you can directly use the Message component.
  • Chat list: Allow you to view the data of your chat list and support automatic update of the chat list based on chat messages.
  • Chat: Create one-on-one chats and group chats.

Integrate the conversation component into your project

Prerequisites

Integrate the In-app Chat Kit SDK into your project (finished the initialization and login are required). For more information, see Quick start.

Add the conversation component

In the file that needs to use the conversation component, use the ZIMKitConversationListView widget.

import 'package:zego_zimkit/zego_zimkit.dart';

// home_page.dart
class ZIMKitDemoHomePage extends StatelessWidget {
  const ZIMKitDemoHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Conversations'),
          actions: const [HomePagePopupMenuButton()],
        ),
        body: ZIMKitConversationListView(
          onPressed: (context, conversation, defaultAction) {
            Navigator.push(context, MaterialPageRoute(
              builder: (context) {
                return ZIMKitMessageListPage(
                  conversationID: conversation.id,
                  conversationType: conversation.type,
                );
              },
            ));
          },
        ),
      ),
    );
  }
}

Customize features/UI

If the default conversation-relevant features, behaviors or UI don’t fully meet your needs, we allow you to flexibly customize those through the parameters provided by the ZIMKitConversationListView mentioned in this section.

The usage of commonly used parameters is as follows:

To customize the press and long press events for a conversation, use the onPressed and onLongPress.

  • onPressed: usually, this callback is used to jump to the MessageListPage, and you can also customize other business logic for this press event.

    For example, you can implement paid chat feature by redefining the click event of the conversation list and modifying it to enter the chat after payment.

    ZIMKitConversationListView(
      onPressed: (context, conversation, defaultAction) {
        Navigator.push(context, MaterialPageRoute(
          builder: (context) {
            return ZIMKitMessageListPage(
              conversationID: conversation.id,
              conversationType: conversation.type,
            );
          },
        ));
      },
    )
  • onLongPress: use this to set the long press event for a conversation.

    When this callback is not set, the default behavior is to pop up a menu. You can choose to delete the conversation or exit the group (if the long-pressed conversation is a group chat). You can refer to the following to implement a custom long-press menu:

    ZIMKitConversationListView(
      onLongPress: (context, conversation, longPressDownDetails, defaultAction) {
        final conversationBox = context.findRenderObject()! as RenderBox;
        final offset = conversationBox.localToGlobal(Offset(0, conversationBox.size.height / 2));
    
        showMenu(
          context: context,
          position: RelativeRect.fromLTRB(
            longPressDownDetails.globalPosition.dx,
            offset.dy,
            longPressDownDetails.globalPosition.dx,
            offset.dy,
          ),
          items: [
            const PopupMenuItem(value: 0, child: Text('Delete')),
            if (conversation.type == ZIMConversationType.group) const PopupMenuItem(value: 1, child: Text('Quit'))
          ],
        ).then((value) {
          switch (value) {
            case 0:
              showDialog(
                context: context,
                builder: (context) {
                  return AlertDialog(
                    title: const Text('Confirm'),
                    content: const Text('Do you want to delete this conversation?'),
                    actions: [
                      TextButton(
                        onPressed: () => Navigator.pop(context),
                        child: const Text('Cancel'),
                      ),
                      TextButton(
                        onPressed: () {
                          ZIMKit().deleteConversation(conversation.id, conversation.type);
                          Navigator.pop(context);
                        },
                        child: const Text('OK'),
                      ),
                    ],
                  );
                },
              );
              break;
            case 1:
              showDialog(
                context: context,
                builder: (context) {
                  return AlertDialog(
                    title: const Text('Confirm'),
                    content: const Text('Do you want to leave this group?'),
                    actions: [
                      TextButton(
                        onPressed: () => Navigator.pop(context),
                        child: const Text('Cancel'),
                      ),
                      TextButton(
                        onPressed: () {
                          ZIMKit().leaveGroup(conversation.id);
                          Navigator.pop(context);
                        },
                        child: const Text('OK'),
                      ),
                    ],
                  );
                },
              );
              break;
          }
        });
      },
    )

The UI of each item in the conversation list can be fully customized, to do so, you can use the itemBuilder of ZIMKitConversationListView. The parameter types are as follows:

final Widget Function(BuildContext context, ZIMKitConversation conversation, Widget defaultWidget)? itemBuilder;

For example, replace each item in the default conversation list (ZIMKitConversationListView) with a custom TextButton.

ZIMKitConversationListView(
  itemBuilder: (context, conversation, defaultWidget) {
    return Center(
      child: TextButton(
        child: Text(conversation.name),
        onPressed: () {
          Navigator.push(context, MaterialPageRoute(
            builder: (context) {
              return ZIMKitMessageListPage(
                conversationID: conversation.id,
                conversationType: conversation.type,
              );
            },
          ));
        },
      ),
    );
  },
)
  1. filter: use this to set how to filter the conversations.
  2. sorter: use this to set how the conversation list sorts.
  3. errorBuilder: use this to customize the UI when error loading the message list.
  4. emptyBuilder: use this to customize the UI when the message list is empty.
  5. loadingBuilder: use this to customize the UI when loading the message list.
  6. lastMessageBuilder: use this to customize how the UI of the latest message of a conversation shows.
  7. lastMessageTimeBuilder: use this to customize how the UI of the latest message time of a conversation shows.

Conversastion API

You can use ZIMKit().deleteConversation(id,type) to delete conversation.

  1. If you only want to delete the conversations on this device, you can set isAlsoDeleteFromServer to false.
  2. If you want to delete a conversation along with its messages, you can set isAlsoDeleteMessages to true.
ZIMKit().deleteAllConversation(
  id,type,
  isAlsoDeleteFromServer: true,
  isAlsoDeleteMessages: true,
);

You can use ZIMKit().deleteAllConversation() to delete conversations.

If you only want to delete the conversations on this device, you can set isAlsoDeleteFromServer to false.

ZIMKit().deleteAllConversation(
  isAlsoDeleteFromServer: true,
  isAlsoDeleteMessages: true,
);

The following methods can be called using ZIMKit() syntax, such as ZIMKit().createGroup().

method prototype:

Future<String?> createGroup(String name, List<String> inviteUserIDs, {String id = ''}) 

This method return the new group's conversationID, If you specify an ID by the id param, the group will be created using the ID you specified.

method prototype:

Future<int> disbandGroup(String conversationID) 

This method return error code. 0 means success.

method prototype:

Future<int> joinGroup(String conversationID) 

This method return error code. 0 means success.

method prototype:

Future<int> leaveGroup(String conversationID) 

This method return error code. 0 means success.

method prototype:

Future<int> addUersToGroup(String conversationID, List<String> userIDs) 

This method return error code. 0 means success.

method prototype:

Future<int> removeUesrsFromGroup(String conversationID, List<String> userIDs) 

This method return error code. 0 means success.

method prototype:

ValueNotifier<ZIMKitGroupInfo> queryGroupInfo(String conversationID)

This method return ValueNotifier<ZIMKitGroupInfo>:

class ZIMKitGroupInfo {
  String notice = "";
  Map<String, String> attributes = {};
  ZIMGroupState state = ZIMGroupState.enter;
  ZIMGroupEvent event = ZIMGroupEvent.created;
}

method prototype:

ListNotifier<ZIMGroupMemberInfo> queryGroupMemberList(String conversationID)

This method return a ListNotifier, which can used by the ValueListenableBuilder, complete sample code can be found here.

method prototype:

Future<ZIMGroupMemberInfo?> queryGroupMemberInfo(String conversationID, String userID) 

method prototype:

Future<int> transferGroupOwner(String conversationID, String toUserID) 

This method return error code. 0 means success.

method prototype:

Future<int?> queryGroupMemberCount(String conversationID)

method prototype:

ValueNotifier<ZIMGroupMemberInfo?> queryGroupOwner(String conversationID)

method prototype:

// Return error code. 0 means success.
Future<int> setGroupMemberRole({required String conversationID, required String userID, required int role})

Role: 1 - owner, 2 - manager, 3 - member, others - If you need to customize group roles, please choose a number above 100. These roles have the same permissions as regular members.

Events: After setting the role, you can obtain the Role update event through the following two events:

  1. If you have already obtained the member list data through queryGroupMemberList, the role in the data will be automatically updated.
  2. You can also obtain the role update event separately by the getGroupMemberInfoUpdatedEventStream event.

Please refer to the usage of this interface in the demo's member_list_dialog.

The following methods can be called using ZIMKit() syntax, such as ZIMKit().getGroupStateChangedEventStream().listen(onGroupStateChangedEvent).

  1. In YourStatefulWidget's initState method, subscribe the event.
  2. When YourStatefulWidget is disposed, please remember to cancel subscribe.
class YourStatefulWidget extends StatefulWidget {
  const YourStatefulWidget({Key? key}) : super(key: key);

  @override
  State<YourStatefulWidget> createState() => YourStatefulWidgetState();
}

class YourStatefulWidgetState extends State<YourStatefulWidget> {
  List<StreamSubscription> sbuscriptions = [];


  // In the initState method, subscribe the event.
  @override
  void initState() {
    sbuscriptions = [
      if (widget.conversationType == ZIMConversationType.group)
        ZIMKit().getGroupStateChangedEventStream().listen(onGroupStateChangedEvent)
    ];
    super.initState();
  }

  // When the widget is disposed, please remember to cancel subscribe.
  @override
  void dispose() {
    for (final element in sbuscriptions) {
      element.cancel();
    }
    super.dispose();
  }

  Future<void> onGroupStateChangedEvent(ZIMKitEventGroupStateChanged event) async {
    debugPrint('getGroupStateChangedEventStream: $event');
    // If you need to automatically exit the page and delete the group
    // conversation that is already in the 'quit' state,
    // you can use this code here.

    // if ((event.groupInfo.baseInfo.id == widget.conversationID) && (event.state == ZIMGroupState.quit)) {
    //   debugPrint('app deleteConversation: $event');
    //   await ZIMKit().deleteConversation(widget.conversationID, widget.conversationType);
    //   if (mounted) {
    //     Navigator.pop(context);
    //   }
    // }
  }
}

Call this method to get the event stream

Stream<ZIMKitEventGroupStateChanged> getGroupStateChangedEventStream() 

The event prototype is :

This Event encapsulates the onGroupStateChanged callback of ZIM SDK.

class ZIMKitEventGroupStateChanged {
  ZIMKitEventGroupStateChanged({
    required this.state,
    required this.event,
    required this.operatedInfo,
    required this.groupInfo,
  });
  final ZIMGroupState state;
  final ZIMGroupEvent event;
  final ZIMGroupOperatedInfo operatedInfo;
  final ZIMGroupFullInfo groupInfo;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupNameUpdated> getGroupNameUpdatedEventStream() 

The event prototype is :

This Event encapsulates the onGroupNameUpdated callback of ZIM SDK.

class ZIMKitEventGroupNameUpdated {
  ZIMKitEventGroupNameUpdated({
    required this.groupName,
    required this.operatedInfo,
    required this.groupID,
  });
  final String groupName;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupAvatarUrlUpdated> getGroupAvatarUrlUpdatedEventStream() 

The event prototype is :

This Event encapsulates the onGroupAvatarUrlUpdated callback of ZIM SDK.

class ZIMKitEventGroupAvatarUrlUpdated {
  ZIMKitEventGroupAvatarUrlUpdated({
    required this.groupAvatarUrl,
    required this.operatedInfo,
    required this.groupID,
  });
  final String groupAvatarUrl;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupNoticeUpdated> getGroupNoticeUpdatedEventStream() 

The event prototype is :

This Event encapsulates the onGroupNoticeUpdated callback of ZIM SDK.

class ZIMKitEventGroupNoticeUpdated {
  ZIMKitEventGroupNoticeUpdated({
    required this.groupNotice,
    required this.operatedInfo,
    required this.groupID,
  });
  final String groupNotice;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupAttributesUpdated> getGroupAttributesUpdatedEventStream() 

The event prototype is :

This Event encapsulates the onGroupAttributesUpdated callback of ZIM SDK.

class ZIMKitEventGroupAttributesUpdated {
  ZIMKitEventGroupAttributesUpdated({
    required this.updateInfo,
    required this.operatedInfo,
    required this.groupID,
  });
  final List<ZIMGroupAttributesUpdateInfo> updateInfo;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupMemberStateChanged> getGroupMemberStateChangedEventStream() 

The event prototype is :

This Event encapsulates the onGroupMemberStateChanged callback of ZIM SDK.

class ZIMKitEventGroupMemberStateChanged {
  ZIMKitEventGroupMemberStateChanged({
    required this.state,
    required this.event,
    required this.userList,
    required this.operatedInfo,
    required this.groupID,
  });
  final ZIMGroupMemberState state;
  final ZIMGroupMemberEvent event;
  final List<ZIMGroupMemberInfo> userList;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Call this method to get the event stream

Stream<ZIMKitEventGroupMemberInfoUpdated> getGroupMemberInfoUpdatedEventStream() 

The event prototype is :

This Event encapsulates the onGroupMemberInfoUpdated callback of ZIM SDK.

class ZIMKitEventGroupMemberInfoUpdated {
  ZIMKitEventGroupMemberInfoUpdated({
    required this.userInfo,
    required this.operatedInfo,
    required this.groupID,
  });
  final List<ZIMGroupMemberInfo> userInfo;
  final ZIMGroupOperatedInfo operatedInfo;
  final String groupID;
}

Previous

Overview

Next

Message component

On this page

Back to top