Skip to content

Commit a76575f

Browse files
author
Franco Bugnano
committed
Implemented messageFilter for the ChatBox and feedFilter for the ConversationList
1 parent 3bf5522 commit a76575f

File tree

8 files changed

+486
-54
lines changed

8 files changed

+486
-54
lines changed

lib/src/chatbox.dart

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import './conversation.dart';
1111
import './chatoptions.dart';
1212
import './user.dart';
1313
import './message.dart';
14+
import './predicate.dart';
1415

1516
typedef SendMessageHandler = void Function(SendMessageEvent event);
1617
typedef TranslationToggledHandler = void Function(TranslationToggledEvent event);
@@ -49,6 +50,7 @@ class ChatBox extends StatefulWidget {
4950
final String? theme;
5051
final TranslateConversations? translateConversations;
5152
final List<String> highlightedWords = const <String>[];
53+
final MessagePredicate messageFilter;
5254

5355
final Conversation? conversation;
5456
final bool? asGuest;
@@ -66,6 +68,7 @@ class ChatBox extends StatefulWidget {
6668
this.theme,
6769
this.translateConversations,
6870
//this.highlightedWords = const <String>[], // Commented out due to bug #1953
71+
this.messageFilter = const MessagePredicate(),
6972
this.conversation,
7073
this.asGuest,
7174
this.onSendMessage,
@@ -104,6 +107,7 @@ class ChatBoxState extends State<ChatBox> {
104107
/// Objects stored for comparing changes
105108
ChatBoxOptions? _oldOptions;
106109
List<String> _oldHighlightedWords = [];
110+
MessagePredicate _oldMessageFilter = const MessagePredicate();
107111
bool? _oldAsGuest;
108112
Conversation? _oldConversation;
109113

@@ -121,7 +125,7 @@ class ChatBoxState extends State<ChatBox> {
121125

122126
_createSession();
123127
_createChatBox();
124-
_setHighlightedWords();
128+
// messageFilter and highlightedWords are set as options for the chatbox
125129
_createConversation();
126130

127131
execute('chatBox.mount(document.getElementById("talkjs-container"));');
@@ -134,9 +138,10 @@ class ChatBoxState extends State<ChatBox> {
134138
final chatBoxRecreated = _checkRecreateChatBox();
135139

136140
if (chatBoxRecreated) {
137-
_setHighlightedWords();
141+
// messageFilter and highlightedWords are set as options for the chatbox
138142
_createConversation();
139143
} else {
144+
_checkMessageFilter();
140145
_checkHighlightedWords();
141146
_checkRecreateConversation();
142147
}
@@ -187,6 +192,9 @@ class ChatBoxState extends State<ChatBox> {
187192
translateConversations: widget.translateConversations,
188193
);
189194

195+
_oldHighlightedWords = List<String>.of(widget.highlightedWords);
196+
_oldMessageFilter = MessagePredicate.of(widget.messageFilter);
197+
190198
execute('chatBox = session.createChatbox(${_oldOptions!.getJsonString(this)});');
191199

192200
execute('chatBox.on("sendMessage", (event) => JSCSendMessage.postMessage(JSON.stringify(event)));');
@@ -259,6 +267,22 @@ class ChatBoxState extends State<ChatBox> {
259267
return false;
260268
}
261269

270+
void _setMessageFilter() {
271+
_oldMessageFilter = MessagePredicate.of(widget.messageFilter);
272+
273+
execute('chatBox.setMessageFilter(${json.encode(_oldMessageFilter)});');
274+
}
275+
276+
bool _checkMessageFilter() {
277+
if (widget.messageFilter != _oldMessageFilter) {
278+
_setMessageFilter();
279+
280+
return true;
281+
}
282+
283+
return false;
284+
}
285+
262286
void _webViewCreatedCallback(WebViewController webViewController) async {
263287
if (kDebugMode) {
264288
print('📗 chatbox._webViewCreatedCallback');
@@ -420,6 +444,15 @@ class ChatBoxState extends State<ChatBox> {
420444
}
421445
}
422446

447+
/// For internal use only. Implementation detail that may change anytime.
448+
///
449+
/// Sets the options for ChatBoxOptions for the properties where there exists
450+
/// both a declarative option and an imperative method
451+
void setExtraOptions(Map<String, dynamic> result) {
452+
result['highlightedWords'] = widget.highlightedWords;
453+
result['messageFilter'] = widget.messageFilter;
454+
}
455+
423456
/// For internal use only. Implementation detail that may change anytime.
424457
///
425458
/// Evaluates the JavaScript statement given.
@@ -438,32 +471,3 @@ class ChatBoxState extends State<ChatBox> {
438471
}
439472
}
440473

441-
/// Encapsulates the message entry field tied to the currently selected conversation.
442-
class MessageField {
443-
/// The ChatBox associated with this message field
444-
ChatBoxState chatbox;
445-
446-
/// The JavaScript variable name for this object.
447-
String variableName;
448-
449-
MessageField({required this.chatbox, required this.variableName});
450-
451-
/// Focuses the message entry field.
452-
///
453-
/// Note that on mobile devices, this will cause the on-screen keyboard to pop up, obscuring part
454-
/// of the screen.
455-
void focus() {
456-
chatbox.execute('$variableName.focus();');
457-
}
458-
459-
/// Sets the message field to `text`.
460-
///
461-
/// Useful if you want to guide your user with message suggestions. If you want to start a UI
462-
/// with a given text showing immediately, call this method before calling Inbox.mount
463-
void setText(String text) {
464-
chatbox.execute('$variableName.setText("$text");');
465-
}
466-
467-
/// TODO: setVisible(visible: boolean | ConversationPredicate): void;
468-
}
469-

lib/src/chatoptions.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ class ChatBoxOptions {
223223
result['translateConversations'] = translateConversations!.getValue();
224224
}
225225

226+
chatBox.setExtraOptions(result);
227+
226228
return json.encode(result);
227229
}
228230

lib/src/conversation.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ class Conversation extends _BaseConversation {
125125
participants = Set<Participant>.of(other.participants.map((participant) => Participant.of(participant))),
126126
super(
127127
id: other.id,
128-
custom: other.custom != null ? Map<String, String?>.of(other.custom!) : null,
129-
welcomeMessages: other.welcomeMessages != null ? List<String>.of(other.welcomeMessages!) : null,
128+
custom: (other.custom != null ? Map<String, String?>.of(other.custom!) : null),
129+
welcomeMessages: (other.welcomeMessages != null ? List<String>.of(other.welcomeMessages!) : null),
130130
photoUrl: other.photoUrl,
131131
subject: other.subject
132132
);
@@ -199,8 +199,8 @@ class Conversation extends _BaseConversation {
199199
class ConversationData extends _BaseConversation {
200200
ConversationData.fromJson(Map<String, dynamic> json)
201201
: super(id: json['id'],
202-
custom: json['custom'] != null ? Map<String, String?>.from(json['custom']) : null,
203-
welcomeMessages: json['welcomeMessages'] != null ? List<String>.from(json['welcomeMessages']) : null,
202+
custom: (json['custom'] != null ? Map<String, String?>.from(json['custom']) : null),
203+
welcomeMessages: (json['welcomeMessages'] != null ? List<String>.from(json['welcomeMessages']) : null),
204204
photoUrl: json['photoUrl'],
205205
subject: json['subject']);
206206
}

lib/src/conversationlist.dart

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:webview_flutter/webview_flutter.dart';
99
import './session.dart';
1010
import './conversation.dart';
1111
import './user.dart';
12+
import './predicate.dart';
1213

1314
typedef SelectConversationHandler = void Function(SelectConversationEvent event);
1415

@@ -36,16 +37,6 @@ class ConversationListOptions {
3637
/// NOT NEEDED FOR FLUTTER?
3738
//bool? useBrowserHistory;
3839

39-
/// Used to control which conversations are shown in the conversation feed, depending on access
40-
/// level, custom conversation attributes or message read status.
41-
///
42-
/// See ConversationPredicate for all available options.
43-
///
44-
/// You can also modify the filter on the fly using {@link Inbox.setFeedFilter}.
45-
///
46-
/// TODO: NOT YET IMPLEMENTED FOR FLUTTER
47-
//ConversationPredicate? feedFilter;
48-
4940
/// Whether to show a "Back" button at the top of the chat screen on mobile devices.
5041
///
5142
/// NOT NEEDED FOR FLUTTER?
@@ -73,6 +64,8 @@ class ConversationListOptions {
7364
result['theme'] = theme;
7465
}
7566

67+
conversationList.setExtraOptions(result);
68+
7669
return json.encode(result);
7770
}
7871
}
@@ -84,13 +77,16 @@ class ConversationList extends StatefulWidget {
8477

8578
final String? theme;
8679

80+
final ConversationPredicate feedFilter;
81+
8782
final SelectConversationHandler? onSelectConversation;
8883

8984
const ConversationList({
9085
Key? key,
9186
required this.session,
9287
this.showFeedHeader,
9388
this.theme,
89+
this.feedFilter = const ConversationPredicate(),
9490
this.onSelectConversation,
9591
}) : super(key: key);
9692

@@ -113,6 +109,9 @@ class ConversationListState extends State<ConversationList> {
113109
/// Talk.User object.
114110
final _users = <String, String>{};
115111

112+
/// Objects stored for comparing changes
113+
ConversationPredicate _oldFeedFilter = const ConversationPredicate();
114+
116115
@override
117116
Widget build(BuildContext context) {
118117
if (kDebugMode) {
@@ -124,8 +123,15 @@ class ConversationListState extends State<ConversationList> {
124123

125124
_createSession();
126125
_createConversationList();
126+
// feedFilter is set as an option for the inbox
127127

128128
execute('conversationList.mount(document.getElementById("talkjs-container"));');
129+
} else {
130+
// If it's not the first time that the widget is built,
131+
// then check what needs to be rebuilt
132+
133+
// TODO: If something has changed in the Session we should do something
134+
_checkFeedFilter();
129135
}
130136

131137
return WebView(
@@ -163,6 +169,8 @@ class ConversationListState extends State<ConversationList> {
163169
theme: widget.theme,
164170
);
165171

172+
_oldFeedFilter = ConversationPredicate.of(widget.feedFilter);
173+
166174
execute('const conversationList = session.createInbox(${options.getJsonString(this)});');
167175

168176
execute('''conversationList.on("selectConversation", (event) => {
@@ -171,6 +179,22 @@ class ConversationListState extends State<ConversationList> {
171179
}); ''');
172180
}
173181

182+
void _setFeedFilter() {
183+
_oldFeedFilter = ConversationPredicate.of(widget.feedFilter);
184+
185+
execute('conversationList.setFeedFilter(${json.encode(_oldFeedFilter)});');
186+
}
187+
188+
bool _checkFeedFilter() {
189+
if (widget.feedFilter != _oldFeedFilter) {
190+
_setFeedFilter();
191+
192+
return true;
193+
}
194+
195+
return false;
196+
}
197+
174198
void _webViewCreatedCallback(WebViewController webViewController) async {
175199
if (kDebugMode) {
176200
print('📗 conversationlist._webViewCreatedCallback');
@@ -246,6 +270,14 @@ class ConversationListState extends State<ConversationList> {
246270
return _users[user.id]!;
247271
}
248272

273+
/// For internal use only. Implementation detail that may change anytime.
274+
///
275+
/// Sets the options for ConversationListOptions for the properties where there exists
276+
/// both a declarative option and an imperative method
277+
void setExtraOptions(Map<String, dynamic> result) {
278+
result['feedFilter'] = widget.feedFilter;
279+
}
280+
249281
/// For internal use only. Implementation detail that may change anytime.
250282
///
251283
/// Evaluates the JavaScript statement given.

lib/src/message.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ class SentMessage {
4141
SentMessage.fromJson(Map<String, dynamic> json)
4242
: id = json['id'],
4343
conversationId = json['conversationId'],
44-
type = json['type'] == 'UserMessage' ? MessageType.UserMessage : MessageType.SystemMessage,
44+
type = (json['type'] == 'UserMessage' ? MessageType.UserMessage : MessageType.SystemMessage),
4545
readBy = List<String>.from(json['readBy']),
4646
senderId = json['senderId'],
4747
text = json['text'],
48-
attachment = json['attachment'] != null ? Attachment.fromJson(json['attachment']) : null,
49-
location = json['location'] != null ? List<double>.from(json['location']) : null;
48+
attachment = (json['attachment'] != null ? Attachment.fromJson(json['attachment']) : null),
49+
location = (json['location'] != null ? List<double>.from(json['location']) : null);
5050
}
5151

0 commit comments

Comments
 (0)