코딩하는 제리

[Flutter/Project](Instagram Clone) Comments 화면 Firestore 연결 본문

Flutter/Project_InstaClone(완)

[Flutter/Project](Instagram Clone) Comments 화면 Firestore 연결

JerryCho 2021. 3. 10. 11:39


comments_screen.dart -> comment 페이지 작성자 표시 및 comment 출력
comments_screen.dart -> comment 작성 버튼


소스코드 및 pubspec.yaml

// screens/comments_screen.dart

import 'package:flutter/material.dart';
import 'package:flutter_project_IJ/constants/auth_input_decor.dart';
import 'package:flutter_project_IJ/constants/common_size.dart';
import 'package:flutter_project_IJ/models/firestore/comment_model.dart';
import 'package:flutter_project_IJ/models/firestore/post_model.dart';
import 'package:flutter_project_IJ/models/firestore/user_model.dart';
import 'package:flutter_project_IJ/models/user_model_state.dart';
import 'package:flutter_project_IJ/repo/comment_network_repository.dart';
import 'package:flutter_project_IJ/widgets/comment.dart';
import 'package:flutter_project_IJ/widgets/rounded_avatar.dart';
import 'package:provider/provider.dart';

class CommentsScreen extends StatefulWidget {
  final String postKey;
  final PostModel postModel;

  const CommentsScreen(this.postKey, this.postModel, {Key key})
      : super(key: key);

  @override
  _CommentsScreenState createState() => _CommentsScreenState();
}

class _CommentsScreenState extends State<CommentsScreen> {
  TextEditingController _textEditingController = TextEditingController();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  // Post 버튼 활성화/비활성화
  bool _btnEnable = false;

  @override
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('Comments'),
        backgroundColor: Colors.grey[200],
        elevation: 1,
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: common_xxs_gap),
            child: IconButton(
              icon: ImageIcon(AssetImage('assets/images/direct_message.png')),
              onPressed: () {},
              color: Colors.black87,
            ),
          )
        ],
      ),
      body: Form(
        key: _formKey,
        onChanged: () {
          setState(() {
            // Form의 상태가 변경될 때마다 _btnEnable 업데이트
            _btnEnable = _formKey.currentState.validate();
          });
        },
        child: Column(
          children: [
            // 포스트 작성자 comment screen에 추가
            Padding(
              padding: const EdgeInsets.only(
                  bottom: common_xs_gap,
                  left: common_xs_gap,
                  right: common_xs_gap,
                  top: common_gap),
              child: Comment(
                showImage: true,
                username: widget.postModel.username,
                text: widget.postModel.caption,
                dateTime: widget.postModel.postTime,
              ),
            ),
            Divider(
              height: 25,
              thickness: 1,
              color: Colors.grey[300],
            ),
            Expanded(
              child: StreamProvider<List<CommentModel>>.value(
                  value:
                      commentNetworkRepository.fetchAllComments(widget.postKey),
                  builder: (context, snapshot) {
                    return Consumer<List<CommentModel>>(
                      builder: (BuildContext context,
                          List<CommentModel> comments, Widget child) {
                        return ListView.separated(
                          itemBuilder: (context, index) {
                            return Padding(
                              padding: const EdgeInsets.all(common_xs_gap),
                              child: Comment(
                                username: comments[index].username,
                                text: comments[index].comment,
                                dateTime: comments[index].commentTime,
                                showImage: true,
                              ),
                            );
                          },
                          // 각각의 아이템 사이 공간
                          separatorBuilder: (context, index) {
                            return SizedBox(height: common_xxs_gap);
                          },
                          itemCount: comments == null ? 0 : comments.length,
                        );
                      },
                    );
                  }),
            ),
            Divider(height: 1, thickness: 1, color: Colors.grey[300]),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: common_xxs_gap),
              child: Row(
                // Row 하단 정렬
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Padding(
                    padding: EdgeInsets.all(common_xxs_gap),
                    child: RoundedAvatar(
                      size: 45,
                    ),
                  ),
                  Expanded(
                    child: Padding(
                      padding: const EdgeInsets.only(
                          right: common_xs_gap,
                          top: common_xxs_gap,
                          bottom: common_xxs_gap),
                      child: TextFormField(
                        controller: _textEditingController,
                        minLines: 1,
                        maxLines: 5,
                        showCursor: true,
                        autofocus: true,
                        cursorColor: Colors.blueAccent,
                        // 값 검사. 비어있으면 에러 메시지 표시
                        validator: (text) => text.isNotEmpty ? null : '',
                        decoration: InputDecoration(
                          focusedErrorBorder: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.grey[300]),
                            borderRadius: BorderRadius.circular(20),
                          ),
                          focusedBorder: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.grey[300]),
                            borderRadius: BorderRadius.circular(20),
                          ),
                          // 에러 메시지 제거
                          errorStyle: TextStyle(fontSize: 0, height: 0),
                          hintText: 'Add a comment...',
                          isDense: true /* 가능한 작은 사이즈 */,
                          contentPadding: EdgeInsets.all(10) /* 내부 공백 */,
                          // hintText: 'Comment..',
                          hintStyle: TextStyle(color: Colors.grey[400]),
                          // 텍스트필드 내부 버튼
                          suffixIcon: TextButton(
                            // 받은 값이 true일 경우 버튼 활성화
                            onPressed: _btnEnable
                                ? () async {
                                    UserModel userModel =
                                        Provider.of<UserModelState>(context,
                                                listen: false)
                                            .userModel;
                                    Map<String, dynamic> newComment =
                                        CommentModel.getMapForNewComment(
                                            userModel.userKey,
                                            userModel.username,
                                            _textEditingController.text);
                                    await commentNetworkRepository
                                        .createNewComment(
                                            widget.postKey, newComment);
                                    _textEditingController.clear();
                                  }
                                : null,
                            style: TextButton.styleFrom(primary: Colors.blue),
                            child: Text('Post'),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Comments