Skip to content

[refactor] #196 PhotoDetail 메모 UI를 HorizontalPager 밖으로 분리#197

Merged
ikseong00 merged 6 commits into
developfrom
refactor/#196-photo-detail-memo-outside-pager
Apr 20, 2026
Merged

[refactor] #196 PhotoDetail 메모 UI를 HorizontalPager 밖으로 분리#197
ikseong00 merged 6 commits into
developfrom
refactor/#196-photo-detail-memo-outside-pager

Conversation

@ikseong00
Copy link
Copy Markdown
Contributor

@ikseong00 ikseong00 commented Apr 19, 2026

🔗 관련 이슈

📙 작업 설명

  • 사진별 memoModes: Map<Long, MemoMode> 를 전역 단일 memoMode: MemoMode 로 단순화
    • currentMemoMode / memoModeOf(photoId) 헬퍼 제거
    • ViewModel 의 메모 인텐트 처리 단순화 (toImmutableMap 체인 제거)
  • 메모 UI(MemoTextField) + dim 오버레이를 HorizontalPager 바깥으로 이동
    • PhotoDetailPagerArea 컴포저블 추출: pager + dim + 메모 박스를 감싸는 Box
    • dim/메모 박스가 화면 전역 단일 인스턴스로 존재
  • PhotoDetailImageItem 시그니처 축소 (imageUrl, isScrollInProgress, isTapEnabled, onClickLeft, onClickRight 만 유지)
  • 페이지 전환 시: 메모 모드(Closed/Preview/Expanded/Editing)는 유지, 내용만 현재 사진의 메모로 갱신
    • MemoTextField 내부 LaunchedEffect(memo, memoMode) 가 내부 TextFieldState 를 새 memo 로 재동기화
    • Editing/Expanded 에서의 pager 스와이프 차단 동작은 기존 그대로 유지

🧪 테스트 내역 (선택)

  • Preview 상태로 스와이프 시 모드 유지 + 내용만 교체 확인
  • Expanded → dim 탭/메모 접기 → Preview 복귀 확인
  • Editing 진입 시 ActionBar 숨김, 완료/취소 시 복귀 확인
  • Editing 중 스와이프 차단 확인
  • 메모 저장 성공/실패 플로우 확인
  • S23 실기기 설치 후 QA

📸 스크린샷 또는 시연 영상 (선택)

Before After
KakaoTalk_Video_2026-04-20-00-01-34.mp4
123.mp4

💬 추가 설명 or 리뷰 포인트 (선택)

  • 커밋 2개로 분리:
    1. 사진별 memo 모드 맵을 전역 단일 memoMode 로 단순화 (state/ViewModel/Screen 호출부 마이그레이션)
    2. 메모 UI/Dim 을 HorizontalPager 밖으로 분리 (UI 구조 변경 + PhotoDetailImageItem 시그니처 단순화)
  • dim 의 탭 핸들러는 기존 noRippleClickableSingle 유지. Expanded/Editing 에서는 pager 스와이프가 차단되어 있어 드래그 전파 이슈가 없음.
  • MemoTextField 본체는 수정하지 않고 재사용 (내부 TextFieldState 동기화 로직이 그대로 활용됨)

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 사진 페이저 스크롤 시작 이벤트 처리 추가
  • 리팩토링

    • 메모 모드 관리를 per-photo 맵에서 단일 상태로 단순화
    • 페이저와 메모 오버레이를 분리·재구성하여 메모 UI를 페이저 레이어 위 오버레이로 이동
    • 이미지 항목에서 메모 관련 입력/콜백 제거 및 책임 축소
    • 액션바에 메모 보유 여부(hasMemo) 반영하여 아이콘 상태 변경
  • 동작 개선

    • 메모 활성 시 페이저 스크롤 및 탭 동작 제어, 편집 전환 및 키보드 인셋 처리 개선

