Skip to content

Commit

Permalink
Merge branch 'release/2024-summer' into feature/naverLogin
Browse files Browse the repository at this point in the history
  • Loading branch information
mrnkim committed Sep 4, 2024
2 parents 646c574 + c5b12ef commit b0b2739
Show file tree
Hide file tree
Showing 40 changed files with 1,205 additions and 505 deletions.
29 changes: 23 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ROOT := $(shell git rev-parse --show-toplevel)

# Detect operating system
ifeq ($(OS), Windows_NT)
DETECTED_OS := Windows
Expand All @@ -12,10 +11,23 @@ else
FLUTTER := $(shell which flutter)
endif
endif

# Define the default target to call all necessary targets
all: init analyze apply format buildRunner

# Define the init target to initialize the project
first : create init analyze buildRunner env
setting : init buildRunner
lint : analyze apply format

# Define the init target
create:
@echo "Create ios and android floder..."
ifeq ($(DETECTED_OS), Windows)
@flutter create .
else
@$(FLUTTER) create .
endif

# Define the init target
init:
@echo "Initializing Flutter project..."
Expand All @@ -24,7 +36,6 @@ ifeq ($(DETECTED_OS), Windows)
else
@$(FLUTTER) pub get
endif

# Define the analyze target
analyze:
@echo "Analyzing Flutter project..."
Expand All @@ -33,7 +44,6 @@ ifeq ($(DETECTED_OS), Windows)
else
-@$(FLUTTER) analyze
endif

# Define the apply target
apply:
@echo "Applying dart fixes..."
Expand All @@ -42,7 +52,6 @@ ifeq ($(DETECTED_OS), Windows)
else
@dart fix --apply
endif

# Define the apply target
format:
@echo "format dart fixes..."
Expand All @@ -51,7 +60,6 @@ ifeq ($(DETECTED_OS), Windows)
else
@dart format .
endif

# Define the buildRunner target
buildRunner:
@echo "Freezed Running build runner..."
Expand All @@ -61,3 +69,12 @@ else
@$(FLUTTER) pub run build_runner build --delete-conflicting-outputs
endif

# Define the env target for Unix-like systems
env:
ifeq ($(DETECTED_OS), Windows)
@echo "Using PowerShell script to create .env file."
@powershell -ExecutionPolicy Bypass -File generate_env.ps1
else
@echo "Using bash script to create .env file."
@bash generate_env.sh
endif
Binary file added assets/launcher_icon/kimberry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions generate_env.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# PowerShell 스크립트로 .env 파일 생성

# 현재 작업 중인 디렉터리 경로 가져오기
$TargetDir = Get-Location

# .env 파일 내용
$envContent = @"
# please replace 'your_api_key_here' with your actual API key
GOOGLE_API_KEY=your_api_key_here
GPT_API_KEY=your_api_key_here
# Other environment variables can be added here
"@

# .env 파일 생성
$envFilePath = Join-Path -Path $TargetDir -ChildPath ".env"
Write-Output "Creating .env file at: $envFilePath"

# UTF-8 인코딩으로 파일 생성
$envContent | Out-File -FilePath $envFilePath -Encoding utf8
5 changes: 5 additions & 0 deletions generate_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# .env 파일 생성
echo "# please replace 'your_api_key_here' with your actual API key" > ".env"
echo "GOOGLE_API_KEY=your_api_key_here" >> ".env"
echo "GPT_API_KEY=your_api_key_here" >> ".env"
echo "# Other environment variables can be added here" >> ".env"
46 changes: 46 additions & 0 deletions integration_test/app_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:blueberry_flutter_template/firebase_options.dart';
import 'package:blueberry_flutter_template/model/PetProfileModel.dart';
import 'package:blueberry_flutter_template/model/PostModel.dart';
import 'package:blueberry_flutter_template/model/UserModel.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -39,5 +41,49 @@ void main() {
// Then: 매핑된 데이터 검증
expect(fetchedData, isNotNull, reason: 'fetchedData는 null이 아니어야 합니다.');
});

test('user 컬렉션이 있을 때, 첫 번째 문서를 가져와 fromJson 메서드로 매핑하면, 오류 없이 매핑된다',
() async {
UserModel? fetchedData;

// Given: 컬렉션 이름 설정
collectionName = 'users';

// When: 첫 번째 문서 가져오기 및 fromJson 매핑
final querySnapshot =
await firestore.collection(collectionName).limit(1).get();

if (querySnapshot.docs.isNotEmpty) {
final data = querySnapshot.docs.first.data();
fetchedData = UserModel.fromJson(data);
} else {
throw Exception('$collectionName 컬렉션 안에 다큐먼트가 존재하지 않습니다');
}

// Then: 매핑된 데이터 검증
expect(fetchedData, isNotNull, reason: 'fetchedData는 null이 아니어야 합니다.');
});

test('posts 컬렉션이 있을 때, 첫 번째 문서를 가져와 fromJson 메서드로 매핑하면, 오류 없이 매핑된다',
() async {
PostModel? fetchedPost;

// Given: 컬렉션 이름 설정
collectionName = 'posts';

// When: 첫 번째 문서 가져오기 및 fromJson 매핑
final querySnapshot =
await firestore.collection(collectionName).limit(1).get();

if (querySnapshot.docs.isNotEmpty) {
final data = querySnapshot.docs.first.data();
fetchedPost = PostModel.fromJson(data);
} else {
throw Exception('$collectionName 컬렉션 안에 다큐먼트가 존재하지 않습니다');
}

// Then: 매핑된 데이터 검증
expect(fetchedPost, isNotNull, reason: 'fetchedPost는 null이 아니어야 합니다.');
});
});
}
2 changes: 1 addition & 1 deletion lib/core/TopScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class TopScreen extends ConsumerWidget {
selectedIconTheme: const IconThemeData(color: Colors.black),
selectedItemColor: Colors.black,
unselectedIconTheme: const IconThemeData(color: Colors.grey),
backgroundColor: Colors.blueGrey[100],
backgroundColor: Colors.white,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.podcasts),
Expand Down
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;
});
95 changes: 72 additions & 23 deletions lib/feature/friendsList/provider/FriendsListProvider.dart
Original file line number Diff line number Diff line change
@@ -1,41 +1,90 @@
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 '../../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
Loading

0 comments on commit b0b2739

Please sign in to comment.