small fix, don't worry about it

This commit is contained in:
Tomas Dvorak
2026-04-10 12:05:40 +02:00
parent 7b7ed0083f
commit 5ab2773f98
55 changed files with 3240 additions and 483 deletions
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import '../application/ai_chat_controller.dart';
class AIChatScreen extends ConsumerStatefulWidget {
@@ -64,7 +65,7 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
Expanded(
child: state.messages.isEmpty
? _buildEmptyState(context)
: _buildMessagesList(state.messages),
: _buildMessagesList(state.messages, state.isLoading),
),
// Error message
@@ -87,7 +88,7 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
color: Theme.of(context)
.colorScheme
.onSurface
.withValues(alpha:0.7),
.withValues(alpha: 0.7),
),
),
),
@@ -128,7 +129,7 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
Text(
'Ask for goal inspiration, motivation, or life advice',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurface.withValues(alpha:0.7),
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7),
),
textAlign: TextAlign.center,
),
@@ -174,12 +175,16 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
);
}
Widget _buildMessagesList(List messages) {
Widget _buildMessagesList(List messages, bool isLoading) {
return ListView.builder(
controller: _scrollController,
padding: const EdgeInsets.all(16),
itemCount: messages.length,
itemCount: messages.length + (isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index == messages.length && isLoading) {
return _buildLoadingIndicator();
}
final message = messages[index];
final isUser = message.role == 'user';
@@ -218,14 +223,29 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(20),
),
child: Text(
message.content,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: isUser
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
child: isUser
? Text(
message.content,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
)
: MarkdownBody(
data: message.content,
styleSheet: MarkdownStyleSheet.fromTheme(Theme.of(context)).copyWith(
p: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
code: Theme.of(context).textTheme.bodySmall?.copyWith(
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
codeblockDecoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(8),
),
),
),
),
),
if (isUser) ...[
@@ -245,6 +265,59 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
);
}
Widget _buildLoadingIndicator() {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
CircleAvatar(
radius: 16,
backgroundColor: Theme.of(context).colorScheme.primary,
child: Icon(
Icons.psychology,
size: 20,
color: Theme.of(context).colorScheme.onPrimary,
),
),
const SizedBox(width: 8),
Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.75,
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
const SizedBox(width: 8),
Text(
'AI is thinking...',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
),
],
),
);
}
Widget _buildErrorMessage(String error, controller) {
return Container(
margin: const EdgeInsets.all(16),
@@ -317,7 +390,7 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
color: Theme.of(context).colorScheme.surface,
boxShadow: [
BoxShadow(
color: Theme.of(context).shadowColor.withValues(alpha:0.1),
color: Theme.of(context).shadowColor.withValues(alpha: 0.1),
blurRadius: 8,
offset: const Offset(0, -2),
),
@@ -362,8 +435,8 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: state.isRecording
? Theme.of(context).colorScheme.error.withValues(alpha:0.12)
: Theme.of(context).colorScheme.primary.withValues(alpha:0.08),
? Theme.of(context).colorScheme.error.withValues(alpha: 0.12)
: Theme.of(context).colorScheme.primary.withValues(alpha: 0.08),
),
child: IconButton(
onPressed: state.isRecording
@@ -429,7 +502,7 @@ class _AIChatScreenState extends ConsumerState<AIChatScreen> {
color: Theme.of(context)
.colorScheme
.primary
.withValues(alpha:state.isLoading ||
.withValues(alpha: state.isLoading ||
_textController.text.trim().isEmpty
? 0.06
: 0.12),