- PhotoDetailState의 memoModes: Map<Long, MemoMode> 제거
- 단일 memoMode: MemoMode 필드로 대체
- currentMemoMode / memoModeOf 헬퍼 제거
- ViewModel의 메모 인텐트 처리 단순화
- 페이지 전환 시 memo 내용만 갱신하고 모드는 유지
- PhotoDetailScreen에서 Pager/Dim/MemoTextField를 감싸는 PhotoDetailPagerArea 컴포저블 추출
- dim 오버레이와 MemoTextField를 각 페이지 안이 아닌 pager 밖 공용 Box에 배치
- PhotoDetailImageItem 시그니처 단순화 (memo/MemoMode/액션 핸들러 제거, 이미지 + 좌우 탭만 유지)
- 메모 관련 UI가 화면 전역 단일 인스턴스로 동작하여 페이지 전환 시 모드는 유지되고 내용만 갱신
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 19, 2026

Warning

Rate limit exceeded

@ikseong00 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ddd9b8a8-a222-41cf-bdbb-67c2397749d2

📥 Commits

Reviewing files that changed from the base of the PR and between 504aac1 and 34a7437.

📒 Files selected for processing (2)
  • core/designsystem/src/main/res/drawable/icon_memo_filled.xml
  • core/designsystem/src/main/res/drawable/icon_memo_stroked.xml

Walkthrough

PhotoDetail의 메모 상태를 사진별 맵에서 전역 단일 memoMode: MemoMode로 단순화하고, 메모 UI(스크림/MemoTextField)를 HorizontalPager 바깥 오버레이로 이동했습니다. 페이저 스크롤 시작을 감지하는 PhotoDetailIntent.PageScrollStarted 인텐트가 추가되었습니다.

Changes

Cohort / File(s) Summary
상태 계약 변경
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailContract.kt
memoModes: ImmutableMap<Long, MemoMode> 제거 및 memoMode: MemoMode = MemoMode.Closed 단일 필드 추가. currentMemoMode/memoModeOf() 파생 접근자 제거.
화면/컴포저블 재구성
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt
페이저 부분을 PhotoDetailPagerArea로 추출. LaunchedEffect(pagerState)로 스크롤 시작 감지하여 PhotoDetailIntent.PageScrollStarted 디스패치 추가. 메모 UI(스크림, MemoTextField)를 페이저 외부 오버레이로 이동하고, 페이저 스크롤·탭 허용 로직을 전역 uiState.memoMode 기준으로 제어. IME/인셋 및 애니메이션 처리 변경.
뷰모델 메모 처리 단순화
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailViewModel.kt
메모 모드 관리를 per-photo 맵 갱신에서 단일 memoMode 할당으로 전환. 메모 관련 인텐트들이 map 조작 대신 memoMode/memo 직접 설정으로 변경되고, PageScrollStarted 처리로 스크롤 시 memoMode = Closed 설정 추가.
이미지 아이템 시그니처 단순화
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/component/PhotoDetailImageItem.kt
PhotoDetailImageItem에서 모든 메모 관련 파라미터와 콜백 제거(메모 텍스트/모드/액션바 인셋 등 삭제). 이미지 줌·탭·좌/우 클릭 처리만 유지; 메모 레이어 제거.
액션바 변경
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/component/PhotoDetailActionBar.kt
hasMemo: Boolean 매개변수 추가. 메모 아이콘을 hasMemo에 따라 icon_memo_filled/icon_memo_stroked로 분기하여 렌더링. 프리뷰 업데이트 포함.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Screen as PhotoDetailScreen
    participant Pager as HorizontalPager
    participant ViewModel as PhotoDetailViewModel
    participant State as PhotoDetailState

    User->>Screen: 메모 아이콘 클릭
    Screen->>ViewModel: ClickMemoIcon()
    ViewModel->>State: state.copy(memoMode = Preview/Expanded/Editing)
    State-->>Screen: uiState.memoMode 업데이트
    Screen->>Screen: 페이저 외부 오버레이(스크림/에디터) 렌더

    User->>Screen: 메모 편집 진입
    Screen->>ViewModel: ClickMemoText() / ClickMemoMore()
    ViewModel->>State: state.copy(memoMode = Editing)
    State-->>Pager: userScrollEnabled = false

    User->>Pager: 페이지 스와이프 시도
    Pager->>Screen: isScrollInProgress = true
    Screen->>ViewModel: PageScrollStarted()
    ViewModel->>State: state.copy(memoMode = Closed)
    State-->>Screen: uiState.memoMode = Closed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 깡충, 깡충 메모가 밖에 나왔네
