From 1aef4b1d89c6e28791affffba194e95354b12210 Mon Sep 17 00:00:00 2001 From: klaus Date: Tue, 30 Jun 2026 15:46:36 +0900 Subject: [PATCH] =?UTF-8?q?docs(home):=20title=20bar=20=EB=A9=94=EB=89=B4?= =?UTF-8?q?=20=EC=95=A1=EC=85=98=20=EA=B3=84=ED=9A=8D=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan-task.md | 196 ++++++++++++++++++ .../prd.md | 103 +++++++++ 2 files changed, 299 insertions(+) create mode 100644 docs/20260630_메인_홈_title_bar_우측_메뉴_액션/plan-task.md create mode 100644 docs/20260630_메인_홈_title_bar_우측_메뉴_액션/prd.md diff --git a/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/plan-task.md b/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/plan-task.md new file mode 100644 index 00000000..2a21077e --- /dev/null +++ b/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/plan-task.md @@ -0,0 +1,196 @@ +# 메인 홈 title bar 우측 메뉴 액션 구현 계획/TASK + +> **For agentic workers:** REQUIRED SUB-SKILL: 구현 시 `superpowers:subagent-driven-development` 또는 `superpowers:executing-plans`를 사용해 task 단위로 진행한다. 각 단계는 체크박스(`- [ ]`)로 추적하고, 완료 즉시 `- [x]`로 갱신한다. 구현 범위 변경이 생기면 이 문서를 먼저 수정한 뒤 코드에 반영한다. + +**Goal:** v2 메인 홈 title bar 우측 `cash`, `search`, `bell` 아이콘 터치 시 기존 충전, 검색, 알림 리스트 페이지로 이동한다. + +**Architecture:** `view_title_bar_home.xml`과 `fragment_v2_main_home.xml`의 기존 UI는 유지하고, `HomeMainFragment`에서 title bar action click listener만 연결한다. 목적지 화면은 기존 레거시 Activity를 명시적 `Intent`로 호출하며, 비로그인 처리는 기존 `ensureMainV2NavigationAllowed`를 재사용한다. + +**Tech Stack:** Kotlin, Android XML Views, ViewBinding, Fragment, Android explicit Intent, JUnit4 source-level test. + +--- + +## 전제와 성공 기준 +- PRD: `docs/20260630_메인_홈_title_bar_우측_메뉴_액션/prd.md` +- 구현 대상: + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` +- 확인 대상: + - `app/src/main/res/layout/view_title_bar_home.xml` + - `app/src/main/res/layout/fragment_v2_main_home.xml` + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuard.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt` +- 목적지: + - cash: `CanChargeActivity` + - search: `SearchActivity` + - bell: `PushNotificationListActivity` +- 성공 기준: + - `HomeMainFragment`가 `setupTitleBarActions()` 또는 동등한 최소 메서드에서 세 아이콘 click listener를 연결한다. + - 세 click listener는 모두 `ensureMainV2NavigationAllowed`를 거친다. + - 목적지 기존 Activity 파일은 수정하지 않는다. + - 레이아웃 XML과 아이콘 리소스는 변경하지 않는다. +- 구현 완료 후 최소 다음 명령을 실행한다. + - `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainTitleBarActionSourceTest"` + - `./gradlew :app:compileDebugKotlin` + - `./gradlew :app:ktlintCheck` + - `git diff --check` + +--- + +## 파일 구조 +- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` + - title bar action click listener를 추가한다. + - `CanChargeActivity`, `SearchActivity`, `PushNotificationListActivity` import를 추가한다. +- Create: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainTitleBarActionSourceTest.kt` + - source-level로 세 아이콘 routing 계약을 검증한다. +- No Modify: + - `app/src/main/res/layout/view_title_bar_home.xml` + - `app/src/main/res/layout/fragment_v2_main_home.xml` + - `app/src/main/java/kr/co/vividnext/sodalive/mypage/can/charge/CanChargeActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/search/SearchActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/pushnotification/PushNotificationListActivity.kt` + +--- + +### Phase 1: 수정 지점과 기존 목적지 확인 + +- [x] **Task 1.1: title bar 아이콘 선언 위치 확인** + - 확인: + - `app/src/main/res/layout/view_title_bar_home.xml` + - `app/src/main/res/layout/fragment_v2_main_home.xml` + - 결과: + - `view_title_bar_home.xml`에 `iv_title_bar_cash`, `iv_title_bar_search`, `iv_title_bar_bell`이 선언되어 있다. + - `fragment_v2_main_home.xml`이 해당 title bar를 `view_home_title_bar`로 include한다. + - 검증 기록: + - 2026-06-30: `rg -n "view_home_title_bar|iv_title_bar_cash|iv_title_bar_search|iv_title_bar_bell" app/src/main/java app/src/main/res/layout -S`로 세 아이콘 선언 위치와 코드 미연결 상태를 확인했다. + +- [x] **Task 1.2: 기존 목적지 Activity 확인** + - 확인: + - `app/src/main/java/kr/co/vividnext/sodalive/mypage/can/charge/CanChargeActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/search/SearchActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/pushnotification/PushNotificationListActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt` + - 결과: + - 레거시 `HomeFragment`에서 search, charge, push notification 이동 사례를 확인했다. + - 목적지 Activity는 별도 factory 없이 `Intent(context, Activity::class.java)` 형태로 호출 가능하다. + - 검증 기록: + - 2026-06-30: `HomeFragment.setupView()`의 short icon click listener와 각 Activity의 존재를 정적으로 확인했다. + +--- + +### Phase 2: source-level 회귀 테스트 추가 + +- [x] **Task 2.1: title bar action source test 작성** + - 생성: + - `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainTitleBarActionSourceTest.kt` + - 작업: + - `HomeMainFragment.kt` source text를 읽어 다음 계약을 검증한다. + - `viewHomeTitleBar.ivTitleBarCash.setOnClickListener` + - `viewHomeTitleBar.ivTitleBarSearch.setOnClickListener` + - `viewHomeTitleBar.ivTitleBarBell.setOnClickListener` + - 세 listener 내부 또는 공통 helper에서 `ensureMainV2NavigationAllowed` 사용 + - `CanChargeActivity::class.java` + - `SearchActivity::class.java` + - `PushNotificationListActivity::class.java` + - 테스트 예시: + ```kotlin + package kr.co.vividnext.sodalive.v2.main.home + + import org.junit.Assert.assertTrue + import org.junit.Test + import java.io.File + + class HomeMainTitleBarActionSourceTest { + private val source = File( + "src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt" + ).readText() + + @Test + fun `홈 title bar 우측 아이콘은 기존 목적지로 이동한다`() { + assertTrue(source.contains("viewHomeTitleBar.ivTitleBarCash.setOnClickListener")) + assertTrue(source.contains("viewHomeTitleBar.ivTitleBarSearch.setOnClickListener")) + assertTrue(source.contains("viewHomeTitleBar.ivTitleBarBell.setOnClickListener")) + assertTrue(source.contains("ensureMainV2NavigationAllowed")) + assertTrue(source.contains("CanChargeActivity::class.java")) + assertTrue(source.contains("SearchActivity::class.java")) + assertTrue(source.contains("PushNotificationListActivity::class.java")) + } + } + ``` + - 검증: + - Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainTitleBarActionSourceTest"` + - Expected: 구현 전에는 `AssertionError`로 실패한다. + - 검증 기록: + - 2026-06-30: `HomeMainTitleBarActionSourceTest`를 추가한 뒤 구현 전 테스트를 실행해 `HomeMainTitleBarActionSourceTest.kt:15`의 listener 문자열 누락 `AssertionError`로 RED를 확인했다. + +--- + +### Phase 3: title bar action 최소 구현 + +- [x] **Task 3.1: `HomeMainFragment`에 title bar action setup 추가** + - 수정: + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` + - 작업: + - `onViewCreated()`에서 기존 tab setup 흐름을 깨지 않는 위치에 `setupTitleBarActions()`를 호출한다. + - `setupTitleBarActions()`에서 세 icon click listener를 연결한다. + - 구현 예시: + ```kotlin + private fun setupTitleBarActions() { + binding.viewHomeTitleBar.ivTitleBarCash.setOnClickListener { + openWithLoginGuard(CanChargeActivity::class.java) + } + binding.viewHomeTitleBar.ivTitleBarSearch.setOnClickListener { + openWithLoginGuard(SearchActivity::class.java) + } + binding.viewHomeTitleBar.ivTitleBarBell.setOnClickListener { + openWithLoginGuard(PushNotificationListActivity::class.java) + } + } + + private fun openWithLoginGuard(activityClass: Class<*>) { + ensureMainV2NavigationAllowed { + startActivity(Intent(requireContext(), activityClass)) + } + } + ``` + - 필요한 import: + ```kotlin + import kr.co.vividnext.sodalive.home.pushnotification.PushNotificationListActivity + import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity + import kr.co.vividnext.sodalive.search.SearchActivity + ``` + - 검증: + - Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainTitleBarActionSourceTest"` + - Expected: PASS + - 검증 기록: + - 2026-06-30: `HomeMainFragment`에 `setupTitleBarActions()`와 `openWithLoginGuard()`를 추가해 cash/search/bell listener가 각각 `CanChargeActivity`, `SearchActivity`, `PushNotificationListActivity`로 이동하도록 구현했다. 구현 후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainTitleBarActionSourceTest"` PASS, `./gradlew :app:compileDebugKotlin` PASS를 확인했다. + +--- + +### Phase 4: 빌드/린트와 수동 확인 + +- [x] **Task 4.1: Kotlin compile 및 ktlint 확인** + - 실행: + - `./gradlew :app:compileDebugKotlin` + - `./gradlew :app:ktlintCheck` + - `git diff --check` + - 기대 결과: + - 모두 PASS한다. + - 검증 기록: + - 2026-06-30: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.HomeMainTitleBarActionSourceTest"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:ktlintCheck`, `git diff --check` PASS를 확인했다. Gradle deprecation warning과 Agora namespace warning은 기존 빌드 경고로 출력됐으나 실패는 없었다. + +- [ ] **Task 4.2: 수동 화면 확인** + - 확인: + - v2 메인 홈 진입 후 title bar 우측 cash/search/bell 아이콘이 기존과 동일하게 보인다. + - 로그인 상태에서 cash 터치 시 충전 페이지로 이동한다. + - 로그인 상태에서 search 터치 시 검색 페이지로 이동한다. + - 로그인 상태에서 bell 터치 시 알림 리스트 페이지로 이동한다. + - 비로그인 상태에서 각 아이콘 터치 시 기존 v2 login guard 흐름으로 이동한다. + - 검증 기록: + - 구현 후 실행 결과를 이 항목 아래에 누적한다. + +--- + +## Verification Log +- 2026-06-30: 문서 작성 단계에서 코드 구현은 수행하지 않았다. `view_title_bar_home.xml`, `fragment_v2_main_home.xml`, `HomeMainFragment.kt`, 레거시 `HomeFragment.kt`, 목적지 Activity 세 개를 정적으로 확인해 구현 위치와 범위를 확정했다. +- 2026-06-30: Phase 2, 3 구현 후 `./gradlew :app:ktlintCheck` PASS를 확인했다. 실행 중 `.editorconfig`의 기존 `disabled_rules` deprecation warning이 출력됐으나 lint 실패는 없었다. +- 2026-06-30: Phase 2, 3 구현 후 `git diff --check` PASS를 확인했다. diff --git a/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/prd.md b/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/prd.md new file mode 100644 index 00000000..dd883c68 --- /dev/null +++ b/docs/20260630_메인_홈_title_bar_우측_메뉴_액션/prd.md @@ -0,0 +1,103 @@ +# PRD: 메인 홈 title bar 우측 메뉴 액션 + +## 1. Overview +v2 메인 홈 title bar 우측의 `cash`, `search`, `bell` 아이콘 터치 시 기존 충전, 검색, 알림 리스트 페이지로 이동하도록 액션을 연결한다. + +--- + +## 2. Problem +- `fragment_v2_main_home.xml`은 `view_title_bar_home.xml`을 include하고, 해당 title bar에는 `ic_bar_cash`, `ic_bar_search`, `ic_bar_bell` 아이콘이 이미 표시된다. +- `HomeMainFragment`에는 현재 이 세 아이콘의 클릭 리스너가 연결되어 있지 않다. +- 레거시 `HomeFragment`에는 동일 목적의 short icon 액션이 이미 있으며, v2 홈 title bar도 같은 목적지로 이동해야 한다. + +--- + +## 3. Goals +- v2 메인 홈 title bar 우측 아이콘 터치 액션을 추가한다. +- `ic_bar_cash` 터치 시 기존 `CanChargeActivity`로 이동한다. +- `ic_bar_search` 터치 시 기존 `SearchActivity`로 이동한다. +- `ic_bar_bell` 터치 시 기존 `PushNotificationListActivity`로 이동한다. +- 목적지 기존 Activity는 수정하지 않고 호출만 한다. +- 로그인 필요 여부는 기존 v2 navigation guard 패턴을 따른다. + +--- + +## 4. Non-Goals +- 이번 PRD 작성 단계에서는 코드, 리소스, 레이아웃 파일을 구현하지 않는다. +- title bar 디자인, 아이콘 리소스, 간격, 크기, 노출 조건을 변경하지 않는다. +- `CanChargeActivity`, `SearchActivity`, `PushNotificationListActivity` 내부 동작을 수정하지 않는다. +- 신규 충전, 검색, 알림 화면을 만들지 않는다. +- 레거시 `HomeFragment`의 short icon 액션은 변경하지 않는다. +- 콘텐츠 탭의 `ic_bar_storage` 등 이번 요구에 없는 아이콘 액션은 범위에 포함하지 않는다. + +--- + +## 5. Target Users +- v2 메인 홈에서 상단 아이콘으로 충전, 검색, 알림 리스트에 빠르게 진입하려는 사용자. +- 기존 화면을 재사용하면서 v2 홈 title bar 동작을 연결해야 하는 Android 개발자. + +--- + +## 6. User Stories +- 사용자는 홈 상단 cash 아이콘을 누르면 충전 페이지로 이동하고 싶다. +- 사용자는 홈 상단 search 아이콘을 누르면 검색 페이지로 이동하고 싶다. +- 사용자는 홈 상단 bell 아이콘을 누르면 알림 리스트 페이지로 이동하고 싶다. + +--- + +## 7. Core Features + +### title bar 우측 메뉴 routing + +#### Requirements +- 구현 대상 title bar: + - `app/src/main/res/layout/view_title_bar_home.xml` + - include 위치: `app/src/main/res/layout/fragment_v2_main_home.xml` + - 연결 Fragment: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` +- 목적지 Activity: + - `ic_bar_cash` / `iv_title_bar_cash` -> `kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity` + - `ic_bar_search` / `iv_title_bar_search` -> `kr.co.vividnext.sodalive.search.SearchActivity` + - `ic_bar_bell` / `iv_title_bar_bell` -> `kr.co.vividnext.sodalive.home.pushnotification.PushNotificationListActivity` +- `HomeMainFragment.onViewCreated()` 흐름에서 별도 `setupTitleBarActions()`를 호출해 클릭 리스너를 연결한다. +- 각 클릭은 `ensureMainV2NavigationAllowed { ... }` 안에서 `startActivity(Intent(requireContext(), TargetActivity::class.java))`를 호출한다. +- 새 wrapper, adapter, ViewModel은 만들지 않는다. + +#### Edge Cases +- 비로그인 상태에서 아이콘을 터치하면 기존 `ensureMainV2NavigationAllowed` 정책에 따라 로그인 화면으로 유도한다. +- Fragment가 view lifecycle 밖에 있을 때 클릭 리스너가 실행되지 않도록 기존 ViewBinding 생명주기 안에서만 연결한다. +- Activity launch 실패에 대한 별도 처리나 Toast는 추가하지 않는다. 기존 명시적 Activity intent 경로만 사용한다. + +--- + +## 8. UX / UI Expectations +- 화면에 이미 표시되는 title bar 아이콘의 디자인은 유지한다. +- 터치 후 목적지 화면 전환은 기존 Android Activity 전환 방식과 동일하게 동작한다. +- 아이콘 순서와 의미는 기존 title bar XML과 동일하게 cash, search, bell 순서를 유지한다. + +--- + +## 9. Technical Constraints +- Android XML View, ViewBinding, Fragment 기반 기존 구조를 유지한다. +- 신규 구현은 `kr.co.vividnext.sodalive.v2.main.home.HomeMainFragment`에 한정한다. +- 기존 레거시 화면은 직접 수정하지 않는다. +- 로그인 guard는 `kr.co.vividnext.sodalive.v2.main.ensureMainV2NavigationAllowed`를 재사용한다. +- 관련 근거 파일: + - `app/src/main/res/layout/view_title_bar_home.xml` + - `app/src/main/res/layout/fragment_v2_main_home.xml` + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2LoginGuard.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/mypage/can/charge/CanChargeActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/search/SearchActivity.kt` + - `app/src/main/java/kr/co/vividnext/sodalive/home/pushnotification/PushNotificationListActivity.kt` + +--- + +## 10. Metrics +- 정량 지표는 이번 범위에 추가하지 않는다. +- 검증 기준은 세 아이콘 클릭 리스너가 코드에 존재하고 각 목적지 Activity로 routing되는지 여부다. + +--- + +## 11. Open Questions +- 없음. 이번 문서는 세 아이콘이 모두 존재하는 v2 메인 홈 title bar를 구현 대상으로 확정한다.