Skip to content

Commit

Permalink
Feature/친구 목록 스크린 로직 개선 (#85)
Browse files Browse the repository at this point in the history
Co-authored-by: Jungwoo <108061510+jwson-automation@users.noreply.github.com>
  • Loading branch information
ottuck and jwson-automation authored Aug 31, 2024
1 parent b8cc023 commit 2da5e49
Show file tree
Hide file tree
Showing 12 changed files with 319 additions and 144 deletions.
10 changes: 10 additions & 0 deletions lib/feature/friendsList/provider/FriendsListImageProvider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 친구목록 이미지 URL을 제공하는 Provider
final friendsListImageProvider =
FutureProvider.family<String, String>((ref, imageName) async {
final storageRef = FirebaseStorage.instance.ref('profileimage/$imageName');
final downloadUrl = await storageRef.getDownloadURL();
return downloadUrl;
});
96 changes: 74 additions & 22 deletions lib/feature/friendsList/provider/FriendsListProvider.dart
Original file line number Diff line number Diff line change
@@ -1,41 +1,93 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../model/FriendModel.dart';
import '../../../utils/AppStrings.dart';
import '../../../utils/Talker.dart';
import '../../userreport/provider/UserReportBottomSheetWidget.dart';

// 친구 목록을 제공하는 Provider
// 친구목록을 제공하는 Provider
final friendsListProvider = StreamProvider<List<FriendModel>>((ref) {
final firestore = FirebaseFirestore.instance;

const userId = 'eztqDqrvEXDc8nqnnrB8'; // 로그인을 가정한 임시 유저 ID

return firestore
.collection('users_test')
.doc(userId)
.collection('friends')
.snapshots()
.map((snapshot) {
return snapshot.docs.map((doc) {
final data = doc.data();
return FriendModel.fromJson({
...data,
'lastConnect':
(data['lastConnect'] as Timestamp).toDate().toIso8601String(),
});
}).toList();
.asyncMap((snapshot) async {
final friendModels = await Future.wait(snapshot.docs.map((doc) async {
final userID = doc['userID'] as String;
final userDoc = await firestore.collection('users_test').doc(userID).get();

if (userDoc.exists) {
return FriendModel.fromJson(userDoc.data()!);
} else {
throw Exception(AppStrings.userNotFoundErrorMessage);
}
}).toList());

return friendModels;
});
});

// 친구목록 이미지 URL을 제공하는 Provider
final friendsListImageProvider =
FutureProvider.family<String, String>((ref, imageName) async {
final ref = FirebaseStorage.instance.ref('friends-profile/$imageName');
return await ref.getDownloadURL();
final deleteFriendProvider =
Provider<Future<void> Function(BuildContext, FriendModel)>((ref) {
return (BuildContext context, FriendModel friend) async {
final firestore = FirebaseFirestore.instance;
const userId = 'eztqDqrvEXDc8nqnnrB8'; // 로그인을 가정한 임시 유저 ID

await firestore
.collection('users_test')
.doc(userId)
.collection('friends')
.doc(friend.userID)
.delete();

ref.invalidate(friendsListProvider);

if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text(AppStrings.friendDeleteSuccessMessage)),
);
}
};
});

// /// 이미지 URL을 제공하는 공용 Provider
// final imageProvider = FutureProvider.family<String, String>((ref, imagePath) async {
// final ref = FirebaseStorage.instance.ref(imagePath);
// return await ref.getDownloadURL();
// });


// ui 팝업 메뉴 선택시 처리하는 함수
void handleMenuSelection(
BuildContext context, WidgetRef ref, int value, FriendModel friend) async {
switch (value) {
case 1:
// 삭제
final deleteFriend = ref.read(deleteFriendProvider);
Navigator.of(context).pop();
await deleteFriend(context, friend);
break;
case 2:
Navigator.of(context).pop();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('차단 기능이 아직 구현되지 않았습니다.')),
);
}
break;
case 3:
// 신고
Navigator.of(context).pop();
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),
),
builder: (context) => UserReportBottomSheetWidget(friend: friend),
);
break;
}
}
10 changes: 7 additions & 3 deletions lib/feature/friendsList/widget/BottomSheetButtonWidget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ class BottomSheetButtonWidget extends StatelessWidget {
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
borderRadius: BorderRadius.circular(12),
),
minimumSize: const Size(140, 50),
textStyle: const TextStyle(
fontSize: 16, // 더 큰 텍스트 크기
fontWeight: FontWeight.bold,
),
minimumSize: const Size(120, 40), // 버튼 크기
),
onPressed: onPressed,
child: Text(text),
Expand Down
165 changes: 88 additions & 77 deletions lib/feature/friendsList/widget/FriendBottomSheet.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../../../model/FriendModel.dart';
import '../../../utils/AppStrings.dart';
import '../../userreport/provider/UserReportBottomSheetWidget.dart';
import '../provider/FriendsListProvider.dart';
import 'BottomSheetButtonWidget.dart';
import 'PopupMenuItem.dart';
import '../../../utils/AppStrings.dart';