페이지는 스윽, 메모는 한 곳에 모였네 ✨
편집할 땐 스와이프 멈추고
보기엔 가볍게, 닫히면 사뿐히
리팩토링 축하해요!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목 '[refactor] #196 PhotoDetail 메모 UI를 HorizontalPager 밖으로 분리'는 변경사항의 핵심을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명은 템플릿의 주요 섹션을 모두 포함하며, 작업 설명, 테스트 내역, 스크린샷, 추가 설명 등이 완전하게 작성되었습니다.
Linked Issues check ✅ Passed 모든 연결된 이슈 #196의 목표들이 구현되었습니다: memoMode 단순화, UI 분리, 시그니처 축소, 스와이프 제어, QA 완료.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #196의 범위 내에 있으며, 메모 UI 분리 및 상태 단순화라는 명확한 목표에 부합합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#196-photo-detail-memo-outside-pager

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt (1)

232-237: Dim 오버레이 색상을 디자인 시스템 토큰으로 추출 권장 (선택)

Color(0x80202227) 하드코딩된 매직 ARGB를 NekiTheme.colorScheme의 scrim/dim 토큰으로 빼두면 다크모드 대응과 다른 오버레이와의 일관성 유지가 쉬워집니다. 프로젝트에 해당 토큰이 아직 없다면 이번 PR 범위 밖으로 미뤄도 무방합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`
around lines 232 - 237, 현재 PhotoDetailScreen의 Box에서 하드코딩된 오버레이 색상
Color(0x80202227)을 직접 사용하고 있어 다크모드/일관성 문제가 생길 수 있으니, Box(…
.background(Color(0x80202227)))를 NekiTheme.colorScheme의 scrim/dim 같은 디자인 토큰으로
교체하도록 변경하세요: 정의된 토큰이 있다면 해당 토큰(예: NekiTheme.colorScheme.scrim 또는 .dim)을 사용하도록
background를 바꾸고, 토큰이 없으면 디자인팀과 협의해 이름을 정한 후 토큰을 추가해 적용하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`:
- Around line 232-237: 현재 PhotoDetailScreen의 Box에서 하드코딩된 오버레이 색상
Color(0x80202227)을 직접 사용하고 있어 다크모드/일관성 문제가 생길 수 있으니, Box(…
.background(Color(0x80202227)))를 NekiTheme.colorScheme의 scrim/dim 같은 디자인 토큰으로
교체하도록 변경하세요: 정의된 토큰이 있다면 해당 토큰(예: NekiTheme.colorScheme.scrim 또는 .dim)을 사용하도록
background를 바꾸고, 토큰이 없으면 디자인팀과 협의해 이름을 정한 후 토큰을 추가해 적용하세요.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 56515d0f-99f0-49d5-a721-40ec82197050

📥 Commits

Reviewing files that changed from the base of the PR and between 7079540 and 619a299.

📒 Files selected for processing (4)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailContract.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailViewModel.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/component/PhotoDetailImageItem.kt
💤 Files with no reviewable changes (1)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/component/PhotoDetailImageItem.kt

Copy link
Copy Markdown
Member

@Ojongseok Ojongseok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~! Before/After로 비교해보니 Before가 더 자연스러운 것 같은 생각이 들지만 요구사항이 그러하다면 이렇게 진행하시죠 😅

- PhotoDetailIntent.PageScrollStarted 인텐트 추가
- PhotoDetailRoute에서 pagerState.isScrollInProgress 관찰 LaunchedEffect 추가
- 스와이프가 시작되는 순간 memoMode를 Closed로 전환 (settle까지 기다리지 않음)
- 다음 사진의 메모를 보려면 메모 아이콘을 다시 탭해야 함
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt (1)

79-91: 두 LaunchedEffect를 하나로 병합 고려(선택).

pagerState를 key로 하는 LaunchedEffect가 두 개 있습니다. 동일한 key이므로 하나의 LaunchedEffect(pagerState) 내부에서 두 snapshotFlowlaunch { ... }로 나눠 수집해도 동일하게 동작하며, 관련 로직을 한 곳에서 파악할 수 있습니다. 필수는 아닙니다.

