Skip to content

Commit

Permalink
feat: #109-채팅 기반 함수 및 최소 테스트 성공
Browse files Browse the repository at this point in the history
  • Loading branch information
ji-hunc committed May 2, 2024
1 parent bd778d2 commit 08758af
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 25 deletions.
6 changes: 6 additions & 0 deletions front/capstone_front/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

// 앱에서 지원하는 언어 리스트 변수
final supportedLocales = [const Locale('en', 'US'), const Locale('ko', 'KR')];
Expand All @@ -61,6 +62,11 @@ Future<void> setSetting() async {
if (str == 'true') {
_isLogin = true;
}
// storage.write(key: "uuid", value: "GVxxcceRRFNcWS690xLo85I8pV03");
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove("chatRoomData");
prefs.remove("23EiDZdTsQXL6erpvmztnnekIKE3");
prefs.remove("GVxxcceRRFNcWS690xLo85I8pV03");
}

void initializeFirebase() async {
Expand Down
5 changes: 1 addition & 4 deletions front/capstone_front/lib/models/api_fail_response.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
class ApiFailResponse {
final bool success;
final String message;
final String code;

ApiFailResponse({
required this.success,
required this.message,
required this.code,
});

ApiFailResponse.fromJson(Map<String, dynamic> json)
: success = json['success'] as bool,
message = json['message'] as String,
code = json['code'] as String;
message = json['message'] as String;
}
14 changes: 14 additions & 0 deletions front/capstone_front/lib/models/chat_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@ class ChatModel {
String content;
String timestamp;

ChatModel({
required this.id,
required this.content,
required this.timestamp,
});

ChatModel.fromJson(Map<String, dynamic> json)
: id = json['id'],
content = json['content'],
timestamp = json['timestamp'];

Map<String, dynamic> toJson() {
return {
'id': id,
'content': content,
'timestamp': timestamp,
};
}
}

class ChatModelForChatList extends ChatModel {
Expand Down
20 changes: 20 additions & 0 deletions front/capstone_front/lib/models/chat_room_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,31 @@ class ChatRoomModel {
String chatRoomMessage;
String chatRoomDate;

ChatRoomModel({
required this.chatRoomId,
required this.userId,
required this.userName,
required this.lastMessageId,
required this.chatRoomMessage,
required this.chatRoomDate,
});

ChatRoomModel.fromJson(Map<String, dynamic> json)
: chatRoomId = json['chatRoomId'],
userId = json['userId'],
userName = json['userName'],
lastMessageId = json['lastMessageId'],
chatRoomMessage = json['chatRoomMessage'],
chatRoomDate = json['chatRoomDate'];

Map<String, dynamic> toJson() {
return {
'chatRoomId': chatRoomId,
'userId': userId,
'userName': userName,
'lastMessageId': lastMessageId,
'chatRoomMessage': chatRoomMessage,
'chatRoomDate': chatRoomDate,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import 'dart:convert';
import 'dart:io';

import 'package:capstone_front/models/chat_model.dart';
import 'package:capstone_front/models/chat_room_model.dart';
import 'package:capstone_front/services/chat_service.dart';
import 'package:capstone_front/utils/bubble_painter1.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart';

class HelperChattingRoom extends StatefulWidget {
const HelperChattingRoom({super.key});
Expand All @@ -11,16 +19,29 @@ class HelperChattingRoom extends StatefulWidget {
}

class _HelperChattingRoomState extends State<HelperChattingRoom> {
FlutterSecureStorage storage = const FlutterSecureStorage();
final ScrollController _scrollController = ScrollController();
final TextEditingController _textController = TextEditingController();
final List<String> _messages = [];
final int _maxLines = 1;

void _sendMessage() {
String userId = "GVxxcceRRFNcWS690xLo85I8pV03";
String userName = "partner";
late int chatRoomId;
late int lastMessageId = 0;
late String lastMessage = "";
late String chatRoomDate = "";
late List<ChatModel> messages = [];
late List<ChatRoomModel> chatRooms;
bool isActive = true;

void _sendMessage() async {
if (_textController.text.isNotEmpty) {
var content = _textController.text;
var newChat = await ChatService.sendChat(chatRoomId, content);

setState(() {
// Todo: _textController.text를 서버로 보내고 답변 받아오기
_messages.insert(_messages.length, _textController.text);
messages.insert(messages.length, newChat);
_textController.clear();

// 텍스트 입력 시 방금 입력된 텍스트가 보일 수 있도록 이동
Expand All @@ -29,10 +50,143 @@ class _HelperChattingRoomState extends State<HelperChattingRoom> {
duration: const Duration(milliseconds: 100),
curve: Curves.easeInOut,
);
// TODO setState 안에서 이게 되나?
saveChatData(messages, userId);
});
}
}

// 채팅 데이터 저장
Future<void> saveChatData(List<ChatModel> chats, String partner) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> chatData =
chats.map((chat) => json.encode(chat.toJson())).toList();

await prefs.setStringList(partner, chatData);
}

// 채팅 데이터 불러오기
Future<List<ChatModel>> loadChatData(String partner) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> chatData = prefs.getStringList(partner) ?? [];

return chatData
.map((chat) => ChatModel.fromJson(json.decode(chat)))
.toList();
}

// 채팅방 데이터 저장
Future<void> saveChatRoomData(List<ChatRoomModel> chatRooms) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> chatRoomData =
chatRooms.map((chatRoom) => json.encode(chatRoom.toJson())).toList();
await prefs.setStringList('chatRoomData', chatRoomData);
}

// 채팅방 데이터 불러오기
Future<List<ChatRoomModel>> loadChatRoomData() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> chatRoomData = prefs.getStringList('chatRoomData') ?? [];
return chatRoomData
.map((chatRoom) => ChatRoomModel.fromJson(json.decode(chatRoom)))
.toList();
}

// 초기 채팅방을 설정함
Future<void> initializeChat() async {
var chatRoomList = await loadChatRoomData();

var flag = false;
for (var chatRoom in chatRoomList) {
// uuid로 이 사람과의 채팅이 처음인지 아닌지 판단
print(chatRoom.userId);
print(1);
if (chatRoom.userId == userId) {
flag = true;
var chatHistory = await loadChatData(userId);
setState(() {
chatRoomId = chatRoom.chatRoomId;
lastMessageId = chatRoom.lastMessageId;
lastMessage = chatRoom.chatRoomMessage;
chatRoomDate = chatRoom.chatRoomDate;
messages = chatHistory;
});
break;
}
}

if (flag) {
var newChats = await ChatService.loadNewChats(chatRoomId, lastMessageId);
messages.addAll(newChats);
} else {
var newChatRoomId = await ChatService.connectChat(userId);
if (newChatRoomId == -1) {
// 이미 나와 상대와의 채팅방이 존재함
}
var newChatRoom = ChatRoomModel(
chatRoomId: newChatRoomId,
userId: userId,
userName: userName,
lastMessageId: lastMessageId,
chatRoomMessage: lastMessage,
chatRoomDate: chatRoomDate,
);

setState(() {
chatRoomId = newChatRoomId;
lastMessageId = 0;
lastMessage = "";
chatRoomDate = "";
messages = [];
chatRoomList.add(newChatRoom);
saveChatRoomData(chatRoomList);
});
}
}

Future<void> startPolling(int chatRoomId, int lastMessageId) async {
print('chatRoomId');
print(chatRoomId);
try {
while (isActive) {
print(1);
try {
var newMessages =
await ChatService.pollingChat(chatRoomId, lastMessageId);
if (newMessages.isNotEmpty) {
print("GOT MESSAGE");
setState(() {
messages.addAll(newMessages);
lastMessageId = messages.last.id;
});
}

await Future.delayed(const Duration(seconds: 3));
} catch (e) {
print('Error while polling: $e');
await Future.delayed(const Duration(seconds: 3));
}
}
} catch (e) {
print('Unexpected error in polling loop: $e');
}
}

@override
void initState() {
super.initState();
initializeChat().then((_) {
startPolling(chatRoomId, lastMessageId);
});
super.initState();
}

@override
void dispose() {
isActive = false;
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -56,7 +210,7 @@ class _HelperChattingRoomState extends State<HelperChattingRoom> {
reverse: true,
shrinkWrap: true,
controller: _scrollController,
itemCount: _messages.length,
itemCount: messages.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(
Expand All @@ -72,7 +226,7 @@ class _HelperChattingRoomState extends State<HelperChattingRoom> {
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
_messages[_messages.length - 1 - index],
messages[messages.length - 1 - index].content,
style: const TextStyle(color: Colors.white),
),
),
Expand Down
Loading

0 comments on commit 08758af

Please sign in to comment.