Skip to content

Commit

Permalink
display chat threads
Browse files Browse the repository at this point in the history
  • Loading branch information
Dat-TG committed Dec 15, 2023
1 parent 3148e6b commit 11f7e74
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 127 deletions.
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
FlutterApplication and put your custom class here. -->
<application
android:icon="@mipmap/ic_launcher"
android:label="Boilerplate Project"
android:label="ChatGPT"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
Expand Down
146 changes: 31 additions & 115 deletions lib/core/widgets/main_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import 'package:boilerplate/core/widgets/chat_thread.dart';
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';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

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

@override
State<MainDrawer> createState() => _MainDrawerState();
}

class _MainDrawerState extends State<MainDrawer> {
ChatStore _chatStore = getIt<ChatStore>();
@override
Widget build(BuildContext context) {
return Drawer(
Expand All @@ -24,123 +33,30 @@ class MainDrawer extends StatelessWidget {
title: Text('New chat'),
minLeadingWidth: 10,
onTap: () {
setChatThreadId(null);
widget.setChatThreadId(null);
},
),
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: [
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'ChatGPT Flutter App',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'ChatGPT Flutter App',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
],
),
child: Observer(builder: (context) {
if (_chatStore.isLoadingChatThreads) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView(
padding: EdgeInsets.zero,
children: _chatStore.chatThreads
.map(
(e) => ChatThreadWidget(
name: e.subject,
onTap: () {
_chatStore.setChatThreadId(e.id);
},
),
)
.toList(),
);
}),
),
],
),
Expand Down
2 changes: 1 addition & 1 deletion lib/data/local/datasources/message/message_datasource.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class MessageDataSource {
print('Loading from database');

// post list
var chatThreadList;
List<ChatThread> chatThreadList = [];

// fetching data
final recordSnapshots = await _messageStore.find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class GetAllChatThreadsUseCase extends UseCase<List<ChatThread>, void> {
GetAllChatThreadsUseCase(this._messageRepository);

@override
Future<List<ChatThread>> call({required void params}) {
Future<List<ChatThread>> call({void params}) {
return _messageRepository.getAllChatThreads();
}
}
134 changes: 134 additions & 0 deletions lib/presentation/chat_screen/store/chat_store.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'package:boilerplate/core/stores/error/error_store.dart';
import 'package:boilerplate/domain/entity/message/chat_thread.dart';
import 'package:boilerplate/domain/entity/message/message.dart';
import 'package:boilerplate/domain/entity/message/message_with_time.dart';
import 'package:boilerplate/domain/usecase/message/get_all_chat_threads_usecase.dart';
import 'package:boilerplate/domain/usecase/message/send_message_usecase.dart';

import 'package:mobx/mobx.dart';

part 'chat_store.g.dart';

class ChatStore = _ChatStore with _$ChatStore;

abstract class _ChatStore with Store {
// constructor:---------------------------------------------------------------
_ChatStore(
this.errorStore,
this._sendMessageUseCase,
this._getAllChatThreadsUseCase,
) {
// load all chat threads
getAllChatThreads();
// setting up disposers
_setupDisposers();
}

// use cases:-----------------------------------------------------------------
final SendMessageUseCase _sendMessageUseCase;
final GetAllChatThreadsUseCase _getAllChatThreadsUseCase;

// store for handling error messages
final ErrorStore errorStore;

// disposers:-----------------------------------------------------------------
late List<ReactionDisposer> _disposers;

void _setupDisposers() {
_disposers = [
reaction((_) => success, (_) => success = false, delay: 200),
];
}

// store variables:-----------------------------------------------------------

@observable
bool success = false;

@observable
int id = 0;

@observable
List<ChatThread> chatThreads = [];

@observable
ObservableFuture<List<ChatThread>?> chatThreadsFuture =
ObservableFuture.value(null);

@observable
ObservableFuture<Message?> sendMessageFuture = ObservableFuture.value(null);

@computed
bool get isLoading => sendMessageFuture.status == FutureStatus.pending;

@computed
bool get isLoadingChatThreads =>
chatThreadsFuture.status == FutureStatus.pending;

// actions:-------------------------------------------------------------------
@action
Future setChatThreadId(int newId) async {
id = newId;
}

@action
Future setChatThreads(List<ChatThread> newChatThreads) async {
chatThreads = newChatThreads;
}

@action
Future getAllChatThreads() async {
final future = _getAllChatThreadsUseCase.call();
chatThreadsFuture = ObservableFuture(future);

await future.then((value) async {
print('response message ${value}');
this.success = true;
this.chatThreads = value;
}).catchError((e) {
print(e);
this.success = false;
throw e;
});
}

@action
Future sendMessage(String content) async {
final Message message = Message(role: Role.user, content: content);
final time = DateTime.now();
final messages = chatThreads
.firstWhere((element) => element.id == id)
.messages
.map((e) => e.message)
.toList();
final future = _sendMessageUseCase.call(params: [...messages, message]);
sendMessageFuture = ObservableFuture(future);

await future.then((value) async {
print('response message ${value.toMap()}');
// TODO: update chat thread in db
// await _saveChatThreadUseCase.call(
// params: ChatThread(
// id: time.millisecondsSinceEpoch,
// subject: message.content,
// messages: [
// MessageWithTime(message, time),
// MessageWithTime(value, time),
// ],
// ),
// );
this.success = true;
}).catchError((e) {
print(e);
this.success = false;
throw e;
});
}

// general methods:-----------------------------------------------------------
void dispose() {
for (final d in _disposers) {
d();
}
}
}

0 comments on commit 11f7e74

Please sign in to comment.