mirror of
https://github.com/foss42/apidash.git
synced 2025-12-01 18:28:25 +08:00
feat: implement scroll controller to scroll to the bottom
This commit is contained in:
@@ -18,6 +18,7 @@ class ChatScreen extends ConsumerStatefulWidget {
|
||||
|
||||
class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
final TextEditingController _textController = TextEditingController();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
bool _showTaskSuggestions = false;
|
||||
|
||||
@override
|
||||
@@ -34,12 +35,36 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textController.dispose();
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||
if (_scrollController.hasClients) {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ref.listen(chatViewmodelProvider, (prev, next) {
|
||||
if (next.isGenerating) {
|
||||
_showTaskSuggestions = false;
|
||||
}
|
||||
// Scroll to bottom when new message is added or streaming updates
|
||||
if (prev?.currentStreamingResponse != next.currentStreamingResponse ||
|
||||
(prev != null && prev.isGenerating && !next.isGenerating)) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
@@ -54,23 +79,28 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
if (msgs.isEmpty && !state.isGenerating) {
|
||||
return const Center(child: Text('Ask me anything!'));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: msgs.length + (state.isGenerating ? 1 : 0),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
itemBuilder: (context, index) {
|
||||
if (state.isGenerating && index == msgs.length) {
|
||||
return Scrollbar(
|
||||
controller: _scrollController,
|
||||
thumbVisibility: true,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: msgs.length + (state.isGenerating ? 1 : 0),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
itemBuilder: (context, index) {
|
||||
if (state.isGenerating && index == msgs.length) {
|
||||
return ChatBubble(
|
||||
message: state.currentStreamingResponse,
|
||||
role: MessageRole.system,
|
||||
);
|
||||
}
|
||||
final message = msgs[index];
|
||||
return ChatBubble(
|
||||
message: state.currentStreamingResponse,
|
||||
role: MessageRole.system,
|
||||
message: message.content,
|
||||
role: message.role,
|
||||
actions: message.actions,
|
||||
);
|
||||
}
|
||||
final message = msgs[index];
|
||||
return ChatBubble(
|
||||
message: message.content,
|
||||
role: message.role,
|
||||
actions: message.actions,
|
||||
);
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -80,7 +110,10 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
height: 5,
|
||||
thickness: 6,
|
||||
),
|
||||
if (_showTaskSuggestions) DashbotTaskButtons(),
|
||||
if (_showTaskSuggestions)
|
||||
DashbotTaskButtons(
|
||||
onTaskSelected: _scrollToBottom,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
@@ -128,6 +161,7 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
text: text,
|
||||
type: ChatMessageType.general,
|
||||
);
|
||||
_scrollToBottom();
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -145,6 +179,7 @@ class _ChatScreenState extends ConsumerState<ChatScreen> {
|
||||
text: text,
|
||||
type: ChatMessageType.general,
|
||||
);
|
||||
_scrollToBottom();
|
||||
},
|
||||
tooltip: 'Send message',
|
||||
),
|
||||
|
||||
@@ -11,7 +11,9 @@ import '../../../home/view/widgets/home_screen_task_button.dart';
|
||||
import '../../../../core/providers/dashbot_window_notifier.dart';
|
||||
|
||||
class DashbotTaskButtons extends ConsumerWidget {
|
||||
const DashbotTaskButtons({super.key});
|
||||
final VoidCallback? onTaskSelected;
|
||||
|
||||
const DashbotTaskButtons({super.key, this.onTaskSelected});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -37,42 +39,49 @@ class DashbotTaskButtons extends ConsumerWidget {
|
||||
label: '🔎 Explain me this response',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.explainResponse);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '🐞 Help me debug this error',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.debugError);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '📄 Generate documentation',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.generateDoc);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '📝 Generate Tests',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.generateTest);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '🧩 Generate Code',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.generateCode);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '📥 Import cURL',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.importCurl);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
label: '📄 Import OpenAPI',
|
||||
onPressed: () {
|
||||
vm.sendTaskMessage(ChatMessageType.importOpenApi);
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
@@ -83,6 +92,7 @@ class DashbotTaskButtons extends ConsumerWidget {
|
||||
notifier.hide();
|
||||
await GenerateToolDialog.show(context, ref);
|
||||
notifier.show();
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
HomeScreenTaskButton(
|
||||
@@ -107,6 +117,7 @@ class DashbotTaskButtons extends ConsumerWidget {
|
||||
);
|
||||
}
|
||||
notifier.show();
|
||||
onTaskSelected?.call();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user