Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements user information synchronization during login by introducing a new API endpoint (getMemberInfo) that replaces the previous getMyStatus API. The new endpoint returns comprehensive user profile data which is then stored locally for offline access.
Key changes:
- Introduced
MemberServiceAPI withgetMemberInfo()endpoint that returns detailed user profile information - Created
MemberInfoResponsedata model containing 20+ user profile fields - Extended
DataStoreManagerto persist all member information fields locally - Updated login flows to fetch and cache member info after authentication
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
MemberService.kt |
New API service interface for fetching member information |
MemberInfoResponse.kt |
New data model containing comprehensive user profile fields |
ServiceFactory.kt |
Added lazy initialization for memberService |
DataStoreManager.kt |
Added saveMemberInfo() method and 18 new preference keys for storing extended user data |
LoginScreenViewModel.kt |
Added refreshMemberInfo() to fetch and cache member info after successful login |
LoginCallbackActivity.kt |
Added refreshMemberInfo() call during OAuth callback handling |
StatusAdvanceEffect.kt |
Replaced getMyStatus() with getMemberInfo() for status polling |
RouterScreen.kt |
Replaced getMyStatus() with getMemberInfo() for initial routing logic |
MatchingService.kt |
Removed unused MyStatusResponse import |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| startActivity(i) | ||
| refreshMemberInfo(dataStore) |
There was a problem hiding this comment.
The member info refresh is called after startActivity() and before finish(), which means it may not complete before the activity is destroyed. This could result in the member info not being saved properly. Consider moving refreshMemberInfo(dataStore) to execute before startActivity(i) to ensure the data is fully persisted before transitioning to the next activity.
| startActivity(i) | |
| refreshMemberInfo(dataStore) | |
| refreshMemberInfo(dataStore) | |
| startActivity(i) |
| private suspend fun refreshMemberInfo() { | ||
| runCatching { | ||
| ServiceFactory.memberService.getMemberInfo().awaitResponse() | ||
| }.onSuccess { response -> | ||
| if (response.isSuccessful) { | ||
| val body = response.body() | ||
| if (body != null) { | ||
| dataStore.saveMemberInfo(body) | ||
| } else { | ||
| Log.w("LoginVM", "member info response is empty") | ||
| } | ||
| } else { | ||
| Log.w("LoginVM", "member info fetch failed: code=${response.code()}") | ||
| } | ||
| }.onFailure { e -> | ||
| Log.w("LoginVM", "member info fetch failed", e) | ||
| } | ||
| } |
There was a problem hiding this comment.
The same refreshMemberInfo() logic is duplicated in three places: LoginScreenViewModel.kt, LoginCallbackActivity.kt, and similar error handling logic in StatusAdvanceEffect.kt and RouterScreen.kt. Consider extracting this into a shared utility function or repository method to reduce code duplication and improve maintainability. This would also ensure consistent error handling and logging across all usages.
|
|
||
| suspend fun saveMemberInfo(info: MemberInfoResponse) { | ||
| context.dataStore.edit { prefs -> | ||
| prefs[KEY_MEMBER_ID] = info.memberId.toInt() |
There was a problem hiding this comment.
Converting Long to Int with .toInt() can cause data loss if the memberId value exceeds the maximum Int value (2,147,483,647). Since the API returns memberId as Long, consider changing KEY_MEMBER_ID to use longPreferencesKey instead of intPreferencesKey to safely store the full range of Long values.
| prefs[KEY_MEMBER_ID] = info.memberId.toInt() | |
| val memberId = info.memberId | |
| require(memberId in Int.MIN_VALUE.toLong()..Int.MAX_VALUE.toLong()) { | |
| "memberId $memberId is out of Int range and cannot be stored safely" | |
| } | |
| prefs[KEY_MEMBER_ID] = memberId.toInt() |
| import retrofit2.Call | ||
| import retrofit2.http.GET | ||
|
|
||
| interface MemberService { | ||
| @GET("members/info") | ||
| fun getMemberInfo(): Call<MemberInfoResponse> |
There was a problem hiding this comment.
Using retrofit2.Call.awaitResponse() with runCatching may not properly handle coroutine cancellation. Consider using Retrofit's suspend function directly instead of Call with awaitResponse. Change the getMemberInfo() return type from Call<MemberInfoResponse> to a suspend function returning Response<MemberInfoResponse> or MemberInfoResponse directly for better coroutine support and simpler error handling.
| import retrofit2.Call | |
| import retrofit2.http.GET | |
| interface MemberService { | |
| @GET("members/info") | |
| fun getMemberInfo(): Call<MemberInfoResponse> | |
| import retrofit2.http.GET | |
| interface MemberService { | |
| @GET("members/info") | |
| suspend fun getMemberInfo(): MemberInfoResponse |
작업내용