Skip to content

Commit

Permalink
message api and db
Browse files Browse the repository at this point in the history
  • Loading branch information
Dat-TG committed Dec 14, 2023
1 parent 04c179b commit e2cbe43
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 29 deletions.
10 changes: 4 additions & 6 deletions lib/core/widgets/chat_thread.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import 'dart:ffi';

import 'package:flutter/material.dart';

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

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

class _ChatThreadState extends State<ChatThread> {
class _ChatThreadWidgetState extends State<ChatThreadWidget> {
@override
Widget build(BuildContext context) {
return GestureDetector(
Expand Down
36 changes: 18 additions & 18 deletions lib/core/widgets/main_drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,109 +31,109 @@ class MainDrawer extends StatelessWidget {
child: ListView(
padding: EdgeInsets.zero,
children: [
ChatThread(
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'ChatGPT Flutter App',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'ChatGPT Flutter App',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'GraphQL in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'REST API Explanation',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Jitsi Meet in Flutter',
onTap: () {
setChatThreadId('1');
},
),
ChatThread(
ChatThreadWidget(
name: 'Websockets in Flutter',
onTap: () {
setChatThreadId('1');
Expand Down
4 changes: 2 additions & 2 deletions lib/data/local/constants/db_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ class DBConstants {
DBConstants._();

// Store Name
static const String STORE_NAME = 'demo';
static const String STORE_NAME = 'chatGPT';

// DB Name
static const DB_NAME = 'demo.db';
static const DB_NAME = 'chatGPT.db';

// Fields
static const FIELD_ID = 'id';
Expand Down
114 changes: 114 additions & 0 deletions lib/data/local/datasources/message/message_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import 'package:boilerplate/core/data/local/sembast/sembast_client.dart';
import 'package:boilerplate/data/local/constants/db_constants.dart';
import 'package:boilerplate/domain/entity/message/chat_thread.dart';
import 'package:boilerplate/domain/entity/post/post.dart';
import 'package:boilerplate/domain/entity/post/post_list.dart';
import 'package:sembast/sembast.dart';

class MessageDataSource {
// A Store with int keys and Map<String, dynamic> values.
// This Store acts like a persistent map, values of which are Flogs objects converted to Map
final _messageStore = intMapStoreFactory.store(DBConstants.STORE_NAME);

// Private getter to shorten the amount of code needed to get the
// singleton instance of an opened database.
// Future<Database> get _db async => await AppDatabase.instance.database;

// database instance
final SembastClient _sembastClient;

// Constructor
MessageDataSource(this._sembastClient);

// DB functions:--------------------------------------------------------------
Future<int> insertChatThread(ChatThread chatThread) async {
int id = await _messageStore
.record(chatThread.id)
.add(_sembastClient.database, chatThread.toMap()) ??
-1;
return id;
}

Future<int> count() async {
return await _messageStore.count(_sembastClient.database);
}

Future<List<ChatThread>> getChatThreads({List<Filter>? filters}) async {
//creating finder
final finder = Finder(
filter: filters != null ? Filter.and(filters) : null,
sortOrders: [SortOrder(DBConstants.FIELD_ID)]);

final recordSnapshots = await _messageStore.find(
_sembastClient.database,
finder: finder,
);

// Making a List<Post> out of List<RecordSnapshot>
return recordSnapshots.map((snapshot) {
final chatThread = ChatThread.fromMap(snapshot.value);
// An ID is a key of a record from the database.
chatThread.id = snapshot.key;
return chatThread;
}).toList();
}

Future<PostList> getAllChatThreads() async {
print('Loading from database');

// post list
var chatThreadList;

// fetching data
final recordSnapshots = await _messageStore.find(
_sembastClient.database,
);

// Making a List<Post> out of List<RecordSnapshot>
if (recordSnapshots.length > 0) {
chatThreadList = recordSnapshots.map((snapshot) {
final chatThread = ChatThread.fromMap(snapshot.value);
// An ID is a key of a record from the database.
chatThread.id = snapshot.key;
return chatThread;
}).toList();
}

return chatThreadList;
}

Future<ChatThread> getChatThreadById(int id) async {
final finder = Finder(filter: Filter.byKey(id));
final recordSnapshots = await _messageStore.findFirst(
_sembastClient.database,
finder: finder,
);
final chatThread = ChatThread.fromMap(recordSnapshots!.value);
return chatThread;
}

Future<int> update(Post post) async {
// For filtering by key (ID), RegEx, greater than, and many other criteria,
// we use a Finder.
final finder = Finder(filter: Filter.byKey(post.id));
return await _messageStore.update(
_sembastClient.database,
post.toMap(),
finder: finder,
);
}

Future<int> delete(Post post) async {
final finder = Finder(filter: Filter.byKey(post.id));
return await _messageStore.delete(
_sembastClient.database,
finder: finder,
);
}

Future deleteAll() async {
await _messageStore.drop(
_sembastClient.database,
);
}
}
40 changes: 40 additions & 0 deletions lib/data/network/apis/message/message_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'dart:async';

import 'package:boilerplate/core/data/network/dio/dio_client.dart';
import 'package:boilerplate/data/network/constants/endpoints.dart';
import 'package:boilerplate/data/network/rest_client.dart';
import 'package:boilerplate/domain/entity/message/message.dart';

class MessageApi {
// dio instance
final DioClient _dioClient;

// rest-client instance
final RestClient _restClient;

// injecting dio instance
MessageApi(this._dioClient, this._restClient);

Future<Message> sendMessage(List<Message> messages) async {
try {
final res = await _dioClient.dio.post(Endpoints.chat, data: {
"messages": messages.map((e) => e.toMap()).toList(),
"model": "gpt-3.5-turbo",
"temperature": "0.5"
});
return Message.fromMap(res.data["choices"][0]["message"]);
} catch (e) {
print(e.toString());
throw e;
}
}

/// sample api call with default rest client
// Future<PostsList> getPosts() {
//
// return _restClient
// .get(Endpoints.getPosts)
// .then((dynamic res) => PostsList.fromJson(res))
// .catchError((error) => throw NetworkException(message: error));
// }
}
8 changes: 5 additions & 3 deletions lib/data/network/constants/endpoints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ class Endpoints {
Endpoints._();

// base url
static const String baseUrl = "http:https://jsonplaceholder.typicode.com";
static const String baseUrl = "https:https://api.openai.com/v1";

// receiveTimeout
static const int receiveTimeout = 15000;
static const int receiveTimeout = 60000;

// connectTimeout
static const int connectionTimeout = 30000;

// booking endpoints
static const String getPosts = baseUrl + "/posts";
}

static const String chat = baseUrl + '/chat/completions';
}
40 changes: 40 additions & 0 deletions lib/data/repository/message/message_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'dart:async';
import 'package:boilerplate/data/local/datasources/message/message_datasource.dart';
import 'package:boilerplate/data/network/apis/message/message_api.dart';
import 'package:boilerplate/domain/entity/message/chat_thread.dart';
import 'package:boilerplate/domain/entity/message/message.dart';
import 'package:boilerplate/domain/repository/message/message_repository.dart';

class MessageRepositoryImpl extends MessageRepository {
// data source object
final MessageDataSource _messageDataSource;

// api objects
final MessageApi _messageApi;

// constructor
MessageRepositoryImpl(this._messageApi, this._messageDataSource);

// Post: ---------------------------------------------------------------------
@override
Future<Message> sendMessage(List<Message> messages) async {
// check to see if posts are present in database, then fetch from database
// else make a network call to get all posts, store them into database for
// later use
return await _messageApi.sendMessage(messages).then((value) {
return value;
}).catchError((error) => throw error);
}

@override
Future<ChatThread> getChatThread(int id) => _messageDataSource
.getChatThreadById(id)
.then((id) => id)
.catchError((error) => throw error);

@override
Future<int> saveChatThread(ChatThread chatThread) => _messageDataSource
.insertChatThread(chatThread)
.then((id) => id)
.catchError((error) => throw error);
}

0 comments on commit e2cbe43

Please sign in to comment.