보관함 상세 화면 및 카드 물리 낙하 애니메이션 추가 - #43
Draft
soyeonLee126 wants to merge 30 commits into
Draft
Conversation
ArchiveScreen에서만 참조되던 worry_bin 시리즈가 feature/home에도 중복으로 남아있어 삭제한다.
body/note 레이어가 분리되어 있던 기존 worry_bin 에셋은 투명 캔버스 대비 그림이 작아 FillWidth 스케일링 시 깨져 보였다. Figma에서 내보낸 카드 단위 통합 이미지로 교체하고, 그리드 레이아웃/카드 크기를 디자인 실측 값에 맞춰 조정했다.
TopLevelDestinationTest가 삭제된 CalendarKey를 계속 참조해 테스트 컴파일이 깨져 있었다. 또한 바텀바 아이템만 원격 설정으로 가려지고 ArchiveKey 네비게이션 엔트리 자체는 가드가 없어, 백스택 복원 등으로 진입 시 숨겨진 화면이 그려질 수 있었다.
getCardsByDate(조회)와 createCard(쓰기)가 호출부가 완전히 갈리는데도 한 인터페이스에 묶여 있어서, 서로 무관한 화면의 테스트 더블들이 쓰지 않는 메서드를 매번 스텁해야 했다. CardQueryRepository/CardWriteRepository로 나누고 CardRepositoryImpl이 둘 다 구현하도록 정리했다.
감정 쓰레기통을 열면 그 달 카드들이 원 충돌 기반 경량 2D 물리 시뮬레이션(중력, 벽/바닥 반발, 카드 간 충돌)으로 낙하해 쌓이는 연출을 넣었다. PaperPhysics.kt는 Compose 의존성 없는 순수 Kotlin이라 물리 로직만 따로 검증할 수 있다. 보관함 그리드에서 감정 쓰레기통을 누르면 상세 화면으로 이동하도록 클릭도 연결했다.
ArchiveDetailKey 라우트를 등록하고, 보관함 그리드의 클릭을 상세 화면 네비게이션으로 이어준다.
카드 기능을 원격 설정과 무관하게 항상 노출하기로 하면서, 타임아웃/재조회까지 갖췄던 remoteConfigGate()가 상수 true를 내보내는 용도로만 남았다. 관련 유스케이스 의존성과 불필요해진 대기 로직을 함께 정리했다.
There was a problem hiding this comment.
detekt found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
PaperBody 생성자 파라미터 수 축소(6개로), 긴 인자 목록 줄바꿈, 최대 줄 길이 초과, 미사용 import, 상단 상수 SCREAMING_CASE 네이밍, import 정렬, 들여쓰기, 미사용 Preview 함수에 대한 @Suppress 누락을 정리했다.
Scaffold 기본 인셋과 GamssBottomBar 자체의 navigationBarsPadding 이 겹쳐 있던 것도 정리했다. 탭바는 하위 화면 진입 시 AnimatedVisibility 로 접히도록 해서, 그 자리만큼 화면이 갑자기 넓어져 보이던 현상을 완화한다.
- 쓰레기통 카드 클릭 시 나타나던 리플/딤 효과 제거 - 보관함 탭은 MainScreen 탭바 위에 떠서 화면 하단에 직접 닿지 않으므로, Scaffold 기본 인셋 대신 상태바 인셋만 반영해 이중 여백을 없앴다 - 기기별로 남는 세로 여백을 위아래로 분산하도록 콘텐츠를 중앙 정렬했다. 타이틀과 그리드를 하나의 Column으로 묶어, Box 안에서 각자 따로 정렬되며 겹치던 문제도 함께 고쳤다
BoxWithConstraints 가 fillMaxSize() 없이 콘텐츠 크기만큼만 차지하고 있어서 contentAlignment 을 Center 로 바꿔도 재배치할 여유 공간이 없었다.
GamssBottomBar는 navigationBarsPadding()으로 내비게이션 바를 직접 피하는데, GamssTopBar는 상태바를 피하는 처리가 없어서 로고/타이틀이 상태바 안쪽까지 그려지고 있었다. GamssTopBar에 statusBarsPadding()을 추가하고, 이제 상태바를 이중으로 예약할 필요가 없어진 ArchiveScreen의 Scaffold 인셋도 함께 정리했다.
GamssTopBar뿐 아니라 ChatRoomScreen의 커스텀 탑바("대화")도 상태바 회피 처리가
없어서 같은 문제를 안고 있었다. 화면마다 따로 처리하면 빠뜨리기 쉬우므로, 탭
전환되는 화면들을 모두 감싸는 NavDisplay에서 한 번에 처리하도록 옮겼다.
GamssTopBar 자체의 처리는 되돌려 이중 여백을 피했다. 배경(GamssPaperBackground)은
Scaffold 바깥에 있어 여전히 상태바 뒤까지 이어진다.
카드 기능이 원격 설정과 무관하게 항상 켜지도록 바뀐 뒤로 useCardFeature/ requiresCardFeature/visibleIn 이 실질적으로 죽은 코드였다. MainState, MainViewModel, TopLevelDestination, MainScreen, GamssRootNavHost 에서 관련 분기와 필드를 모두 정리하고, 이제 항상 세 탭이 그대로 노출된다. ChatRoomViewModel 이 쓰는 RemoteConfigKey.UseChatEndFeature(대화 끝내기 버튼용)는 별개라 그대로 뒀다.
보관함 탭이 원격 설정과 무관하게 항상 노출되도록 바뀐 뒤로 이 주석이 더 이상 맞지 않았다. 실제 코드(bottomBar 노출 분기)는 이미 이전 커밋에서 제거됐다.
보관함 상세가 오늘 하루치가 아니라 고른 달 전체를 보여줘야 해서, 서버의 GET /api/cards/monthly(yearMonth=yyyy-MM)를 붙였다. YearMonth.toString()이 서버가 요구하는 yyyy-MM 그대로라 포맷터는 두지 않았다. 이 응답에는 카드 식별자가 없고 날짜별 대표 감정 목록만 온다. 그래서 카드 한 건의 신원을 날짜와 그날 순번(CardEntry.indexInDate)으로 잡았다. 순번은 알 수 없는 감정을 걸러낸 뒤를 기준으로 센다. 날짜별 조회(getCardsByDate)도 같은 기준으로 걸러내므로, 나중에 요약 같은 상세가 필요해지면 날짜로 다시 조회해 그 순번의 카드를 그대로 찾을 수 있다.
월 표시 박스가 오늘이 속한 달을 표시만 하고 눌러도 아무 일이 없었다. 박스를 누르면 연·월 휠 바텀시트가 올라오고, 선택하기를 눌러야 그 달로 다시 조회한다. 고른 달이 보고 있는 달과 같으면 이미 쌓인 종이를 다시 쏟지 않고 시트만 닫는다. 휠 가운데 칸 판정은 스크롤 오프셋을 어림하지 않고 layoutInfo에서 화면 중앙에 가장 가까운 칸을 찾는다. 오프셋으로 계산하면 스크롤 도중 한 칸씩 밀린다. 첫 프레임에는 아직 레이아웃이 없어 가운데를 알 수 없으므로, 그때는 지금 고른 칸을 그대로 답한다. 0번째로 떨어뜨리면 고르지도 않은 첫 칸이 선택돼 버린다. 연도는 올해로 끝나는 최근 5년만 준다. 월은 12개월을 그대로 둬서 연·월 휠이 서로를 잘라내지 않게 하고, 카드가 없는 달은 기존 빈 상태로 답한다. 시트 아래 여백은 디자인이 화면 맨 아래까지 재는 값이라 contentWindowInsets를 비우고 직접 계산한다. 다만 3버튼 내비처럼 인셋이 그 여백보다 큰 기기에서는 버튼이 가려지므로 그때는 인셋만큼 확보한다. 닫기 아이콘(X)이 디자인시스템에 없어 ic_close를 추가했다.
인셋만큼만 확보하면 인셋이 디자인 여백보다 큰 기기에서 여백이 하나도 남지 않아 선택하기 버튼이 내비바에 붙는다. 실기기(인셋 47.8dp, 3버튼 내비)에서 확인했다. 인셋 위로 최소 간격을 두어 제스처 바 기기는 디자인값 32dp 그대로, 3버튼 기기는 55.7dp 가 된다.
develop 이 같은 이름으로 다른 아이콘(원형으로 채운 지우기 버튼, GamssIcons.ClearButton) 을 추가해 add/add 충돌이 났다. 선으로만 그린 X 는 파일명을 나눠 둘 다 남긴다.
월 박스만 곧은 1dp 테두리라 앱의 손그림 톤에서 겉돌았다. 입력바가 쓰는 손그림 에셋을 그대로 가져와(fix/home-ui 의 bg_input_box 와 바이트 동일) 같은 그림이 리소스로 갈라지지 않게 했다. 셰브론은 두 가지가 어긋나 있었다. ic_right_chevron 글리프가 24 뷰포트 안에서 오른쪽에 몰려 있어(중심 16.85, 12.03) 박스 중심을 축으로 90° 돌리면 그 가로 편차 4.85dp 가 세로 어긋남으로 바뀌었다. 회전축을 글리프 중심으로 옮겨(GamssDisclosureToggle 과 같은 값) 제자리에서 돌게 했다. 또 디자인의 셰브론 프레임은 18dp 인데 드로어블 고유 크기 24dp 로 그려 33% 커 보였다. 실기기 실측으로 세로 편차 4.85dp → 0.17dp, 잉크 17.5×8.9dp → 13.0×6.5dp 가 됐다. 낙하는 조금 더 빠른 편이 좋아 중력을 1700 → 2600 으로 올렸다.
MainScreen 충돌은 develop 의 화면전환 애니메이션(#47)과 이 브랜치의 탭바 애니메이션·상태바 처리가 같은 파일을 건드려 났다. 양쪽을 모두 살리고, 삭제한 CalendarKey 엔트리는 버렸다. 보관함 상세도 탭 안쪽 상세 화면이라 다른 상세들과 같은 detailSlideTransition 을 붙였다. ArchiveDetailScreen 의 BackHandler 는 제거했다 — 시스템 뒤로가기를 먼저 가로채면 NavDisplay 의 onBack 에 닿지 않아, develop 이 새로 넣은 predictive back 미리보기와 pop 트랜지션이 이 화면에서만 빠진다. 다른 상세 화면들도 BackHandler 없이 onBack 에 맡긴다.
한 파일이 화면 조립부터 월 박스, 종이 낙하 물리 루프까지 들고 있어 390줄이었다. component/MonthSelector, component/PaperPile 로 갈라 화면 파일은 조립만 남겼다. 402dp 시안 배율 계산은 보관함 그리드와 종이 더미가 각자 복붙하고 있어 designScale 로 뺐다. 빈 상태·실패 문구, 닫기 버튼, 시트 아래 여백 계산도 이름 있는 조각으로 꺼냈다. 주석은 코드를 그대로 읽어주는 설명을 지우고, 그 코드가 왜 그렇게 생겼는지만 남겼다. 순번 규칙 설명이 CardEntry 와 CardCalendarResponse 양쪽에 있어 도메인만 남겼고, PaperPhysics 에 섞여 있던 영어 주석은 한글로 맞췄다. 하드코딩으로 남아 있던 보관함 그리드 문구와 설정 아이콘 접근성 설명을 strings.xml 로 옮겼다.
app 모듈 의존성 목록에서 충돌했다. 이 브랜치가 :feature:calendar 를 :feature:archive 로 개명했고 develop 은 새로 :feature:emotion 을 추가해, 양쪽을 모두 남겼다.
되돌릴 수 없는 삭제인데 표시만 하고 있었다. 누르면 확인을 한 번 받는다. 다이얼로그는 develop 의 GamssDialog 를 그대로 쓴다. GamssDialogAction 으로 액션만 받는 구조라 무엇을 지울지는 호출하는 화면이 정하고, Destructive/Secondary 변형이 디자인의 빨간 비우기·회색 취소와 그대로 맞는다. 삭제 API 가 아직 없어 확인은 지금 닫기만 한다. 호출부는 onClearConfirm 으로 열어 뒀다. 문구는 디자인을 그대로 옮겼는데, 감정별 화면에 있는 버튼인데도 "대화 전체"라고 말하고 있어 삭제 범위가 정해지면 문구도 같이 손봐야 한다.
하위 화면 진입 시 탭바를 AnimatedVisibility 로 접었는데(c3140d0), develop 의 화면전환 애니메이션이 들어온 뒤로는 화면 슬라이드와 겹쳐 필요하지 않다. develop 과 같은 조건부 렌더로 되돌린다. 같은 커밋에 있던 contentWindowInsets = WindowInsets(0) 은 남긴다. GamssBottomBar 가 navigationBarsPadding 을 직접 물고 있어 Scaffold 기본 인셋과 겹치던 별개 수정이다.
카드 두 장과 간격을 합쳐도 가용 폭보다 2dp 모자란데(디자인 수치도 402-96 안에 132*2+40), Arrangement.spacedBy 가 기본 start 정렬이라 남는 여분이 전부 오른쪽에 쏠렸다. 여분을 좌우로 나눠 실제로 가운데 오게 한다. 실기기 실측으로 좌우 49.3/51.4dp 에서 50.4/50.4dp 가 됐다. 세로는 그대로 둔다. 타이틀과 그리드를 묶은 그룹이 중앙에 오는 게 의도한 배치다.
develop 이 카드 레이어를 크게 손댔다(#41). 카드에 id·conversationId·emotionLabel·date 가 붙고 DELETE /api/cards/{cardId} 와 deleteCard 유스케이스가 생겼다. 이 브랜치가 얹은 월별 조회를 그 위에 합쳤다 — CardRepository 는 getCardsByDate/getCardsByMonth/createCard/ deleteCard 넷을 갖고, CardService 도 넷을 그대로 노출한다. CardResponse 와 GetCardsByDateUseCase 는 develop 쪽을 그대로 쓴다. 캘린더 화면은 보관함이 대체하므로 삭제를 유지했다. develop 이 그 화면에 붙인 카드 상세 팝업 중 CardDetailDialog 는 남겨 두고(R 참조만 이 모듈 네임스페이스로 고침), 캘린더 전용이던 kizitonwose 의존성은 뺐다. 지금은 아무 화면도 이 팝업을 부르지 않는다 — 보관함 종이 탭에 연결하는 건 별도로 한다. 테스트 더블은 네 메서드를 모두 구현하도록 맞췄다. 어느 테스트에서 쓰지 않는 메서드인지는 error() 메시지로 남긴다. app 모듈의 onboarding 의존성 중복도 정리했다.
월별 응답에는 카드 식별자가 없어 종이는 날짜와 그날 순번만 들고 있다. 눌린 종이의 날짜로 날짜별 조회를 한 번 더 해서 그 순번의 카드를 집는다 — 여기서 요약·대사와 id 가 손에 들어오고, 버리기·대화보기가 그 id 로 이어진다. 상세 팝업은 develop 이 캘린더에 만든 CardDetailDialog 를 그대로 부른다. 버리기는 DeleteCardUseCase, 대화보기는 OpenChatRoom 사이드이펙트로 MainScreen 이 채팅방을 열고, 공유는 develop 의 CalendarScreen 에 있던 Intent 흐름을 옮겼다. 버린 뒤에는 그 달을 다시 받아 온다. 목록에서만 빼면 같은 날짜 뒤 순번이 한 칸씩 당겨져 남은 종이가 다른 카드를 가리킨다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CardRepository를CardQueryRepository(조회) /CardWriteRepository(쓰기)로 분리하고, 날짜별 카드 조회 API(getCardsByDate) 추가Test plan
보관함탭 → 카드가 있는 감정 쓰레기통 진입 시 카드가 위에서 낙하해 자연스럽게 쌓이는지 확인./gradlew test testDebugUnitTest통과 확인