Line data Source code
1 : library chatwoot_client_sdk;
2 :
3 : import 'package:chatwoot_client_sdk/chatwoot_callbacks.dart';
4 : import 'package:chatwoot_client_sdk/chatwoot_client.dart';
5 : import 'package:chatwoot_client_sdk/data/local/entity/chatwoot_message.dart';
6 : import 'package:chatwoot_client_sdk/data/local/entity/chatwoot_user.dart';
7 : import 'package:flutter/material.dart';
8 : import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
9 : import 'package:flutter_chat_ui/flutter_chat_ui.dart';
10 : import 'package:open_file/open_file.dart';
11 : import 'package:uuid/uuid.dart';
12 :
13 : class ChatwootChatPage extends StatefulWidget {
14 : final String baseUrl;
15 : final String inboxIdentifier;
16 : final bool enablePersisitence;
17 : final ChatwootUser? user;
18 0 : const ChatwootChatPage({
19 : Key? key,
20 : required this.baseUrl,
21 : required this.inboxIdentifier,
22 : this.enablePersisitence = true,
23 : this.user
24 0 : }) : super(key: key);
25 :
26 0 : @override
27 0 : _ChatwootChatPageState createState() => _ChatwootChatPageState();
28 : }
29 :
30 : class _ChatwootChatPageState extends State<ChatwootChatPage> {
31 : List<types.Message> _messages = [];
32 : final idGen = Uuid();
33 : late final _user;
34 : late final ChatwootClient chatwootClient;
35 :
36 : late final chatwootCallbacks;
37 :
38 0 : @override
39 : void initState() {
40 0 : super.initState();
41 :
42 0 : if(widget.user == null){
43 0 : _user = types.User(id: idGen.v4());
44 : }else{
45 0 : _user = types.User(
46 0 : id: widget.user?.identifier ?? idGen.v4(),
47 0 : firstName: widget.user?.name,
48 0 : imageUrl: widget.user?.avatarUrl,
49 : );
50 : }
51 :
52 0 : chatwootCallbacks = ChatwootCallbacks(
53 0 : onWelcome: (){},
54 0 : onPing: (){},
55 0 : onConfirmedSubscription: (){},
56 0 : onConversationStartedTyping: (){
57 :
58 : },
59 0 : onConversationStoppedTyping: (){
60 :
61 : },
62 0 : onPersistedMessagesRetrieved: (persistedMessages){
63 0 : if(widget.enablePersisitence){
64 0 : setState(() {
65 0 : _messages = persistedMessages.map((message)=> chatwootMessageToTextMessage(message)).toList();
66 : });
67 : }
68 : },
69 0 : onMessagesRetrieved: (messages){
70 0 : setState(() {
71 0 : final chatMessages = messages.map((message)=> chatwootMessageToTextMessage(message)).toList();
72 0 : final mergedMessages = [..._messages,chatMessages].toSet().toList() as List<types.Message>;
73 0 : final now = DateTime.now().millisecondsSinceEpoch;
74 0 : mergedMessages.sort((a,b){
75 0 : return (b.createdAt ?? now).compareTo(a.createdAt ?? now);
76 : });
77 : });
78 : },
79 0 : onMessageReceived: (chatwootMessage){
80 0 : _addMessage(chatwootMessageToTextMessage(chatwootMessage));
81 : },
82 0 : onMessageSent: (chatwootMessage, echoId){
83 0 : _handleMessageSent(chatwootMessageToTextMessage(chatwootMessage, echoId: echoId));
84 : },
85 0 : onError: (event){
86 0 : print("Ooops! Something went wrong. Error Cause: ${event.cause}");
87 : },
88 : );
89 :
90 :
91 0 : ChatwootClient.create(
92 0 : baseUrl: widget.baseUrl,
93 0 : inboxIdentifier: widget.inboxIdentifier,
94 0 : user: widget.user,
95 0 : callbacks: chatwootCallbacks
96 0 : ).then((client) {
97 0 : setState(() {
98 0 : chatwootClient = client;
99 0 : chatwootClient.loadMessages();
100 : });
101 0 : }).onError((error, stackTrace) {
102 0 : print(error);
103 : });
104 :
105 : }
106 :
107 0 : types.Message chatwootMessageToTextMessage(ChatwootMessage message, {String? echoId}){
108 0 : return types.TextMessage(
109 0 : id: echoId ?? idGen.v4(),
110 0 : author: message.isMine ? _user : types.User(
111 0 : id: message.sender?.id.toString() ?? idGen.v4(),
112 0 : firstName: message.sender?.name,
113 0 : imageUrl: message.sender?.avatarUrl ?? message.sender?.thumbnail,
114 : ),
115 0 : text: message.content ?? "",
116 : status: types.Status.seen
117 : );
118 : }
119 :
120 :
121 0 : void _addMessage(types.Message message) {
122 0 : setState(() {
123 0 : _messages.insert(0, message);
124 : });
125 : }
126 :
127 :
128 0 : void _handleMessageTap(types.Message message) async {
129 0 : if (message is types.FileMessage) {
130 0 : await OpenFile.open(message.uri);
131 : }
132 : }
133 :
134 0 : void _handlePreviewDataFetched(
135 : types.TextMessage message,
136 : types.PreviewData previewData,
137 : ) {
138 0 : final index = _messages.indexWhere((element) => element.id == message.id);
139 0 : final updatedMessage = _messages[index].copyWith(previewData: previewData);
140 :
141 0 : WidgetsBinding.instance?.addPostFrameCallback((_) {
142 0 : setState(() {
143 0 : _messages[index] = updatedMessage;
144 : });
145 : });
146 : }
147 :
148 0 : void _handleMessageSent(
149 : types.Message message,
150 : ) {
151 0 : final index = _messages.indexWhere((element) => element.id == message.id);
152 :
153 0 : WidgetsBinding.instance?.addPostFrameCallback((_) {
154 0 : setState(() {
155 0 : _messages[index] = message;
156 : });
157 : });
158 : }
159 :
160 0 : void _handleSendPressed(types.PartialText message) {
161 0 : final textMessage = types.TextMessage(
162 0 : author: _user,
163 0 : createdAt: DateTime.now().millisecondsSinceEpoch,
164 0 : id: const Uuid().v4(),
165 0 : text: message.text,
166 : );
167 :
168 0 : _addMessage(textMessage);
169 :
170 0 : chatwootClient.sendMessage(content: textMessage.text, echoId: textMessage.id);
171 :
172 : }
173 :
174 0 : @override
175 : Widget build(BuildContext context) {
176 0 : return Scaffold(
177 0 : body: Chat(
178 0 : messages: _messages,
179 0 : onMessageTap: _handleMessageTap,
180 0 : onPreviewDataFetched: _handlePreviewDataFetched,
181 0 : onSendPressed: _handleSendPressed,
182 0 : user: _user,
183 : ),
184 : );
185 : }
186 : }
187 :
|