Skip to content

Commit d1ff7b6

Browse files
authored
Merge pull request #687 from Mobile-Artificial-Intelligence/chat_listener
Chat listener
2 parents 15fbe08 + 83c3185 commit d1ff7b6

File tree

5 files changed

+48
-44
lines changed

5 files changed

+48
-44
lines changed

lib/controllers/chat_controller.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ class ChatController extends ChangeNotifier {
161161
_rootKey = chat.id;
162162
}
163163

164+
_rootKey = _mapping.keys.firstWhere((key) => _mapping[key]!.parent == null);
165+
164166
notifyListeners();
165167
}
166168

lib/main.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ part 'widgets/dropdowns/theme_mode_dropdown.dart';
6363
part 'widgets/layout/main_drawer.dart';
6464

6565
part 'widgets/listeners/artificial_intelligence_listener.dart';
66+
part 'widgets/listeners/chat_listener.dart';
6667

6768
part 'widgets/message/message_view.dart';
6869
part 'widgets/message/message.dart';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
part of 'package:maid/main.dart';
2+
3+
class ChatListener extends StatelessWidget{
4+
final Widget Function(BuildContext context, Widget? child) builder;
5+
6+
const ChatListener({
7+
super.key,
8+
required this.builder,
9+
});
10+
11+
@override
12+
Widget build(BuildContext context) => ListenableBuilder(
13+
listenable: ChatController.instance,
14+
builder: builder,
15+
);
16+
17+
Widget buildMessageListener(int index) => ListenableBuilder(
18+
listenable: ChatController.instance.root.chain[index],
19+
builder: ChatController.instance.root.chain.length - 1 >= index
20+
? (context, child) => builder(context, child)
21+
: (context, child) => buildMessageListener(index + 1),
22+
);
23+
}

lib/widgets/message/message.dart

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,26 @@ part of 'package:maid/main.dart';
33
class MessageWidget extends StatefulWidget {
44
final ChatMessage node;
55

6-
/// The chain position is used to determine the position of the message in the chain.
7-
/// Where a position of 0 would indicate the bottom of the chain.
8-
final int chainPosition;
9-
106
ChatMessage get message => node.currentChild!;
117
int get siblingsIndex => node.currentChildIndex;
128
int get siblingCount => node.children.length;
139
bool get onNextEnabled => (siblingsIndex + 1) < siblingCount;
1410
bool get onPreviousEnabled => siblingsIndex > 0;
15-
bool get buildChild => node.currentChild?.currentChild != null && chainPosition > 0;
1611

1712
const MessageWidget({
1813
required super.key,
19-
required this.node,
20-
required this.chainPosition,
14+
required this.node
2115
});
2216

17+
factory MessageWidget.itemBuilder(int index) {
18+
final message = ChatController.instance.root.chain[index];
19+
20+
return MessageWidget(
21+
key: message.id,
22+
node: message,
23+
);
24+
}
25+
2326
@override
2427
State<MessageWidget> createState() => MessageWidgetState();
2528
}
@@ -103,25 +106,11 @@ class MessageWidgetState extends State<MessageWidget> {
103106
@override
104107
Widget build(BuildContext context) => ListenableBuilder(
105108
listenable: widget.node.currentChild ?? widget.node,
106-
builder: buildColumn
107-
);
108-
109-
Widget buildColumn(BuildContext context, Widget? child) => Column(
110-
children: [
111-
// Build the current node
112-
if (widget.node.currentChild != null) buildCurrentMessage(),
113-
114-
/// Builds the child node/s if it exists.
115-
if (widget.buildChild) MessageWidget(
116-
key: childKey,
117-
node: widget.node.currentChild!,
118-
chainPosition: widget.chainPosition - 1,
119-
),
120-
],
109+
builder: buildMessage
121110
);
122111

123112
// The buildCurrentMessage method will build the padding and the appropriate column based on the editing state.
124-
Widget buildCurrentMessage() => Padding(
113+
Widget buildMessage(BuildContext context, Widget? child) => Padding(
125114
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
126115
child: editing && !AIController.instance.busy ?
127116
buildMessageEditingColumn() :

lib/widgets/message/message_view.dart

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,7 @@ class MessageViewState extends State<MessageView> {
7373
void initState() {
7474
super.initState();
7575
controller.addListener(onScroll);
76-
77-
WidgetsBinding.instance.addPostFrameCallback((_) {
78-
final root = ChatController.instance.root;
79-
rootPosition = math.max(0, root.chain.length - maxMessages);
80-
controller.jumpTo(controller.position.maxScrollExtent);
81-
});
76+
rootPosition = math.max(0, ChatController.instance.root.chain.length - maxMessages);
8277
}
8378

8479
void onScroll() {
@@ -128,7 +123,7 @@ class MessageViewState extends State<MessageView> {
128123
if (rootPosition >= 0 && rootPosition < ChatController.instance.root.chain.length - maxMessages)
129124
buildClearButton(),
130125
Expanded(
131-
child: buildScrollView()
126+
child: buildSettingsListener()
132127
)
133128
],
134129
);
@@ -142,18 +137,12 @@ class MessageViewState extends State<MessageView> {
142137
)
143138
);
144139

145-
Widget buildScrollView() => SingleChildScrollView(
146-
controller: controller,
147-
child: buildChatListener(),
148-
);
149-
150-
Widget buildChatListener() => ListenableBuilder(
151-
listenable: ChatController.instance,
152-
builder: buildSettingsListener
140+
Widget buildSettingsListener() => ListenableBuilder(
141+
listenable: AppSettings.instance,
142+
builder: buildChatListener
153143
);
154144

155-
Widget buildSettingsListener(BuildContext context, Widget? child) => ListenableBuilder(
156-
listenable: AppSettings.instance,
145+
Widget buildChatListener(BuildContext context, Widget? child) => ChatListener(
157146
builder: buildMessage
158147
);
159148

@@ -178,10 +167,10 @@ class MessageViewState extends State<MessageView> {
178167
WidgetsBinding.instance.addPostFrameCallback(jumpToExtent);
179168
}
180169

181-
return MessageWidget(
182-
key: rootKey,
183-
node: localRoot,
184-
chainPosition: maxMessages - 1,
170+
return ListView.builder(
171+
controller: controller,
172+
itemBuilder: (context, index) => MessageWidget.itemBuilder(rootPosition + index),
173+
itemCount: math.min(maxMessages, ChatController.instance.root.chain.length - 1),
185174
);
186175
}
187176
}

0 commit comments

Comments
 (0)