Skip to content

Commit

Permalink
load chat thread messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Dat-TG committed Dec 15, 2023
1 parent 11f7e74 commit c3febc6
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 138 deletions.
29 changes: 21 additions & 8 deletions lib/core/widgets/chat_thread.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import 'package:boilerplate/di/service_locator.dart';
import 'package:boilerplate/presentation/chat_screen/store/chat_store.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';

class ChatThreadWidget extends StatefulWidget {
final String name;
final int id;
final VoidCallback onTap;
const ChatThreadWidget({Key? key, required this.name, required this.onTap})
: super(key: key);
const ChatThreadWidget({
Key? key,
required this.name,
required this.onTap,
required this.id,
}) : super(key: key);

@override
State<ChatThreadWidget> createState() => _ChatThreadWidgetState();
}

class _ChatThreadWidgetState extends State<ChatThreadWidget> {
ChatStore _chatStore = getIt<ChatStore>();
@override
Widget build(BuildContext context) {
return GestureDetector(
Expand Down Expand Up @@ -49,12 +58,16 @@ class _ChatThreadWidgetState extends State<ChatThreadWidget> {
}
});
},
child: ListTile(
title: Text(widget.name),
onTap: () {
widget.onTap();
},
),
child: Observer(builder: (context) {
return ListTile(
tileColor: _chatStore.id == widget.id ? Colors.grey[700] : null,
textColor: _chatStore.id == widget.id ? Colors.white : null,
title: Text(widget.name),
onTap: () {
widget.onTap();
},
);
}),
);
}
}
8 changes: 5 additions & 3 deletions lib/core/widgets/main_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class MainDrawer extends StatefulWidget {
final Function setChatThreadId;
const MainDrawer({super.key, required this.setChatThreadId});
const MainDrawer({super.key});

@override
State<MainDrawer> createState() => _MainDrawerState();
Expand All @@ -33,7 +32,8 @@ class _MainDrawerState extends State<MainDrawer> {
title: Text('New chat'),
minLeadingWidth: 10,
onTap: () {
widget.setChatThreadId(null);
_chatStore.setChatThreadId(-1);
Navigator.pop(context);
},
),
Expanded(
Expand All @@ -49,8 +49,10 @@ class _MainDrawerState extends State<MainDrawer> {
.map(
(e) => ChatThreadWidget(
name: e.subject,
id: e.id,
onTap: () {
_chatStore.setChatThreadId(e.id);
Navigator.pop(context);
},
),
)
Expand Down
228 changes: 111 additions & 117 deletions lib/presentation/chat_screen/chat_screen.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import 'package:boilerplate/core/widgets/chat_input.dart';
import 'package:boilerplate/core/widgets/progress_indicator_widget.dart';
import 'package:boilerplate/di/service_locator.dart';
import 'package:boilerplate/domain/entity/message/message.dart';
import 'package:boilerplate/presentation/chat_screen/store/chat_store.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:intl/intl.dart';

class Message {
final String content;
final bool isGPT;
final DateTime createdAt;

Message({
required this.content,
required this.isGPT,
required this.createdAt,
});
}

class ChatScreen extends StatefulWidget {
final String chatThreadId;
const ChatScreen({super.key, required this.chatThreadId});
const ChatScreen({super.key});

@override
State<ChatScreen> createState() => _ChatScreenState();
Expand All @@ -43,126 +34,129 @@ class _ChatScreenState extends State<ChatScreen> {
}
}

List<Message> messages = [
Message(
content: 'How can I help you?', isGPT: true, createdAt: DateTime.now()),
Message(
content: 'I want to learn about Flutter',
isGPT: false,
createdAt: DateTime.now()),
Message(
content: 'What do you want to learn about Flutter?',
isGPT: true,
createdAt: DateTime.now()),
Message(
content: 'I want to learn about Bloc',
isGPT: false,
createdAt: DateTime.now()),
Message(
content: 'What do you want to learn about Bloc?',
isGPT: true,
createdAt: DateTime.now()),
Message(
content: 'I want to learn about Bloc',
isGPT: false,
createdAt: DateTime.now()),
];

@override
void initState() {
super.initState();
}

ChatStore _chatStore = getIt<ChatStore>();

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ListView.builder(
controller: _controller,
itemCount: messages.length + 1,
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
// if (index == state.messages?.length) {
// return (state is! ConversationDone)
// ? Center(
// child: SizedBox(
// width: 30,
// height: 30,
// child: CircularProgressIndicator(
// strokeWidth: 1.5,
// color: Theme.of(context).primaryColor,
// ),
// ),
// )
// : const SizedBox();
// }
if (index == 0) {
return CustomProgressIndicatorWidget();
}
return Container(
padding: EdgeInsets.only(
left: (messages[index - 1].isGPT) ? 14 : 56,
right: (messages[index - 1].isGPT) ? 56 : 14,
top: 10,
bottom: 10),
child: Column(
crossAxisAlignment: (messages[index - 1].isGPT)
? CrossAxisAlignment.start
: CrossAxisAlignment.end,
children: [
if (index - 1 == showTimeAtIndex)
Center(
child: Padding(
padding: const EdgeInsets.only(
bottom: 5,
),
child: Text(
DateFormat(null, 'en')
.format(messages[index - 1].createdAt),
style: Theme.of(context).textTheme.displayMedium,
child: Observer(builder: (context) {
if (_chatStore.id == -1) {
return const Center(
child: Text('Select a chat to start'),
);
}
final int chatThreadIndex = _chatStore.chatThreads
.indexWhere((element) => element.id == _chatStore.id);
if (_chatStore.chatThreads[chatThreadIndex].messages.isEmpty) {
return const Center(
child: Text('No messages yet'),
);
}
if (_chatStore.chatThreads.isEmpty ||
_chatStore.isLoading ||
_chatStore.isLoadingChatThreads) {
return const Center(
child: CustomProgressIndicatorWidget(),
);
}
print(_chatStore.chatThreads);
return ListView.builder(
controller: _controller,
itemCount:
_chatStore.chatThreads[chatThreadIndex].messages.length,
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.only(
left: (_chatStore.chatThreads[chatThreadIndex]
.messages[index].message.role ==
Role.assistant)
? 14
: 56,
right: (_chatStore.chatThreads[chatThreadIndex]
.messages[index].message.role ==
Role.assistant)
? 56
: 14,
top: 10,
bottom: 10),
child: Column(
crossAxisAlignment: (_chatStore.chatThreads[chatThreadIndex]
.messages[index].message.role ==
Role.assistant)
? CrossAxisAlignment.start
: CrossAxisAlignment.end,
children: [
if (index == showTimeAtIndex)
Center(
child: Padding(
padding: const EdgeInsets.only(
bottom: 5,
),
child: Text(
DateFormat(null, 'en').format(_chatStore
.chatThreads[chatThreadIndex]
.messages[index]
.time),
style: Theme.of(context).textTheme.displayMedium,
),
),
),
),
InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () {
setState(() {
if (showTimeAtIndex != index - 1) {
showTimeAtIndex = index - 1;
} else {
showTimeAtIndex = -1;
}
});
},
child: Material(
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (messages[index - 1].isGPT)
? Colors.grey.shade300
: Theme.of(context).colorScheme.primary),
padding: const EdgeInsets.only(
left: 16, right: 16, top: 16, bottom: 16),
child: Text(
messages[index - 1].content,
style: TextStyle(
color: (messages[index - 1].isGPT)
? Colors.black
: Colors.white),
InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () {
setState(() {
if (showTimeAtIndex != index) {
showTimeAtIndex = index;
} else {
showTimeAtIndex = -1;
}
});
},
child: Material(
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (_chatStore.chatThreads[chatThreadIndex]
.messages[index].message.role ==
Role.assistant)
? Colors.grey.shade300
: Theme.of(context).colorScheme.primary),
padding: const EdgeInsets.only(
left: 16, right: 16, top: 16, bottom: 16),
child: Text(
_chatStore.chatThreads[chatThreadIndex]
.messages[index].message.content,
style: TextStyle(
color: (_chatStore
.chatThreads[chatThreadIndex]
.messages[index]
.message
.role ==
Role.assistant)
? Colors.black
: Colors.white),
),
),
),
),
),
],
),
);
},
),
],
),
);
},
);
}),
),
ChatInput(onSend: () {}),
],
Expand Down
16 changes: 7 additions & 9 deletions lib/presentation/home/home_screen.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'package:boilerplate/core/widgets/main_app_bar.dart';
import 'package:boilerplate/core/widgets/main_drawer.dart';
import 'package:boilerplate/di/service_locator.dart';
import 'package:boilerplate/presentation/chat_screen/chat_screen.dart';
import 'package:boilerplate/presentation/chat_screen/store/chat_store.dart';
import 'package:boilerplate/presentation/new_chat/new_chat_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';

class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
Expand All @@ -12,23 +15,18 @@ class HomeScreen extends StatefulWidget {
}

class _HomeScreenState extends State<HomeScreen> {
String? chatThreadId;
ChatStore _chatStore = getIt<ChatStore>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(60),
child: MainAppBar(),
),
drawer: MainDrawer(setChatThreadId: (id) {
setState(() {
chatThreadId = id;
});
Navigator.pop(context);
drawer: MainDrawer(),
body: Observer(builder: (context) {
return _chatStore.id > 0 ? ChatScreen() : NewChatScreen();
}),
body: chatThreadId != null
? ChatScreen(chatThreadId: chatThreadId!)
: NewChatScreen(),
);
}
}
2 changes: 1 addition & 1 deletion lib/presentation/new_chat/new_chat_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
height: 10,
),
Text(
'How can I help you today? ${dotenv.env['OPEN_API_ACCESS_KEY']}',
'How can I help you today?',
style: Theme.of(context).textTheme.titleLarge,
),
],
Expand Down

0 comments on commit c3febc6

Please sign in to comment.