Introduce message kinds, and handle them appropriately in user and agent chat
This commit is contained in:
1 parent
cba41f1e7e
commit
396b06b05c
4 files changed
+89
-18
No files matched your search
@@ -25,12 +25,34 @@ class Message extends ChatEntry {
|
||||
|
||||
class ThreadHeader extends ChatEntry {
|
||||
final int threadId;
|
||||
final int messageCount;
|
||||
int messageCount;
|
||||
|
||||
ThreadHeader({required this.threadId, required this.messageCount})
|
||||
: super(content: "Thread ($messageCount messages)", isFromUser: false);
|
||||
}
|
||||
|
||||
class NoteMessage extends Message {
|
||||
NoteMessage({sender, content, id, threadId}) :
|
||||
super(sender: sender, content: content, id: id, threadId: threadId);
|
||||
}
|
||||
class HiddenMessage extends Message {
|
||||
HiddenMessage({sender, content, id, threadId}) :
|
||||
super(sender: sender, content: content, id: id, threadId: threadId);
|
||||
}
|
||||
|
||||
Message createMessageFromData (Map<String, dynamic> data) {
|
||||
switch (data['kind']) {
|
||||
case 'message':
|
||||
return Message(sender: data['sender'], content: data['content'], threadId: data['threadId']);
|
||||
break;
|
||||
case 'note':
|
||||
return NoteMessage(sender: data['sender'], content: data['content'], threadId: data['threadId']);
|
||||
break;
|
||||
default:
|
||||
return HiddenMessage(sender: data['sender'], content: data['content'], threadId: data['threadId']);
|
||||
}
|
||||
}
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
final int chatId;
|
||||
|
||||
@@ -39,9 +61,7 @@ class ChatScreen extends StatefulWidget {
|
||||
static Future<List<Message>> getChatMessages(int chatId) async {
|
||||
final response = await Backend.sendAction("get-chat-messages", {'chatId': chatId});
|
||||
List<dynamic> messageObjects = response['messages'];
|
||||
List<Message> messages = messageObjects.map((msg) =>
|
||||
Message(sender: msg['sender'], content: msg['content'], id: msg['id'], threadId: msg['threadId'])
|
||||
).toList();
|
||||
List<Message> messages = messageObjects.map((msg) => createMessageFromData(msg)).toList();
|
||||
return messages;
|
||||
}
|
||||
|
||||
@@ -58,6 +78,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
// UI State
|
||||
Set<int> expandedThreads = {};
|
||||
int? editingMessageId = null;
|
||||
bool noteMode = false;
|
||||
|
||||
// Internal Funcionality
|
||||
Offset? _longPressOffset;
|
||||
@@ -70,7 +91,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
super.initState();
|
||||
_loadInitialData();
|
||||
_chatSubscription = Backend.chatMessages(widget.chatId).listen((data) {
|
||||
final message = Message(sender: data['sender'], content: data['content'], threadId: data['threadId']);
|
||||
final message = createMessageFromData(data);
|
||||
if (!message.isFromUser) {
|
||||
addMessage(message);
|
||||
}
|
||||
@@ -117,8 +138,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
|
||||
// Second pass: Build the display list with correct ordering
|
||||
for (var message in _messages) {
|
||||
if (message.threadId == null) {
|
||||
// Non-threaded messages go directly to the result
|
||||
if (message is NoteMessage || message.threadId == null) {
|
||||
// Non-threaded messages and notes go directly to the result
|
||||
result.add(message);
|
||||
} else {
|
||||
final threadId = message.threadId!;
|
||||
@@ -164,29 +185,40 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
'chatId': widget.chatId,
|
||||
'content': content,
|
||||
'threadId': currentThreadId,
|
||||
'kind': noteMode ? 'note' : null,
|
||||
}).then((response) {
|
||||
if (response['error'] != null) {
|
||||
print("Error sending chat message: ${response['error']}");
|
||||
}
|
||||
});
|
||||
|
||||
final newMessage = Message(sender: "user", content: content, threadId: currentThreadId);
|
||||
final newMessage = noteMode ?
|
||||
NoteMessage(sender: "user", content: content, threadId: currentThreadId) :
|
||||
Message(sender: "user", content: content, threadId: currentThreadId);
|
||||
addMessage(newMessage);
|
||||
} else {
|
||||
Message message = _messages.firstWhere((element) => element.id == editingMessageId!);
|
||||
|
||||
Backend.sendAction("update-chat-message", {
|
||||
'messageId': editingMessageId,
|
||||
'content': content,
|
||||
'kind': noteMode ? 'note' : null,
|
||||
}).then((response) {
|
||||
if (response['error'] != null) {
|
||||
print("Error updating message: ${response['error']}");
|
||||
}
|
||||
});
|
||||
|
||||
Message message = _messages.firstWhere((element) => element.id == editingMessageId!);
|
||||
setState(() {
|
||||
message.content = content;
|
||||
});
|
||||
}
|
||||
|
||||
if (noteMode) {
|
||||
setState(() {
|
||||
noteMode = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void createThread () async {
|
||||
@@ -276,6 +308,18 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isWideScreen = MediaQuery.of(context).size.width > 600;
|
||||
final String? editInfo;
|
||||
if (editingMessageId != null) {
|
||||
if (noteMode) {
|
||||
editInfo = 'Editing Note ${editingMessageId}';
|
||||
} else {
|
||||
editInfo = 'Editing ${editingMessageId}';
|
||||
}
|
||||
} else if (noteMode) {
|
||||
editInfo = 'Editing Note';
|
||||
} else {
|
||||
editInfo = null;
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -297,6 +341,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
if (entry is ThreadHeader) {
|
||||
return _buildThreadHeader(context, entry);
|
||||
} else if (entry is Message) {
|
||||
final isNote = entry is NoteMessage;
|
||||
final message = entry as Message;
|
||||
return GestureDetector(
|
||||
onLongPressStart: (details) {
|
||||
@@ -318,7 +363,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: getMessageColor(context),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(isNote ? 0 : 12),
|
||||
border: isNote ? Border.all(color: Colors.white) : null,
|
||||
),
|
||||
child: SelectableText(
|
||||
message.content,
|
||||
@@ -343,8 +389,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
if (editingMessageId!= null) ...[
|
||||
Text('Editing ${editingMessageId}'),
|
||||
if (editInfo != null) ...[
|
||||
Text(editInfo!),
|
||||
],
|
||||
Expanded(
|
||||
child: KeyboardListener(
|
||||
@@ -380,6 +426,14 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
},
|
||||
child: Text('Start New Topic'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
noteMode = !noteMode;
|
||||
});
|
||||
},
|
||||
child: Text(noteMode ? 'Switch to Message' : 'Make Note'),
|
||||
),
|
||||
if (editingMessageId!= null) ...[
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
|
||||
Reference in new issue
Block a user