-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 최근 로그인 계정 정보 안내 기능 구현 #243
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
base: develop
Are you sure you want to change the base?
Conversation
기존 CustomTooltipBox -> RecordTooltipBox로 네이밍 변경
Walkthrough이 변경사항은 사용자의 마지막 로그인 방법(카카오 또는 구글)을 추적하고 저장하는 기능을 구현합니다. DataStore Preferences를 기반으로 하는 새로운 데이터소스를 통해 로그인 방법을 관리하고, 로그인 화면에서 마지막 로그인 정보를 나타내는 툴팁을 표시합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant LoginUI as Login<br/>Screen
participant LoginPresenter
participant AuthRepository
participant LoginMethodDataSource
participant DataStore as DataStore<br/>Preferences
rect rgb(200, 240, 220)
Note over User,DataStore: 초기 로드: 최근 로그인 방법 조회
LoginUI->>LoginPresenter: LaunchedEffect 시작
LoginPresenter->>AuthRepository: recentLoginMethod 수집
AuthRepository->>LoginMethodDataSource: recentLoginMethod Flow 요청
LoginMethodDataSource->>DataStore: "RECENT_LOGIN_METHOD" 읽기
DataStore-->>LoginMethodDataSource: 저장된 값 반환
LoginMethodDataSource-->>AuthRepository: LoginMethod enum 변환
AuthRepository-->>LoginPresenter: 최근 로그인 방법 발행
LoginPresenter->>LoginPresenter: showLoginTooltip, recentLoginMethod 상태 업데이트
LoginPresenter-->>LoginUI: 업데이트된 UiState 전달
LoginUI->>LoginUI: 툴팁 표시
end
rect rgb(240, 220, 200)
Note over User,DataStore: 로그인 성공: 로그인 방법 저장
User->>LoginUI: 카카오 로그인 클릭
LoginUI->>LoginPresenter: 로그인 프로세스 시작
LoginPresenter->>AuthRepository: 로그인 처리
alt 로그인 성공
AuthRepository->>LoginMethodDataSource: setRecentLoginMethod(KAKAO) 호출
LoginMethodDataSource->>DataStore: "KAKAO" 저장
DataStore-->>LoginMethodDataSource: 저장 완료
LoginMethodDataSource-->>AuthRepository: 완료
end
end
rect rgb(220, 240, 240)
Note over User,DataStore: 툴팁 닫기
User->>LoginUI: 배경 클릭 (showLoginTooltip=true)
LoginUI->>LoginPresenter: OnDismissLoginTooltip 전송
LoginPresenter->>LoginPresenter: showLoginTooltip = false
LoginPresenter-->>LoginUI: 업데이트된 UiState (showLoginTooltip=false)
LoginUI->>LoginUI: 툴팁 숨기기
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ 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: 3
🧹 Nitpick comments (6)
core/datastore/api/src/main/kotlin/com/ninecraft/booket/core/datastore/api/datasource/LoginMethodDataSource.kt (1)
6-10: 공개 API에 KDoc 문서화 권장새로운 공개 인터페이스에 KDoc 주석을 추가하면 API 사용성과 유지보수성이 향상됩니다. 각 메서드의 목적과 동작을 간략히 설명하는 것이 좋습니다.
🔎 제안하는 문서화 예시
+/** + * 최근 로그인 방식을 관리하는 데이터 소스. + */ interface LoginMethodDataSource { + /** + * 최근 로그인 방식을 Flow로 제공합니다. + */ val recentLoginMethod: Flow<LoginMethod> + + /** + * 최근 로그인 방식을 저장합니다. + */ suspend fun setRecentLoginMethod(loginMethod: LoginMethod) + + /** + * 저장된 최근 로그인 방식을 초기화합니다. + */ suspend fun clearRecentLoginMethod() }core/model/src/main/kotlin/com/ninecraft/booket/core/model/LoginMethod.kt (1)
3-7: Enum 정의 확인 완료 및 문서화 권장로그인 방식을 나타내는 enum이 명확하게 정의되었습니다. PR 설명에 따르면 구글 로그인 툴팁은 별도 PR에서 작업 예정이므로
간단한 KDoc 주석을 추가하면 코드 가독성이 향상됩니다.
🔎 제안하는 문서화 예시
+/** + * 사용자의 로그인 방식을 나타냅니다. + */ enum class LoginMethod { + /** 로그인 방식이 설정되지 않음 */ NONE, + /** 카카오 로그인 */ KAKAO, + /** 구글 로그인 */ GOOGLE, }core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.kt (1)
21-25: 공개 API에 KDoc 문서화 권장새로운 공개 API에 KDoc 주석을 추가하면 의도와 사용 방법이 명확해집니다. 특히
clearRecentLoginMethod()가 어떤 상황에서 호출되어야 하는지(로그아웃/탈퇴 시) 명시하면 좋습니다.🔎 제안하는 문서화 예시
+ /** + * 최근 로그인 방식을 나타내는 Flow입니다. + */ val recentLoginMethod: Flow<LoginMethod> + /** + * 최근 로그인 방식을 저장합니다. + * @param loginMethod 저장할 로그인 방식 + */ suspend fun setRecentLoginMethod(loginMethod: LoginMethod) + /** + * 저장된 최근 로그인 방식을 초기화합니다. + * 로그아웃 또는 회원 탈퇴 시 호출됩니다. + */ suspend fun clearRecentLoginMethod()core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.kt (1)
22-31: 문자열 비교 대신LoginMethod.name을 사용하는 것이 더 안전합니다.현재 하드코딩된 문자열("KAKAO", "GOOGLE")로 비교하고 있는데,
LoginMethodenum의name을 사용하면 enum 이름 변경 시에도 일관성을 유지할 수 있습니다.🔎 제안하는 수정
override val recentLoginMethod: Flow<LoginMethod> = dataStore.data .handleIOException() .map { prefs -> val method = prefs[RECENT_LOGIN_METHOD] when (method) { - "KAKAO" -> LoginMethod.KAKAO - "GOOGLE" -> LoginMethod.GOOGLE + LoginMethod.KAKAO.name -> LoginMethod.KAKAO + LoginMethod.GOOGLE.name -> LoginMethod.GOOGLE else -> LoginMethod.NONE } }feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
77-82: 삼각형 포인터의 오프셋 값에 하드코딩된14.dp가 사용되고 있습니다.다른 곳에서는
ReedTheme.spacing을 사용하는데, 여기서는14.dp가 하드코딩되어 있습니다. 일관성을 위해 테마 값을 사용하거나 상수로 추출하는 것을 고려해 주세요.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (1)
128-135: 툴팁 위치 지정에 하드코딩된 오프셋 값이 사용되고 있습니다.
(-28).dp와(-32).dp값이 하드코딩되어 있습니다. 다양한 화면 크기나 폰트 스케일링에서 일관된 위치를 보장하려면 테마 기반 값을 사용하거나, 최소한 상수로 추출하는 것이 좋습니다.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.ktcore/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultAuthRepository.ktcore/datastore/api/src/main/kotlin/com/ninecraft/booket/core/datastore/api/datasource/LoginMethodDataSource.ktcore/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.ktcore/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/di/DataStoreGraph.ktcore/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/di/DataStoreQualifier.ktcore/model/src/main/kotlin/com/ninecraft/booket/core/model/LoginMethod.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.ktfeature/login/src/main/res/values/strings.xmlfeature/onboarding/stability/onboarding.stabilityfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/RecordTooltipBox.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.ktfeature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt
💤 Files with no reviewable changes (1)
- feature/onboarding/stability/onboarding.stability
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.ktcore/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/di/DataStoreGraph.ktcore/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt
📚 Learning: 2025-07-31T23:30:37.547Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/record/RecordDetailPresenter.kt:18-47
Timestamp: 2025-07-31T23:30:37.547Z
Learning: In Circuit architecture, presenters receive the Screen object directly as a constructor parameter (e.g., Assisted private val screen: RecordDetailScreen), and screen parameters are accessed through this screen object (e.g., screen.recordId). Screen parameters should not be added as separate constructor parameters.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt
📚 Learning: 2025-08-28T12:26:12.482Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.kt:16-19
Timestamp: 2025-08-28T12:26:12.482Z
Learning: In AuthRepository, autoLoginState and userState serve different purposes and should not be conflated:
- autoLoginState: tracks whether automatic login is enabled (user preference/setting)
- userState: tracks current authentication state (Guest vs LoggedIn)
These are orthogonal concepts that need to be maintained separately.
Applied to files:
core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.kt
📚 Learning: 2025-07-20T12:34:23.786Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 `booket.android.feature` convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt
🧬 Code graph analysis (6)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/RecordTooltipBox.kt (1)
RecordTooltipBox(25-64)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt (1)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/RecordTooltipBox.kt (1)
RecordTooltipBox(25-64)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (5)
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedTopAppBar.kt (1)
ReedCloseTopAppBar(105-120)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
LoginTooltipBox(51-91)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedTextButton.kt (1)
ReedTextButton(25-74)core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedLoadingIndicator.kt (1)
ReedLoadingIndicator(16-36)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultAuthRepository.kt (3)
core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.kt (1)
clearRecentLoginMethod(25-25)core/datastore/api/src/main/kotlin/com/ninecraft/booket/core/datastore/api/datasource/LoginMethodDataSource.kt (1)
clearRecentLoginMethod(9-9)core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.kt (1)
clearRecentLoginMethod(39-43)
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/RecordTooltipBox.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
⏰ 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). (2)
- GitHub Check: Compose Stability Check
- GitHub Check: ci-build
🔇 Additional comments (16)
feature/login/src/main/res/values/strings.xml (1)
9-9: 문자열 리소스 추가 확인 완료최근 로그인 기능을 위한 문자열 리소스가 적절하게 추가되었습니다.
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/QuoteStep.kt (1)
48-48: 컴포넌트 리네임 확인 완료
CustomTooltipBox에서RecordTooltipBox로의 리네임이 일관되게 적용되었습니다.Also applies to: 148-148
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/step/ImpressionStep.kt (1)
54-54: 컴포넌트 리네임 확인 완료
CustomTooltipBox에서RecordTooltipBox로의 리네임이 일관되게 적용되었습니다.Also applies to: 159-161
feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/component/RecordTooltipBox.kt (1)
26-26: 컴포넌트 리네임 확인 완료
CustomTooltipBox에서RecordTooltipBox로의 리네임이 선언부, 프리뷰 함수, 사용처 모두에서 일관되게 적용되었습니다. 더 명확한 네이밍으로 개선되었습니다.Also applies to: 68-70
core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/di/DataStoreQualifier.kt (1)
25-27: DI Qualifier 추가 확인 완료기존 패턴을 따라
LoginMethodDataStorequalifier가 적절하게 추가되었습니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt (2)
14-15: LGTM! 상태 속성 추가가 적절합니다.
showLoginTooltip과recentLoginMethod의 기본값이 적절하며, 기존LoginUiState패턴을 잘 따르고 있습니다.
34-34: 이벤트 추가가 적절합니다.
OnDismissLoginTooltip이벤트가 기존 이벤트 네이밍 컨벤션과 일관성 있게 추가되었습니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt (1)
105-126: 로그인 성공 시 최근 로그인 방식 저장 로직이 적절합니다.Kakao 로그인 성공 후
setRecentLoginMethod(LoginMethod.KAKAO)를 호출하여 다음 로그인 시 툴팁에 표시될 수 있도록 저장하는 로직이 올바르게 구현되었습니다.core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/di/DataStoreGraph.kt (2)
30-37: DataStore 설정이 기존 패턴과 일관성 있게 추가되었습니다.
LOGIN_METHOD_DATASTORE_NAME상수와Context.loginMethodDataStore확장 속성이 기존의 다른 DataStore 설정과 동일한 패턴으로 구현되었습니다.
72-76: DI 바인딩이 올바르게 구성되었습니다.Provider와 Binds 설정이 기존 DataSource들과 동일한 패턴을 따르고 있어 일관성이 유지됩니다.
Also applies to: 92-94
core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.kt (1)
17-21: SingleIn 스코프와 의존성 주입이 올바르게 설정되었습니다.
@SingleIn(DataScope::class)와@LoginMethodDataStore한정자를 사용한 DI 설정이 프로젝트의 다른 DataSource 구현체들과 일관성 있게 구성되었습니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
31-49: TriangleShape 구현이 깔끔합니다.커스텀
Shape구현이 명확하고 주석도 잘 되어 있어 코드 이해가 쉽습니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (2)
124-136:recentLoginMethod상태가 UI에서 사용되지 않고 있습니다.현재
state.recentLoginMethod가LoginUiState에 포함되어 있지만, 툴팁 메시지에서 사용되지 않고 있습니다. 항상R.string.recent_login만 표시되는데, 이것이 의도된 동작인지 확인해 주세요.만약 "카카오로 최근 로그인" 또는 "구글로 최근 로그인"처럼 로그인 방식에 따라 다른 메시지를 표시해야 한다면,
recentLoginMethod를 활용하여 동적으로 메시지를 선택해야 합니다.
59-72: 툴팁 해제를 위한 클릭 핸들러 구현이 적절합니다.
showLoginTooltip상태에 따라 조건부로noRippleClickable을 적용하여 툴팁 외부 클릭 시 해제되도록 구현한 부분이 좋습니다.core/data/impl/src/main/kotlin/com/ninecraft/booket/core/data/impl/repository/DefaultAuthRepository.kt (2)
41-45: 회원 탈퇴 시 최근 로그인 방식 초기화가 적절하게 구현되었습니다.
withdraw()호출 시clearRecentLoginMethod()를 호출하여 계정 삭제 후 로그인 방식 정보가 남지 않도록 처리한 부분이 올바릅니다.
76-81:recentLoginMethod속성과 setter 메서드가 올바르게 구현되었습니다.
loginMethodDataSource에 위임하는 방식으로 깔끔하게 구현되었으며, 기존 repository 패턴과 일관성을 유지하고 있습니다.
| val recentLoginMethod: Flow<LoginMethod> | ||
|
|
||
| suspend fun setRecentLoginMethod(loginMethod: LoginMethod) | ||
|
|
||
| suspend fun clearRecentLoginMethod() |
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:
#!/bin/bash
# Find and examine the logout implementation in DefaultAuthRepository
rg -A 10 "override suspend fun logout" --type kotlinRepository: YAPP-Github/Reed-Android
Length of output: 1459
logout() 메서드에서 clearRecentLoginMethod() 호출 누락
logout() 메서드에서 clearRecentLoginMethod()를 호출하지 않고 있습니다. withdraw() 메서드에서는 호출되고 있으나, logout()에서는 누락되어 있습니다. 사용자가 로그아웃 후 다시 로그인 화면에 접근할 때 이전 로그인 방식이 표시되는 불일치한 동작이 발생합니다. logout() 메서드에도 clearRecentLoginMethod()를 추가하여 withdraw()와 일관성 있게 수정해주세요.
🤖 Prompt for AI Agents
In
core/data/api/src/main/kotlin/com/ninecraft/booket/core/data/api/repository/AuthRepository.kt
around lines 21 to 25, the recentLoginMethod flow and clearRecentLoginMethod()
are defined but the logout() implementation does not call
clearRecentLoginMethod(), causing the previous login method to remain visible
after logout; update the logout() method to invoke suspend fun
clearRecentLoginMethod() (same as withdraw()) so the stored recent login method
is cleared on logout, and ensure any call is awaited and errors are handled
consistently with withdraw().
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt
Show resolved
Hide resolved
| LaunchedEffect(Unit) { | ||
| authRepository.recentLoginMethod.collect { method -> | ||
| recentLoginMethod = method | ||
| showLoginTooltip = method != LoginMethod.NONE | ||
| } | ||
| } |
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.
툴팁 해제 후 다시 표시되는 잠재적 문제가 있습니다.
LaunchedEffect에서 collect를 사용하여 recentLoginMethod를 수신하고 있는데, 사용자가 툴팁을 해제(showLoginTooltip = false)한 후에도 Flow에서 동일한 값이 다시 emit되면 툴팁이 다시 표시될 수 있습니다.
해제 상태를 별도로 추적하거나, collectLatest와 함께 해제 플래그를 관리하는 방식을 고려해 주세요.
🔎 제안하는 수정 방안
+ var hasUserDismissedTooltip by rememberRetained { mutableStateOf(false) }
+
LaunchedEffect(Unit) {
authRepository.recentLoginMethod.collect { method ->
recentLoginMethod = method
- showLoginTooltip = method != LoginMethod.NONE
+ showLoginTooltip = method != LoginMethod.NONE && !hasUserDismissedTooltip
}
}그리고 OnDismissLoginTooltip 핸들러에서:
is LoginUiEvent.OnDismissLoginTooltip -> {
showLoginTooltip = false
+ hasUserDismissedTooltip = true
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| LaunchedEffect(Unit) { | |
| authRepository.recentLoginMethod.collect { method -> | |
| recentLoginMethod = method | |
| showLoginTooltip = method != LoginMethod.NONE | |
| } | |
| } | |
| var hasUserDismissedTooltip by rememberRetained { mutableStateOf(false) } | |
| LaunchedEffect(Unit) { | |
| authRepository.recentLoginMethod.collect { method -> | |
| recentLoginMethod = method | |
| showLoginTooltip = method != LoginMethod.NONE && !hasUserDismissedTooltip | |
| } | |
| } |
🤖 Prompt for AI Agents
In
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt
around lines 58 to 63, the LaunchedEffect collects recentLoginMethod and
unconditionally sets showLoginTooltip when a value is emitted, which allows the
tooltip to reappear if the Flow re-emits the same/non-NONE method after the user
dismissed it; fix by adding a dismissed flag (e.g., loginTooltipDismissed) that
the OnDismissLoginTooltip handler sets to true, and in the collector only set
showLoginTooltip = true when method != LoginMethod.NONE AND
loginTooltipDismissed is false (or use collectLatest and check the dismissed
flag before showing), ensuring the dismiss action prevents future emissions from
re-showing the tooltip.
compose stability analyzer 버전 최신화
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: 1
🧹 Nitpick comments (4)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (2)
79-79: 하드코딩된 값을 테마 상수로 추출하는 것을 고려하세요.Line 79의
14.dp와 Line 84의8.dp등 하드코딩된 값들이 있습니다. 이러한 값들을 테마 상수로 추출하면 유지보수성과 일관성이 향상됩니다.🔎 제안하는 개선 방안
.offset { IntOffset( - x = 14.dp.roundToPx(), + x = ReedTheme.spacing.spacing2.roundToPx(), y = 0, ) } .graphicsLayer { - shadowElevation = 8.dp.toPx() + shadowElevation = ReedTheme.elevation.medium.toPx() // elevation 상수가 있다면 shape = TriangleShape clip = true }Also applies to: 84-84
59-59: 테마 상수의 의미적 사용을 검토하세요.
- Line 59:
ReedTheme.radius.xs를 그림자 elevation으로 사용하고 있습니다.radius는 일반적으로 corner rounding을 위한 값이며, elevation에는 별도의 상수를 사용하는 것이 의미상 적절합니다.- Lines 75-76:
ReedTheme.spacing.spacing3를 삼각형의 width/height로 사용하고 있습니다.spacing상수는 일반적으로 요소 간 간격을 위한 값이며, 컴포넌트 크기에는 별도의 dimension 상수를 사용하는 것이 더 명확합니다.Also applies to: 75-76
core/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.kt (1)
24-31: 하드코딩된 문자열 대신 enum name 사용을 권장합니다.
setRecentLoginMethod에서는loginMethod.name을 사용하지만, 읽기 시에는 하드코딩된 문자열을 사용합니다. 일관성을 위해 enum의 name 속성을 활용하세요.🔎 제안된 수정 사항
.map { prefs -> val method = prefs[RECENT_LOGIN_METHOD] when (method) { - "KAKAO" -> LoginMethod.KAKAO - "GOOGLE" -> LoginMethod.GOOGLE + LoginMethod.KAKAO.name -> LoginMethod.KAKAO + LoginMethod.GOOGLE.name -> LoginMethod.GOOGLE else -> LoginMethod.NONE } }feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (1)
128-133: 매직 넘버를 상수로 추출하는 것을 고려해 보세요.오프셋 값
-28.dp와-32.dp를 상수로 추출하면 유지보수성이 향상됩니다.🔎 제안된 수정 사항
private object LoginTooltipOffset { val X = (-28).dp val Y = (-32).dp }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
app/stability/app.stabilitycore/datastore/api/src/main/kotlin/com/ninecraft/booket/core/datastore/api/datasource/LoginMethodDataSource.ktcore/datastore/impl/src/main/kotlin/com/ninecraft/booket/core/datastore/impl/datasource/DefaultLoginMethodDataSource.ktcore/designsystem/stability/designsystem.stabilityfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.ktfeature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.ktfeature/login/stability/login.stabilityfeature/record/stability/record.stabilitygradle/libs.versions.toml
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-28T12:25:54.058Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 174
File: feature/search/src/main/kotlin/com/ninecraft/booket/feature/search/book/BookSearchPresenter.kt:128-133
Timestamp: 2025-08-28T12:25:54.058Z
Learning: In BookSearchPresenter.kt, when a guest user tries to register a book and is redirected to login, the bottom sheet (isBookRegisterBottomSheetVisible) and selection state (selectedBookIsbn, selectedBookStatus) are intentionally kept open/preserved so that when the user returns from login, they can continue from where they left off without losing context.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt
📚 Learning: 2025-07-28T18:08:47.298Z
Learnt from: seoyoon513
Repo: YAPP-Github/Reed-Android PR: 72
File: feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/ocr/component/CameraFrame.kt:21-82
Timestamp: 2025-07-28T18:08:47.298Z
Learning: Jetpack Compose에서 scale() 변환은 시각적 변환만 적용하며 레이아웃 좌표계는 변경하지 않는다. 따라서 scale(scaleX = -1f, scaleY = -1f)로 반전된 아이콘에서 padding()은 원래 레이아웃 기준으로 동작하므로, 시각적으로 올바른 위치를 위해서는 변환 전 좌표계 기준으로 padding을 설정해야 한다.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt
📚 Learning: 2025-07-20T12:34:23.786Z
Learnt from: easyhooon
Repo: YAPP-Github/Reed-Android PR: 61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 `booket.android.feature` convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
Applied to files:
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt
🧬 Code graph analysis (2)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (5)
core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedTopAppBar.kt (1)
ReedCloseTopAppBar(105-120)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedButton.kt (1)
ReedButton(34-114)feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
LoginTooltipBox(51-91)core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/button/ReedTextButton.kt (1)
ReedTextButton(25-74)core/ui/src/main/kotlin/com/ninecraft/booket/core/ui/component/ReedLoadingIndicator.kt (1)
ReedLoadingIndicator(16-36)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (1)
core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt (1)
ReedTheme(14-21)
🔇 Additional comments (11)
feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/component/LoginTooltipBox.kt (3)
31-49: 삼각형 Shape 구현이 올바릅니다.툴팁 포인터를 위한 아래를 가리키는 삼각형 Path 구현이 정확하며, Compose Shape API를 올바르게 따르고 있습니다.
57-89: 메인 박스와 삼각형 포인터의 그림자 처리가 다릅니다.메인 툴팁 박스는
shadow()modifier를 사용하고(Line 59), 삼각형 포인터는graphicsLayer의shadowElevation을 사용합니다(Line 84). 또한 elevation 값도 다릅니다(ReedTheme.radius.xsvs8.dp).커스텀 Shape에 대한 그림자는 플랫폼에 따라 렌더링이 일관되지 않을 수 있습니다. 두 요소의 그림자 처리 방식과 elevation 값이 다른 것이 의도된 것인지 확인하고, 시각적으로 일관된 결과를 제공하는지 검증해주세요.
93-99: Preview 함수명이 이제 올바릅니다.이전 리뷰에서 지적된 네이밍 이슈가 해결되었습니다.
LoginTooltipBoxPreview가 컴포넌트명과 일관성 있게 명명되었습니다.app/stability/app.stability (1)
12-12: LGTM - 자동 생성된 안정성 분석 결과입니다.Compose Stability Analyzer가
targetState의 가변 속성을 올바르게 감지하여 UNSTABLE로 표시했습니다.core/datastore/api/src/main/kotlin/com/ninecraft/booket/core/datastore/api/datasource/LoginMethodDataSource.kt (1)
6-10: 깔끔한 인터페이스 설계입니다.DataStore 기반 데이터 소스에 적합한 API 설계입니다:
Flow를 통한 반응형 데이터 관찰- suspend 함수를 통한 비동기 쓰기 작업
feature/login/stability/login.stability (1)
35-48: LGTM - LoginTooltipBox 안정성 분석 결과가 양호합니다.모든 파라미터가 STABLE로 표시되어 불필요한 재구성을 방지합니다.
feature/record/stability/record.stability (1)
44-56: LGTM - RecordTooltipBox로의 리네이밍이 적절합니다.
CustomTooltipBox에서RecordTooltipBox로 변경하여 컴포넌트의 용도가 더 명확해졌습니다.feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUi.kt (2)
58-71: LGTM - 툴팁 외부 클릭 시 닫기 처리가 적절합니다.
Modifier.then()을 사용한 조건부 클릭 핸들러 적용이 깔끔합니다. 툴팁이 표시될 때만 클릭 이벤트를 처리하여 불필요한 이벤트 처리를 방지합니다.
97-136: 카카오 로그인 버튼과 툴팁 구현이 잘 되어 있습니다.
ReedButton에leadingIcon파라미터를 활용하여 카카오 아이콘을 추가하고, 조건부로LoginTooltipBox를 렌더링하는 구조가 적절합니다.core/designsystem/stability/designsystem.stability (2)
44-57: LGTM - ReedButton API 확장이 적절히 반영되었습니다.
leadingIcon과trailingIcon파라미터가 추가되어 버튼 컴포넌트의 유연성이 향상되었습니다. 모든 파라미터가 STABLE로 표시되어 재구성 성능이 양호합니다.
103-137: LGTM - 버튼 스타일 헬퍼 함수들이 잘 구성되었습니다.
largeButtonStyle(),mediumButtonStyle(),smallButtonStyle()등 크기별 스타일 헬퍼가 추가되어 버튼 스타일 적용이 간편해졌습니다.
| compose-effects = "0.1.4" | ||
| compose-shadow = "2.0.4" | ||
| compose-stability-analyzer = "0.5.2" | ||
| compose-stability-analyzer = "0.6.6" |
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
🌐 Web query:
compose-stability-analyzer version 0.6.6 releases breaking changes
💡 Result:
I couldn’t find a published 0.6.6 release for skydoves/compose-stability-analyzer — the official GitHub releases page shows 0.6.5 (2025‑12‑17) as the latest and no “Breaking changes” entry for recent releases. Source: GitHub releases. [1]
If you have a link or tag name for 0.6.6 (or want me to search other registries like Maven Central), share it and I’ll check its changelog and breaking changes. [1]
🌐 Web query:
compose-stability-analyzer Maven Central repository versions
💡 Result:
Here are the Compose Stability Analyzer artifacts on Maven Central and current/latest versions shown on Maven repository pages:
- com.github.skydoves:compose-stability-compiler — listed 0.4.0 (page notes newer 0.6.1). [1]
- com.github.skydoves:compose-stability-runtime-jvm — 0.4.2 (newer 0.6.1 noted). [2]
- com.github.skydoves:compose-stability-gradle — 0.2.21. [3]
- com.github.skydoves.compose.stability.analyzer:com.github.skydoves.compose.stability.analyzer.gradle.plugin — 0.2.6. [4]
Sources: Maven Repository pages for the artifacts. [1] [2] [3] [4]
compose-stability-analyzer 버전을 0.6.5로 수정하세요.
버전 0.6.6은 존재하지 않습니다. 최신 버전은 0.6.5입니다(2025-12-17 릴리스). 현재 설정된 버전으로는 Gradle 의존성 해석이 실패하게 됩니다.
🤖 Prompt for AI Agents
In gradle/libs.versions.toml around line 27, the compose-stability-analyzer
version is set to 0.6.6 which does not exist; change the value to "0.6.5" so
Gradle can resolve the dependency; update the version string and save the file,
then re-run the build to verify resolution.
🔗 관련 이슈
📙 작업 설명
🧪 테스트 내역 (선택)
📸 스크린샷 또는 시연 영상 (선택)
default.mp4
💬 추가 설명 or 리뷰 포인트 (선택)
Summary by CodeRabbit
출시 노트
새 기능
UI 개선
✏️ Tip: You can customize this high-level summary in your review settings.