본문 바로가기

Flutter/12 Clone 'Used Goods app'

[Flutter] Clone - 당근마켓51(Chat - 3) 메시지 표시

이번에는 채팅 화면에 간단하게 메시지를 표시해 보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

 

 

 

화면 구현은 아래와 같습니다. 

 

 

 

 

./src/screens/chat/chatroom_screen.dart

 

class _ChatroomScreenState extends State<ChatroomScreen> {
  late String chatroomKey;
  final TextEditingController _textEditingController = TextEditingController();
  late final ChatController chatController;

  @override
  void initState() {
    // TODO: implement initState
    chatroomKey = Get.parameters['chatroomKey']!;
    chatController = Get.put(ChatController(chatroomKey));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    logger.d('${Get.parameters['chatroomKey']}');
    UserModel1 userModel = UserController.to.userModel.value!;
    List<ChatModel2> _chatList = ChatController.to.chatList;
    Rxn<ChatroomModel2> chatModel = ChatController.to.chatroomModel;

    return Scaffold(
      appBar: AppBar(),
      backgroundColor: Colors.grey[200],
      // 화면 하단의 메뉴바 때문에 SafeArea 로 wrapping 해야 오동작을 방지함.
      body: SafeArea(
        child: Column(
          children: [
            // 게시글 정보를 간략히 표시
            _buildItemInfo(context),
            // 채팅 메시지 표시 부분
            Expanded(
              child: Obx(
                () => Container(
                  color: Colors.yellowAccent,
                  child: ListView.separated(
                    shrinkWrap: true,
                    reverse: true,
                    padding: const EdgeInsets.all(16),
                    itemBuilder: (context, index) {
                      return ListTile(
                        dense: true,
                        title: Text(_chatList[index].msg +
                            ' - ' +
                            DateFormat('yyyy-MM-dd').format(_chatList[index].createdDate)),
                        contentPadding: EdgeInsets.zero,
                        horizontalTitleGap: 0.0,
                        visualDensity: const VisualDensity(horizontal: 0, vertical: -4),
                        minVerticalPadding: 0,
                      );
                    },
                    separatorBuilder: (context, index) {
                      return const SizedBox(
                        height: 12,
                      );
                    },
                    itemCount: _chatList.length,
                  ),
                ),
              ),
            ),
            const Padding(padding: EdgeInsets.all(4)),
            // 메시지 입력 창
            _buildInputBar(userModel)
          ],
        ),
      ),
    );
  }

  // 컬럼내부에 리스트타일(높이 관련 오류가 있어서 나중에 row+column 조함으로 변경함)과 버튼으로 구성 예정
  MaterialBanner _buildItemInfo(BuildContext context) {
.... 중간생략
  }

  Widget _buildInputBar(UserModel1 userModel) {
.... 중간생략
  }
}

 

 

 

./src/states/chat_controller.dart 

 

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../models/chat_model.dart';
import '../models/chatroom_model.dart';
import '../repo/chat_service.dart';

class ChatController extends GetxController {
  static ChatController get to => Get.find();

  final String _chatroomKey;
  // 형선언을 직접해줘야 오류가 발생하지 않음
  final RxList<ChatModel2> _chatList = <ChatModel2>[].obs;
  final Rxn<ChatroomModel2> _chatroomModel = Rxn<ChatroomModel2>();

  // 형선언을 직접해줘야 오류가 발생하지 않음
  List<ChatModel2> get chatList => _chatList;
  Rxn<ChatroomModel2> get chatroomModel => _chatroomModel;

  @override
  void onReady() {
    // TODO: implement onReady
    super.onReady();
    debugPrint('************************* >>> ChatController >> onReady');
    debugPrint('>>> ChatController >> onReady .. [$_chatroomKey]');
  }

  ChatController(this._chatroomKey) {
    // todo: connect chatroom
    ChatService().connectChatroom(_chatroomKey).listen((chatroomModel) {
    // stream 처리해서 변경시 자동 호출됨
      _chatroomModel.value = chatroomModel;

      if (_chatList.isEmpty) {
        // todo: fetch 10 latest chats, if chat list is empty
        ChatService().getChatList(_chatroomKey).then((chatList) {
          _chatList.addAll(chatList);
        });
      } else {
        // todo: when new chatroom arrive, fetch latest chats
        if (_chatList[0].reference == null) {
          _chatList.removeAt(0);
        }
        ChatService().getLatestChats(_chatroomKey, _chatList[0].reference!).then((latestChats) {
          _chatList.insertAll(0, latestChats);
        });
      }
    });
  }
}