class FriendBottomSheetWidget extends StatelessWidget {
final FriendModel friend;
Expand All @@ -16,88 +18,97 @@ class FriendBottomSheetWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Container(
height: 260, // 바텀 시트 높이 수정 부분
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: const BorderRadius.vertical(
top: Radius.circular(25.0),
),
),
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Row(
children: [
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 4),
image: DecorationImage(
image: CachedNetworkImageProvider(imageUrl),
fit: BoxFit.cover,
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(friend.name,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 20)),
const SizedBox(height: 8),
Text(friend.status, style: const TextStyle(fontSize: 16)),
],
),
),
],
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: const BorderRadius.vertical(
top: Radius.circular(25.0),
),
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
BottomSheetButtonWidget(
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).push('/chat');
},
text: AppStrings.chatButton,
),
BottomSheetButtonWidget(
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context)
.push('/userdetail'); // 현재 임의 경로 사용 중 수정 필요
},
text: AppStrings.profileButton,
),
BottomSheetButtonWidget(
onPressed: () {
Navigator.of(context).pop();
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.vertical(top: Radius.circular(25.0)),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 4),
image: DecorationImage(
image: CachedNetworkImageProvider(imageUrl),
fit: BoxFit.cover,
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(friend.name,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 20)),
const SizedBox(height: 8),
Text(friend.status,
style: const TextStyle(fontSize: 16)),
],
),
),
builder: (context) =>
UserReportBottomSheetWidget(friend: friend),
);
},
text: AppStrings.reportButton,
Consumer(
builder: (context, ref, child) {
return PopupMenuButton<int>(
onSelected: (value) =>
handleMenuSelection(context, ref, value, friend),
itemBuilder: (context) => [
buildPopupMenuItem(
icon: Icons.delete,
text: AppStrings.deleteButton,
value: 1),
buildPopupMenuItem(
icon: Icons.block,
text: AppStrings.blockButton,
value: 2),
buildPopupMenuItem(
icon: Icons.report,
text: AppStrings.reportButton,
value: 3),
],
);
},
),
],
),
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
BottomSheetButtonWidget(
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).push('/chat');
},
text: AppStrings.chatButton,
),
BottomSheetButtonWidget(
onPressed: () {
Navigator.of(context).pop();
GoRouter.of(context).push('/userdetail');
},
text: AppStrings.profileButton,
),
],
),
],
),
],
),
),
);
}
Expand Down
26 changes: 26 additions & 0 deletions lib/feature/friendsList/widget/FriendBottomSheetLauncher.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';

import '../../../model/FriendModel.dart';
import 'FriendBottomSheet.dart';

class FriendBottomSheetLauncher {
static void show({
required BuildContext context,
required FriendModel friend,
required String imageUrl,
}) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(25.0),
),
),
builder: (context) => FriendBottomSheetWidget(
friend: friend,
imageUrl: imageUrl,
),
);
}
}
Loading

0 comments on commit 2da5e49

Please sign in to comment.