♻️ 예시 리팩터
-    LaunchedEffect(pagerState) {
-        snapshotFlow { pagerState.settledPage }.collect { page ->
-            viewModel.store.onIntent(PhotoDetailIntent.PageChanged(page))
-        }
-    }
-
-    LaunchedEffect(pagerState) {
-        snapshotFlow { pagerState.isScrollInProgress }
-            .filter { it }
-            .collect {
-                viewModel.store.onIntent(PhotoDetailIntent.PageScrollStarted)
-            }
-    }
+    LaunchedEffect(pagerState) {
+        launch {
+            snapshotFlow { pagerState.settledPage }.collect { page ->
+                viewModel.store.onIntent(PhotoDetailIntent.PageChanged(page))
+            }
+        }
+        launch {
+            snapshotFlow { pagerState.isScrollInProgress }
+                .filter { it }
+                .collect { viewModel.store.onIntent(PhotoDetailIntent.PageScrollStarted) }
+        }
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`
around lines 79 - 91, There are two LaunchedEffect(pagerState) blocks collecting
snapshotFlow { pagerState.settledPage } and snapshotFlow {
pagerState.isScrollInProgress } separately; merge them by using a single
LaunchedEffect(pagerState) and inside it launch separate coroutines to collect
each snapshotFlow so both handlers run concurrently: keep using snapshotFlow for
settledPage to call
viewModel.store.onIntent(PhotoDetailIntent.PageChanged(page)) and for
isScrollInProgress to filter true and call
viewModel.store.onIntent(PhotoDetailIntent.PageScrollStarted), ensuring you
reference pagerState, settledPage, isScrollInProgress, and the
viewModel.store.onIntent/PhotoDetailIntent symbols unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`:
- Around line 79-91: There are two LaunchedEffect(pagerState) blocks collecting
snapshotFlow { pagerState.settledPage } and snapshotFlow {
pagerState.isScrollInProgress } separately; merge them by using a single
LaunchedEffect(pagerState) and inside it launch separate coroutines to collect
each snapshotFlow so both handlers run concurrently: keep using snapshotFlow for
settledPage to call
viewModel.store.onIntent(PhotoDetailIntent.PageChanged(page)) and for
isScrollInProgress to filter true and call
viewModel.store.onIntent(PhotoDetailIntent.PageScrollStarted), ensuring you
reference pagerState, settledPage, isScrollInProgress, and the
viewModel.store.onIntent/PhotoDetailIntent symbols unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8badb4d9-9959-4e3b-8949-5e28d6f99a7f

📥 Commits

Reviewing files that changed from the base of the PR and between 619a299 and afb97a7.

📒 Files selected for processing (3)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailContract.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailViewModel.kt

- PhotoDetailPagerArea의 HorizontalPager에 Editing 시 bottom padding 추가
- ActionBar가 숨겨질 때 pager 영역이 그만큼 확장되어 이미지가 커 보이던 문제 해결
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`:
- Around line 215-225: The pager swipe blocking incorrectly uses a combined
flag; replace the combined isMemoActive logic with a dedicated isMemoEditing
flag (e.g., val isMemoEditing = uiState.memoMode == MemoMode.Editing) and use
that for pager interaction: set userScrollEnabled = !isMemoEditing on the
HorizontalPager (pagerState) so only Editing blocks swipes while
Preview/Expanded allow them; keep the dim visibility/clickable behavior separate
(introduce a separate isDimVisible or isMemoExpanded flag tied to
MemoMode.Expanded for the full-screen clickable dim and use that in the
clickable modifier) so dim rendering does not implicitly block pager drag.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 06acd76a-2881-49f3-90f4-67de8032f8cc

📥 Commits

Reviewing files that changed from the base of the PR and between afb97a7 and 612b85a.

📒 Files selected for processing (1)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt

- PhotoDetailActionBar에서 참조하는 icon_memo_filled, icon_memo_stroked 드로어블 커밋 누락 수정
- CI 빌드 실패 해결
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt (1)

216-250: ⚠️ Potential issue | 🟠 Major

Expanded에서도 pager 스와이프/탭이 차단됩니다 — 이슈 #196 요구사항과 불일치.

Line 216–217에서 ExpandedEditing이 여전히 isMemoActive 하나로 묶여 있고, 그 플래그가 Line 226의 userScrollEnabled, Line 234의 isTapEnabled에 그대로 사용되고 있어서 Expanded 상태에서도 스와이프/탭이 막힙니다. 추가로 Line 245–250의 전체화면 dim BoxfillMaxSize() + noRippleClickableSingle로 Expanded에서도 포인터 이벤트를 가로채기 때문에, userScrollEnabled를 Editing 전용으로 풀어도 드래그가 dim에 먹혀 pager로 전달되지 않을 수 있습니다.

Linked issue #196 목표("Editing에서만 pager 스와이프 차단, Preview/Expanded는 허용")에 맞추려면 "dim 표시 여부"와 "pager interaction 차단 여부"를 별도 플래그로 분리해 주세요.

🛠 참고 수정안
-    val isMemoActive = uiState.memoMode == MemoMode.Expanded ||
-        uiState.memoMode == MemoMode.Editing
+    val isMemoDimVisible = uiState.memoMode == MemoMode.Expanded ||
+        uiState.memoMode == MemoMode.Editing
+    val isPagerInteractionBlocked = uiState.memoMode == MemoMode.Editing
@@
-            userScrollEnabled = !isMemoActive,
+            userScrollEnabled = !isPagerInteractionBlocked,
@@
-                isTapEnabled = !isMemoActive,
+                isTapEnabled = !isPagerInteractionBlocked,
@@
-        AnimatedVisibility(
-            visible = isMemoActive,
+        AnimatedVisibility(
+            visible = isMemoDimVisible,
             enter = fadeIn(),
             exit = fadeOut(),
         ) {
             Box(
                 modifier = Modifier
                     .fillMaxSize()
                     .background(Color(0x80202227))
-                    .noRippleClickableSingle { onIntent(PhotoDetailIntent.ClickMemoFold) },
+                    .then(
+                        if (isPagerInteractionBlocked) {
+                            Modifier.noRippleClickableSingle {
+                                onIntent(PhotoDetailIntent.ClickMemoFold)
+                            }
+                        } else {
+                            Modifier
+                        },
+                    ),
             )
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`
around lines 216 - 250, Separate the combined isMemoActive into two booleans:
one for showing the dim (e.g., showDim = uiState.memoMode == MemoMode.Expanded
|| uiState.memoMode == MemoMode.Editing) and one for blocking interactions
(e.g., blockInteractions = uiState.memoMode == MemoMode.Editing); then use
blockInteractions for pager/user interaction flags (set HorizontalPager
userScrollEnabled = !blockInteractions and PhotoDetailImageItem isTapEnabled =
!blockInteractions) and use showDim to control AnimatedVisibility, but apply
noRippleClickableSingle (the ClickMemoFold handler) only when blockInteractions
is true so the dim in Expanded no longer intercepts pointer events; update
references to uiState.memoMode, MemoMode.Expanded, MemoMode.Editing, pagerState,
PhotoDetailImageItem, and the ClickMemoFold/noRippleClickableSingle usage
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt`:
- Around line 216-250: Separate the combined isMemoActive into two booleans: one
for showing the dim (e.g., showDim = uiState.memoMode == MemoMode.Expanded ||
uiState.memoMode == MemoMode.Editing) and one for blocking interactions (e.g.,
blockInteractions = uiState.memoMode == MemoMode.Editing); then use
blockInteractions for pager/user interaction flags (set HorizontalPager
userScrollEnabled = !blockInteractions and PhotoDetailImageItem isTapEnabled =
!blockInteractions) and use showDim to control AnimatedVisibility, but apply
noRippleClickableSingle (the ClickMemoFold handler) only when blockInteractions
is true so the dim in Expanded no longer intercepts pointer events; update
references to uiState.memoMode, MemoMode.Expanded, MemoMode.Editing, pagerState,
PhotoDetailImageItem, and the ClickMemoFold/noRippleClickableSingle usage
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9d2b886b-1aaa-4ac3-9884-0f70c98bdc5f

📥 Commits

Reviewing files that changed from the base of the PR and between 612b85a and 504aac1.

📒 Files selected for processing (2)
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/PhotoDetailScreen.kt
  • feature/archive/impl/src/main/kotlin/com/neki/android/feature/archive/impl/photo_detail/component/PhotoDetailActionBar.kt

@ikseong00 ikseong00 merged commit b42d2b9 into develop Apr 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] PhotoDetail 메모 UI를 HorizontalPager 밖으로 분리

2 participants