-
Notifications
You must be signed in to change notification settings - Fork 0
홈화면 UI 수정 반영 및기존 카드 올라갔다 내려가는 카드 애니메이션 변경점 적용 필요 #382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
홈화면 UI 수정 반영 및기존 카드 올라갔다 내려가는 카드 애니메이션 변경점 적용 필요 #382
The head ref may contain hidden characters: "20250917_#280_v2_\uAE30\uB2A5\uAC1C\uC120_\uD648\uD654\uBA74_\uD648\uD654\uBA74_UI_\uC218\uC815_\uBC18\uC601_\uBC0F\uAE30\uC874_\uCE74\uB4DC_\uC62C\uB77C\uAC14\uB2E4_\uB0B4\uB824\uAC00\uB294_\uCE74\uB4DC_\uC560\uB2C8\uBA54\uC774\uC158_\uBCC0\uACBD\uC810_\uC801\uC6A9_\uD544\uC694"
Conversation
…한 애니메이션 수정 및 성공 토스트창 표시 #280
Walkthrough홈 탭의 거래 다이얼로그를 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant HomeScreen
participant TradeDialog as _TradeRequestDialog
participant API
participant Scaffold
User->>HomeScreen: 거래 요청(카드 선택)
HomeScreen->>TradeDialog: showDialog(...) (scale+fade, blur)
TradeDialog->>User: 옵션 선택 UI
User->>TradeDialog: 옵션 선택 / 전송
TradeDialog->>API: onSendRequest(payload)
alt 성공
API-->>TradeDialog: success
TradeDialog->>Scaffold: showSnackBar("요청 전송 완료")
TradeDialog-->>HomeScreen: onSendRequest 완료 콜백
else 실패
API-->>TradeDialog: error
TradeDialog->>TradeDialog: showErrorModal(...)
end
TradeDialog-->>HomeScreen: onCancel / 닫기
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
lib/screens/home_tab_screen.dart (1)
570-635: 거래 요청 다이얼로그 showDialog 설정 및 상태 초기화 전반적으로 적절함
- 카드 드롭 시 point-in-time 의
cardData와_currentFeedIndex를 사용해TradeRequest를 구성하는 흐름이 자연스럽고, 성공/실패에 대한 스낵바·에러 모달 처리도 잘 되어 있습니다.finally블록에서_selectedTradeOptions.clear()를 호출해 옵션 상태를 항상 초기화하는 점도 좋습니다.한 가지,
barrierColor: Colors.transparent는 팀 가이드라인상 직접 Colors.* 대신AppColors계열로 치환하는 것이 좋습니다. 필요하다면 AppColors 에 투명 색을 추가해 사용하도록 정리해 주세요. As per coding guidelines, ...lib/widgets/home_tab_card_hand.dart (2)
268-285: 카드 AnimatedBuilder 의 animation 목록에서 _dropZonePulseAnimation 제거 고려
_buildCard의AnimatedBuilder가Listenable.merge에_fanAnimation,_pullAnimation,_cardAbsorbAnimation,_dropZonePulseAnimation을 모두 포함하고 있지만, 카드 렌더링 로직에서는_dropZonePulseAnimation값을 직접 사용하지 않습니다.- 이 상태에서는 드롭존 펄스 애니메이션이 도는 동안 각 카드 위젯도 매 프레임 rebuild 되므로(최대 10장), 미세하지만 불필요한 작업이 발생할 수 있습니다.
카드는
_fanAnimation,_pullAnimation,_cardAbsorbAnimation만 merge 하고, 드롭존은 별도의AnimatedBuilder(이미 아래에 존재)를 사용하는 지금 구조를 유지하는 쪽으로, 카드 쪽 merge 목록에서_dropZonePulseAnimation만 제거하면 더 깔끔할 것 같습니다.Also applies to: 332-352
525-581: 드롭존 펄스 연출과 실제 드롭 판정 영역 간의 차이를 인지해 두면 좋겠습니다
- 드롭 성공 시
_dropZonePulseController+Transform.scale로 드롭존이 시각적으로 1.15배 정도 커지지만, 충돌 판정은_globalRectOf(_dropZoneKey)에서 가져온 layout 기준Rect를 사용합니다.- 즉, 펄스 상태에서는 보이는 영역이 실제 판정보다 약간 더 커질 수 있습니다. UX 상 크게 문제되지 않는다면 그대로 둬도 괜찮지만,
드롭 판정과 시각적 영역을 최대한 맞추고 싶다면 scale 값을 반영한 hit 영역 계산(예: scale 을 곱한 가상 Rect 로 overlaps 체크)을 고려할 수 있습니다.기능상 버그는 아니고, 향후 연출/판정 미세 조정 시 참고하면 좋을 정도의 포인트입니다.
Also applies to: 671-705
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
ios/Podfile.lockis excluded by!**/*.lockpubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
.gitignore(2 hunks)lib/screens/home_tab_screen.dart(2 hunks)lib/widgets/home_tab_card_hand.dart(8 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.dart: Use CustomTextStyles for all text styling in Flutter widgets - never define TextStyle directly
Use AppColors for all color values - never use direct Color codes or Colors constants
Use the team's common extension methodcontext.navigateTo()for screen navigation to support iOS swipe gesture handling
Files:
lib/widgets/home_tab_card_hand.dartlib/screens/home_tab_screen.dart
**/lib/widgets/**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
Do not use unnecessary
_widgetsuffix in widget filenames
Files:
lib/widgets/home_tab_card_hand.dart
🧠 Learnings (2)
📚 Learning: 2025-11-28T09:18:17.218Z
Learnt from: CR
Repo: TEAM-ROMROM/RomRom-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-28T09:18:17.218Z
Learning: Applies to **/lib/widgets/**/*.dart : Do not use unnecessary `_widget` suffix in widget filenames
Applied to files:
lib/screens/home_tab_screen.dart
📚 Learning: 2025-11-28T09:18:17.218Z
Learnt from: CR
Repo: TEAM-ROMROM/RomRom-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-28T09:18:17.218Z
Learning: Applies to **/*.dart : Use the team's common extension method `context.navigateTo()` for screen navigation to support iOS swipe gesture handling
Applied to files:
lib/screens/home_tab_screen.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: 프로젝트 빌드 테스트
🔇 Additional comments (2)
.gitignore (1)
47-48: 좋습니다. Android 키스토어 속성 파일 무시 규칙이 적절하게 추가되었습니다.파일 위치와 주석이 명확하며, 기존의 다른 키스토어 관련 무시 규칙들(
key.jks,key.jks.b64) 근처에 논리적으로 배치되어 있습니다.lib/widgets/home_tab_card_hand.dart (1)
31-39: 새 흡수/펄스 애니메이션 컨트롤러 초기화·해제가 일관적으로 잘 구성됨
_cardAbsorbController,_dropZonePulseController를_initializeAnimations에서 생성하고dispose에서 모두 정리해 주어 애니메이션 컨트롤러 누수 위험이 없어 보입니다._isAbsorbing,_dropZoneCenter도 드롭 완료 후 지연 콜백에서 한 번에 초기화하고, 컨트롤러reset()까지 호출하는 구조라 상태 꼬임 가능성이 낮습니다.이 부분은 현재 형태 그대로 유지해도 무방해 보입니다.
Also applies to: 78-80, 120-167, 194-203
| # Google Cloud 서비스 계정 키 파일 | ||
| *-*.json | ||
| romrom-*.json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
head -120 .gitignore | tail -20Repository: TEAM-ROMROM/RomRom-FE
Length of output: 383
🏁 Script executed:
# Find all .json files in the repository to see what legitimate configs exist
find . -type f -name "*.json" | head -30Repository: TEAM-ROMROM/RomRom-FE
Length of output: 535
🌐 Web query:
Google Cloud service account key file naming convention
💡 Result:
Short answer: Google Cloud does not enforce a specific service-account key filename. The console downloads a JSON key file when you create a key, and the gcloud command requires you to supply an output filename — you can move/rename the file however you like. Common practice is to use descriptive names (for example PROJECTID-.json or -key.json) for clarity. [1][2][3]
Sources:
- Create and delete service account keys (IAM) — notes that clicking Create downloads the JSON key and “You can move and rename this file however you like.” [1]
- gcloud iam service-accounts keys create — shows the command takes an OUTPUT-FILE argument (you choose the filename). [2]
- Example usage in Google docs (Apigee) showing common descriptive filename patterns like PROJECT_ID-.json. [3]
*-*.json pattern is too broad and incorrectly ignores legitimate project files.
The current pattern catches package-lock.json, which is a legitimate dependency lock file that should be committed to version control. This demonstrates the pattern is overly broad.
Google Cloud service account keys have no enforced naming convention—they can be named anything. Common practices include *-key.json or descriptive patterns like projectid-serviceaccount.json, but these are not mandatory. Given that the repository already uses romrom-*.json for its own service accounts, refine the pattern to match your actual naming convention rather than a catch-all.
Replace *-*.json with specific patterns like *-key.json or more descriptive identifiers matching your Google Cloud key files to avoid accidentally ignoring legitimate configuration files.
🤖 Prompt for AI Agents
.gitignore around lines 106 to 108: the current glob "*-*.json" is too broad and
unintentionally excludes valid files (e.g., package-lock.json); remove that
generic pattern and replace it with specific, intentional patterns that match
only your service account keys (for example use patterns like "*-key.json",
"romrom-*.json" is OK to keep for repo-specific keys, or add explicit filenames
you want ignored); update the file to delete "*-*.json" and add one or more
narrow patterns that reflect the actual naming convention for Google Cloud key
files used in this project.
| /// 거래 요청 다이얼로그 (우아한 등장 애니메이션 포함) | ||
| class _TradeRequestDialog extends StatefulWidget { | ||
| final Item cardData; | ||
| final List<ItemTradeOption> selectedTradeOptions; | ||
| final Function(ItemTradeOption) onOptionSelected; | ||
| final VoidCallback onCancel; | ||
| final VoidCallback onSendRequest; | ||
|
|
||
| const _TradeRequestDialog({ | ||
| required this.cardData, | ||
| required this.selectedTradeOptions, | ||
| required this.onOptionSelected, | ||
| required this.onCancel, | ||
| required this.onSendRequest, | ||
| }); | ||
|
|
||
| @override | ||
| State<_TradeRequestDialog> createState() => _TradeRequestDialogState(); | ||
| } | ||
|
|
||
| class _TradeRequestDialogState extends State<_TradeRequestDialog> | ||
| with SingleTickerProviderStateMixin { | ||
| late AnimationController _controller; | ||
| late Animation<double> _scaleAnimation; | ||
| late Animation<double> _fadeAnimation; | ||
|
|
||
| @override | ||
| void initState() { | ||
| super.initState(); | ||
| _controller = AnimationController( | ||
| duration: const Duration(milliseconds: 400), | ||
| vsync: this, | ||
| ); | ||
|
|
||
| _scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate( | ||
| CurvedAnimation( | ||
| parent: _controller, | ||
| curve: Curves.easeOutBack, | ||
| ), | ||
| ); | ||
|
|
||
| _fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate( | ||
| CurvedAnimation( | ||
| parent: _controller, | ||
| curve: Curves.easeOut, | ||
| ), | ||
| ); | ||
|
|
||
| // 애니메이션 시작 | ||
| WidgetsBinding.instance.addPostFrameCallback((_) { | ||
| _controller.forward(); | ||
| }); | ||
| } | ||
|
|
||
| @override | ||
| void dispose() { | ||
| _controller.dispose(); | ||
| super.dispose(); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return Material( | ||
| type: MaterialType.transparency, | ||
| child: AnimatedBuilder( | ||
| animation: _controller, | ||
| builder: (context, child) { | ||
| return Opacity( | ||
| opacity: _fadeAnimation.value, | ||
| child: BackdropFilter( | ||
| filter: ImageFilter.blur( | ||
| sigmaX: 30 * _fadeAnimation.value, | ||
| sigmaY: 30 * _fadeAnimation.value, | ||
| ), | ||
| child: Center( | ||
| child: Transform.scale( | ||
| scale: _scaleAnimation.value, | ||
| child: Padding( | ||
| padding: EdgeInsets.symmetric( | ||
| horizontal: 40.0.w, | ||
| vertical: 65.0.h, | ||
| ), | ||
| child: Column( | ||
| mainAxisSize: MainAxisSize.min, | ||
| children: [ | ||
| SizedBox(height: 5.h), | ||
| SizedBox( | ||
| width: 310.w, | ||
| height: 496.h, | ||
| child: ItemCard( | ||
| itemId: widget.cardData.itemId!, | ||
| itemName: widget.cardData.itemName!, | ||
| itemCategoryLabel: ItemCategories.fromServerName( | ||
| widget.cardData.itemCategory!, | ||
| ).label, | ||
| itemCardImageUrl: widget.cardData.primaryImageUrl != | ||
| null | ||
| ? widget.cardData.primaryImageUrl! | ||
| : 'https://picsum.photos/400/300', | ||
| onOptionSelected: widget.onOptionSelected, | ||
| ), | ||
| ), | ||
| SizedBox(height: 32.h), | ||
| Row( | ||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
| children: [ | ||
| CompletionButton( | ||
| isEnabled: true, | ||
| buttonText: '취소', | ||
| buttonWidth: 130, | ||
| buttonHeight: 44, | ||
| enabledBackgroundColor: | ||
| AppColors.transactionRequestDialogCancelButton, | ||
| enabledOnPressed: widget.onCancel, | ||
| ), | ||
| CompletionButton( | ||
| isEnabled: true, | ||
| buttonText: '요청 보내기', | ||
| buttonWidth: 171, | ||
| buttonHeight: 44, | ||
| enabledOnPressed: widget.onSendRequest, | ||
| ), | ||
| ], | ||
| ), | ||
| ], | ||
| ), | ||
| ), | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| }, | ||
| ), | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_TradeRequestDialog 내 null‑safety 보완 및 중복 요청 방지 필요
ItemCard생성 시widget.cardData.itemId!,widget.cardData.itemName!,widget.cardData.itemCategory!에 모두!를 사용하고 있습니다. 백엔드 응답이 깨졌거나 필드가 비워진 경우 런타임 크래시로 이어질 수 있으니,itemName은?? '아이템'같은 기본값을 두고,itemCategory는 null 시 fallback 라벨을 사용하거나, 다이얼로그를 열기 전에 필수 필드 검증을 통해 조기에 막는 방식으로 방어 코드를 추가하는 것이 안전합니다.
"요청 보내기"버튼은 API 호출 중에도isEnabled: true로 남아 있어 빠르게 여러 번 탭하면requestTrade가 중복 호출될 수 있습니다. 요청 중에는 로딩 상태를 두고 버튼을 비활성화하거나, 내부에서isSending플래그로 재진입을 막는 것을 권장합니다.
위 두 부분만 보완하면 다이얼로그 자체의 애니메이션·레이아웃 구조는 잘 잡혀 있습니다.
|
✅ 프로젝트 빌드 성공 APK 빌드가 완료되었습니다. |
…드_올라갔다_내려가는_카드_애니메이션_변경점_적용_필요
|
✅ 프로젝트 빌드 성공 APK 빌드가 완료되었습니다. |
|
✅ 프로젝트 빌드 성공 APK 빌드가 완료되었습니다. |
|
@suh-lab app build |
|
🚀 앱 빌드 트리거 완료 Android와 iOS 빌드 워크플로우를 시작했습니다.
|
|
🤖 ✅ Android 테스트 APK 빌드 완료
|
|
🍎 ✅ iOS TestFlight 빌드 완료
📱 TestFlight에서 테스트 앱을 다운로드할 수 있습니다. |
|
@suh-lab app build |
|
🚀 앱 빌드 트리거 완료 Android와 iOS 빌드 워크플로우를 시작했습니다.
⏳ 빌드가 완료되면 자동으로 결과 댓글이 작성됩니다. |
|
@suh-lab app build |
|
🚀 앱 빌드 트리거 완료 Android와 iOS 빌드 워크플로우를 시작했습니다.
⏳ 빌드가 완료되면 자동으로 결과 댓글이 작성됩니다. |
|
🤖 ✅ Android 테스트 APK 빌드 완료
|
|
🍎 ✅ iOS TestFlight 빌드 완료
📱 TestFlight에서 테스트 앱을 다운로드할 수 있습니다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
lib/screens/home_tab_screen.dart (1)
570-570: AppColors 사용 권장코딩 가이드라인에 따르면 Colors 상수 대신 AppColors를 사용해야 합니다.
Colors.transparent대신AppColors에 투명 색상 상수를 추가하거나, 이미 정의된 투명 색상이 있다면 그것을 사용하는 것을 권장합니다.🔎 제안된 수정
AppColors에 투명 색상 상수가 있다면:
- barrierColor: Colors.transparent, + barrierColor: AppColors.transparent, // 또는 적절한 AppColors 상수
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
ios/Podfile.lockis excluded by!**/*.lock
📒 Files selected for processing (1)
lib/screens/home_tab_screen.dart
🧰 Additional context used
📓 Path-based instructions (1)
**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.dart: Use CustomTextStyles for all text styling in Flutter widgets - never define TextStyle directly
Use AppColors for all color values - never use direct Color codes or Colors constants
Use the team's common extension methodcontext.navigateTo()for screen navigation to support iOS swipe gesture handling
Files:
lib/screens/home_tab_screen.dart
🧠 Learnings (2)
📚 Learning: 2025-11-28T09:18:17.218Z
Learnt from: CR
Repo: TEAM-ROMROM/RomRom-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-28T09:18:17.218Z
Learning: Applies to **/*.dart : Use the team's common extension method `context.navigateTo()` for screen navigation to support iOS swipe gesture handling
Applied to files:
lib/screens/home_tab_screen.dart
📚 Learning: 2025-11-28T09:18:17.218Z
Learnt from: CR
Repo: TEAM-ROMROM/RomRom-FE PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-28T09:18:17.218Z
Learning: Applies to **/lib/widgets/**/*.dart : Do not use unnecessary `_widget` suffix in widget filenames
Applied to files:
lib/screens/home_tab_screen.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: 프로젝트 빌드 테스트
🔇 Additional comments (4)
lib/screens/home_tab_screen.dart (4)
572-629: 다이얼로그 리팩토링 잘 되었습니다인라인 다이얼로그 로직을
_TradeRequestDialog로 추출하여 코드 구조가 깔끔해졌습니다. 콜백을 통한 상태 관리와 에러 처리도 적절하게 구현되어 있습니다.finally블록에서 상태 정리를 수행하는 것도 좋은 접근입니다.
734-752: 위젯 구조 깔끔합니다
_TradeRequestDialog위젯의 선언과 매개변수 구조가 명확하고 재사용 가능한 형태로 잘 설계되었습니다.
754-792: 애니메이션 구현이 우수합니다스케일과 페이드 애니메이션 설정이 적절하며,
postFrameCallback을 사용한 애니메이션 시작과dispose에서의 컨트롤러 정리가 올바르게 구현되어 있습니다.easeOutBack과easeOut커브 선택도 다이얼로그 등장 효과에 적합합니다.
794-869: UI 구현은 우수하나 이전 리뷰 지적사항 확인 필요다이얼로그의 애니메이션 통합과 UI 레이아웃이 잘 구성되어 있습니다.
BackdropFilter를 페이드 애니메이션과 연동한 부분도 좋습니다.다만, 이전 리뷰에서 지적된 다음 사항들이 아직 해결되지 않았습니다:
- Lines 824-828:
itemId!,itemName!,itemCategory!의 null-safety 보완 필요 (critical)- Line 850: 중복 요청 방지를 위한 버튼 비활성화 로직 필요 (major)
이전 리뷰 코멘트를 참고하여 해당 이슈들을 해결해 주시기 바랍니다.
|
✅ 프로젝트 빌드 성공 APK 빌드가 완료되었습니다. |
|
@suh-lab app build |
|
🚀 앱 빌드 트리거 완료 Android와 iOS 빌드 워크플로우를 시작했습니다.
⏳ 빌드가 완료되면 자동으로 결과 댓글이 작성됩니다. |
|
🤖 ✅ Android 테스트 APK 빌드 완료
|
|
🍎 ✅ iOS TestFlight 빌드 완료
📱 TestFlight에서 테스트 앱을 다운로드할 수 있습니다. |
Summary by CodeRabbit
릴리스 노트
New Features
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.