From 45fe1dbca80926e800db60c5d954b4e21a9be97e Mon Sep 17 00:00:00 2001 From: ha-ccoon Date: Sun, 24 Nov 2024 21:06:25 +0900 Subject: [PATCH 1/3] chore: add fetchAllMessagesDto --- lib/dto/fetch_all_messages.dto.dart | 27 ++++++++++++++++ lib/dto/fetch_all_messages.dto.g.dart | 25 +++++++++++++++ lib/dto/fetch_message_dto.dart | 31 ------------------- lib/dto/fetch_messages_in_minute_dto.dart | 31 +++++++++++++++++++ ...rt => fetch_messages_in_minute_dto.g.dart} | 10 +++--- 5 files changed, 89 insertions(+), 35 deletions(-) create mode 100644 lib/dto/fetch_all_messages.dto.dart create mode 100644 lib/dto/fetch_all_messages.dto.g.dart delete mode 100644 lib/dto/fetch_message_dto.dart create mode 100644 lib/dto/fetch_messages_in_minute_dto.dart rename lib/dto/{fetch_message_dto.g.dart => fetch_messages_in_minute_dto.g.dart} (70%) diff --git a/lib/dto/fetch_all_messages.dto.dart b/lib/dto/fetch_all_messages.dto.dart new file mode 100644 index 0000000..0d48e7e --- /dev/null +++ b/lib/dto/fetch_all_messages.dto.dart @@ -0,0 +1,27 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'fetch_all_messages.dto.g.dart'; + +@JsonSerializable() +class FetchAllMessagesDto { + @JsonKey(required: true) + final String senderId; + + @JsonKey(required: true) + final String receiverId; + + FetchAllMessagesDto({ + required this.senderId, + required this.receiverId, + }); + + /// Connect the generated [_$FetchAllMessagesDtoFromJson] function to the `fromJson` + /// factory. + factory FetchAllMessagesDto.fromJson(Map json) => + _$FetchAllMessagesDtoFromJson(json); + + /// Connect the generated [_$FetchAllMessagesDtoToJson] function to the `toJson` method. + Map toJson() => _$FetchAllMessagesDtoToJson(this); +} + +// dart run build_runner build diff --git a/lib/dto/fetch_all_messages.dto.g.dart b/lib/dto/fetch_all_messages.dto.g.dart new file mode 100644 index 0000000..4035b72 --- /dev/null +++ b/lib/dto/fetch_all_messages.dto.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'fetch_all_messages.dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +FetchAllMessagesDto _$FetchAllMessagesDtoFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['senderId', 'receiverId'], + ); + return FetchAllMessagesDto( + senderId: json['senderId'] as String, + receiverId: json['receiverId'] as String, + ); +} + +Map _$FetchAllMessagesDtoToJson( + FetchAllMessagesDto instance) => + { + 'senderId': instance.senderId, + 'receiverId': instance.receiverId, + }; diff --git a/lib/dto/fetch_message_dto.dart b/lib/dto/fetch_message_dto.dart deleted file mode 100644 index ff7b93f..0000000 --- a/lib/dto/fetch_message_dto.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'fetch_message_dto.g.dart'; - -@JsonSerializable() -class FetchMessageDto { - @JsonKey(required: true) - final String senderId; - - @JsonKey(required: true) - final String receiverId; - - @JsonKey(required: true) - final DateTime createdAt; - - FetchMessageDto({ - required this.senderId, - required this.receiverId, - required this.createdAt, - }); - - /// Connect the generated [_$FetchMessageDtoFromJson] function to the `fromJson` - /// factory. - factory FetchMessageDto.fromJson(Map json) => - _$FetchMessageDtoFromJson(json); - - /// Connect the generated [_$FetchMessageDtoToJson] function to the `toJson` method. - Map toJson() => _$FetchMessageDtoToJson(this); -} - -// dart run build_runner build diff --git a/lib/dto/fetch_messages_in_minute_dto.dart b/lib/dto/fetch_messages_in_minute_dto.dart new file mode 100644 index 0000000..ab31087 --- /dev/null +++ b/lib/dto/fetch_messages_in_minute_dto.dart @@ -0,0 +1,31 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'fetch_messages_in_minute_dto.g.dart'; + +@JsonSerializable() +class FetchMessageInMinuteDto { + @JsonKey(required: true) + final String senderId; + + @JsonKey(required: true) + final String receiverId; + + @JsonKey(required: true) + final DateTime createdAt; + + FetchMessageInMinuteDto({ + required this.senderId, + required this.receiverId, + required this.createdAt, + }); + + /// Connect the generated [_$FetchMessageInMinuteDtoFromJson] function to the `fromJson` + /// factory. + factory FetchMessageInMinuteDto.fromJson(Map json) => + _$FetchMessageInMinuteDtoFromJson(json); + + /// Connect the generated [_$FetchMessageInMinuteDtoToJson] function to the `toJson` method. + Map toJson() => _$FetchMessageInMinuteDtoToJson(this); +} + +// dart run build_runner build diff --git a/lib/dto/fetch_message_dto.g.dart b/lib/dto/fetch_messages_in_minute_dto.g.dart similarity index 70% rename from lib/dto/fetch_message_dto.g.dart rename to lib/dto/fetch_messages_in_minute_dto.g.dart index d62c1fa..6409a15 100644 --- a/lib/dto/fetch_message_dto.g.dart +++ b/lib/dto/fetch_messages_in_minute_dto.g.dart @@ -1,24 +1,26 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'fetch_message_dto.dart'; +part of 'fetch_messages_in_minute_dto.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** -FetchMessageDto _$FetchMessageDtoFromJson(Map json) { +FetchMessageInMinuteDto _$FetchMessageInMinuteDtoFromJson( + Map json) { $checkKeys( json, requiredKeys: const ['senderId', 'receiverId', 'createdAt'], ); - return FetchMessageDto( + return FetchMessageInMinuteDto( senderId: json['senderId'] as String, receiverId: json['receiverId'] as String, createdAt: DateTime.parse(json['createdAt'] as String), ); } -Map _$FetchMessageDtoToJson(FetchMessageDto instance) => +Map _$FetchMessageInMinuteDtoToJson( + FetchMessageInMinuteDto instance) => { 'senderId': instance.senderId, 'receiverId': instance.receiverId, From f5c35dac8a3fbfe7dd5ff4bb27b85e2ac7c95eba Mon Sep 17 00:00:00 2001 From: ha-ccoon Date: Sun, 24 Nov 2024 21:06:53 +0900 Subject: [PATCH 2/3] chore: implement fetchAllMessages feature --- lib/api/message.dart | 31 ++++++++++++++++++++++++++++--- lib/chat.dart | 33 ++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/lib/api/message.dart b/lib/api/message.dart index b606505..f53a62c 100644 --- a/lib/api/message.dart +++ b/lib/api/message.dart @@ -2,7 +2,8 @@ import 'package:dio/dio.dart'; import 'package:kuna_talk/api/config.dart'; import 'package:kuna_talk/dto/create_message_dto.dart'; -import 'package:kuna_talk/dto/fetch_message_dto.dart'; +import 'package:kuna_talk/dto/fetch_all_messages.dto.dart'; +import 'package:kuna_talk/dto/fetch_messages_in_minute_dto.dart'; import 'package:kuna_talk/models/message.dart'; final Dio dio = DioClient().dio; @@ -13,7 +14,7 @@ Future createMessage(CreateMessageDto data) async { final result = Message.fromJson(response.data); if (response.statusCode == 201) { - print('createMessage111: $result'); + print('createMessage: $result'); return result; } else { @@ -26,11 +27,35 @@ Future createMessage(CreateMessageDto data) async { } } -Future> fetchMessage(FetchMessageDto data) async { +Future> fetchAllMessages(FetchAllMessagesDto data) async { try { final response = await dio.get('/chat', queryParameters: { 'senderId': data.senderId, 'receiverId': data.receiverId, + }); + + final result = + (response.data as List).map((json) => Message.fromJson(json)).toList(); + + if (response.statusCode == 200) { + print('fetchAllMessages: ${result[0].message}'); + return result; + } else { + print('Failed to send message'); + throw Exception( + 'createMessage API error ${response.statusCode} ${response.statusMessage}'); + } + } catch (e) { + throw Exception('createMessage API error: $e'); + } +} + +Future> fetchMessagesInMinute( + FetchMessageInMinuteDto data) async { + try { + final response = await dio.get('/chat/minute', queryParameters: { + 'senderId': data.senderId, + 'receiverId': data.receiverId, 'createdAt': data.createdAt }); diff --git a/lib/chat.dart b/lib/chat.dart index 5fba239..d6cd71c 100644 --- a/lib/chat.dart +++ b/lib/chat.dart @@ -2,7 +2,8 @@ import 'package:flutter/material.dart'; import 'package:kuna_talk/api/message.dart'; import 'package:kuna_talk/dto/create_message_dto.dart'; -import 'package:kuna_talk/dto/fetch_message_dto.dart'; +import 'package:kuna_talk/dto/fetch_all_messages.dto.dart'; +import 'package:kuna_talk/dto/fetch_messages_in_minute_dto.dart'; import 'package:kuna_talk/models/message.dart'; import 'package:kuna_talk/utils/util.dart'; @@ -17,20 +18,30 @@ class ChatState extends State { final person1 = '4rwodzn1uuacfpq'; final person2 = 'c4w28yb8dmgo4lz'; - final TextEditingController controller = TextEditingController(); List messages = []; - String? message; + + final TextEditingController controller = TextEditingController(); @override void initState() { super.initState(); - loadMessages(); + loadAllMessages(); + } + + Future loadAllMessages() async { + final response = await fetchAllMessages( + FetchAllMessagesDto(senderId: person1, receiverId: person2), + ); + + setState(() { + messages = response; + }); } - Future loadMessages({DateTime? createdAt}) async { + Future loadMessagesInMinute({DateTime? createdAt}) async { try { - final response = await fetchMessage( - FetchMessageDto( + final response = await fetchMessagesInMinute( + FetchMessageInMinuteDto( senderId: person1, receiverId: person2, createdAt: createdAt!, @@ -46,6 +57,8 @@ class ChatState extends State { } Future sendMessage(String message) async { + final messageId = generateRandomId(15); + if (message.isEmpty) { print('Message required'); return; @@ -54,7 +67,7 @@ class ChatState extends State { final data = CreateMessageDto( senderId: person1, receiverId: person2, - messageId: generateRandomId(15), + messageId: messageId, message: message, updatedAt: DateTime.now(), createdAt: DateTime.now(), @@ -64,12 +77,10 @@ class ChatState extends State { final response = await createMessage(data); setState(() { - messages.add(response); - message = response.message; controller.clear(); }); - loadMessages(createdAt: response.createdAt); + loadMessagesInMinute(createdAt: response.createdAt); } catch (e) { throw Exception('sendMessage error: $e'); } From 551d6c3a7e006eac24f79a1dc027cd02d5e18cea Mon Sep 17 00:00:00 2001 From: ha-ccoon Date: Sun, 24 Nov 2024 21:19:14 +0900 Subject: [PATCH 3/3] chore: delete duplicate messages --- lib/api/message.dart | 2 ++ lib/chat.dart | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/api/message.dart b/lib/api/message.dart index f53a62c..60e635a 100644 --- a/lib/api/message.dart +++ b/lib/api/message.dart @@ -8,6 +8,7 @@ import 'package:kuna_talk/models/message.dart'; final Dio dio = DioClient().dio; +// create Future createMessage(CreateMessageDto data) async { try { final response = await dio.post('/chat', data: data); @@ -27,6 +28,7 @@ Future createMessage(CreateMessageDto data) async { } } +// read Future> fetchAllMessages(FetchAllMessagesDto data) async { try { final response = await dio.get('/chat', queryParameters: { diff --git a/lib/chat.dart b/lib/chat.dart index d6cd71c..82e7cb3 100644 --- a/lib/chat.dart +++ b/lib/chat.dart @@ -38,16 +38,20 @@ class ChatState extends State { }); } - Future loadMessagesInMinute({DateTime? createdAt}) async { + Future loadMessagesInMinute(DateTime createdAt) async { try { final response = await fetchMessagesInMinute( FetchMessageInMinuteDto( senderId: person1, receiverId: person2, - createdAt: createdAt!, + createdAt: createdAt, ), ); + List ids = messages.map((item) => item.messageId).toList(); + + response.removeWhere((item) => ids.contains(item.messageId)); + setState(() { messages.addAll(response); }); @@ -80,7 +84,7 @@ class ChatState extends State { controller.clear(); }); - loadMessagesInMinute(createdAt: response.createdAt); + loadMessagesInMinute(response.createdAt); } catch (e) { throw Exception('sendMessage error: $e'); }