코딩하는 제리

[Flutter/Project](Instagram Clone) user follow/unfollow 본문

Flutter/Project_InstaClone(완)

[Flutter/Project](Instagram Clone) user follow/unfollow

JerryCho 2021. 3. 2. 17:30

follow 되어 있으면 unfollow 버튼 활성화


repo/user_network_repository.dart -> follow 메서드
repo/user_network_repository.dart -> unfollow 메서드
screens/share_post_screen.dart -> ListView를 Consumer로 감싼다.
models/user_model_state.dart
follow 되어 있으면 unfollow 버튼 활성화
followings 다른 유저 키 추가
followers 증가


소스코드 및 pubspec.yaml

// screens/search_screen.dart

import 'package:flutter/material.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/user_network_repository.dart';
import 'package:flutter_project_IJ/widgets/my_progress_indicator.dart';
import 'package:flutter_project_IJ/widgets/rounded_avatar.dart';
import 'package:local_image_provider/local_album.dart';
import 'package:provider/provider.dart';

class SearchScreen extends StatefulWidget {
  @override
  _SearchScreenState createState() => _SearchScreenState();
}

class _SearchScreenState extends State<SearchScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('Follow/UnFollow'),
      ),
      body: StreamBuilder<List<UserModel>>(
        stream: userNetworkRepository.getAllUsersWithoutMe(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return SafeArea(
              child: Consumer<UserModelState>(
                builder: (BuildContext context, UserModelState myUserModelState,
                    Widget child) {
                  return ListView.separated(
                    // 데이터 갯수
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) {
                      UserModel otherUser = snapshot.data[index];

                      // follow/unfollow 확인.
                      bool amIFollowing = myUserModelState
                          .amIFollowingThisUser(otherUser.userKey);

                      return ListTile(
                        onTap: () {
                          setState(() {
                            amIFollowing
                                ? userNetworkRepository.unFollowUser(
                                    myUserKey:
                                        myUserModelState.userModel.userKey,
                                    otherUserKey: otherUser.userKey)
                                : userNetworkRepository.followUser(
                                    myUserKey:
                                        myUserModelState.userModel.userKey,
                                    otherUserKey: otherUser.userKey);
                          });
                        },
                        leading: RoundedAvatar(),
                        title: Text(otherUser.username),
                        subtitle:
                            Text('this is user bio of ${otherUser.username}'),
                        trailing: Container(
                          height: 30,
                          width: 80,
                          // Container 중앙정렬
                          alignment: Alignment.center,
                          decoration: BoxDecoration(
                            // 배경색
                            color:
                                amIFollowing ? Colors.red[50] : Colors.blue[50],
                            // 테두리 모양
                            border: Border.all(
                                color: amIFollowing ? Colors.red : Colors.blue,
                                width: 0.5),
                            // 모서리 둥글기
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: Text(
                            amIFollowing ? 'unfollow' : 'follow',
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                        ),
                      );
                    },
                    separatorBuilder: (context, builder) {
                      return Divider(
                        // 구분선
                        color: Colors.grey,
                      );
                    },
                  );
                },
              ),
            );
          } else {
            return MyProgressIndicator();
          }
        },
      ),
    );
  }
}
// repo/user_model_state.dart

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter_project_IJ/models/firestore/user_model.dart';

// 유저마다 다른 데이터를 위젯에 새로 출력하기 위해 작성.
class UserModelState extends ChangeNotifier {
  UserModel _userModel;

  // 구독 정보를 저장하고 있다가 사용자가 로그아웃하면
  // 더 이상 데이터를 전달 받지 않도록 구독을 취소함.
  StreamSubscription<UserModel> _currentStreamSub;

  UserModel get userModel => _userModel;

  // userModel 데이터가 바뀔 때 해당 위젯에 알려줌.
  set userModel(UserModel userModel) {
    _userModel = userModel;
    notifyListeners();
  }

  // currentStreamSub을 받아와서 _currentStreamSub에 저장.
  set currentStreamSub(StreamSubscription<UserModel> currentStreamSub) =>
      _currentStreamSub = currentStreamSub;

  clear() {
    // null이 아니면 실행.
    if(_currentStreamSub != null)
      _currentStreamSub.cancel();
    _currentStreamSub = null;
    _userModel = null;
  }
  
  bool amIFollowingThisUser(String otherUserKey) {
    // 다른 유저의 키를 가지고 있으면 follow, 아니면 unfollow
    return _userModel.followings.contains(otherUserKey);
  }
}
Comments