Skip to content

Commit 3b8ef89

Browse files
authored
feat - status에 따른 대기 화면 이동 구현 (#69)
* feat: PendingApproval -> PendingConnecting 이동 구현 * feat: status에 따른 대기 화면 전환 처리 완료 * feat: 재실행 안해도 되도록 해결 * feat: 폴링 주석 처리 * refactor: StatusRepository.kt 제거
1 parent a5976a9 commit 3b8ef89

File tree

7 files changed

+134
-19
lines changed

7 files changed

+134
-19
lines changed

app/src/main/java/com/apptive/japkor/data/api/MatchingService.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import retrofit2.Call
55
import retrofit2.http.GET
66
import retrofit2.http.POST
77
import retrofit2.http.Path
8+
import com.apptive.japkor.data.model.MyStatusResponse
89

910
interface MatchingService {
1011
@GET("members/matchings/female")
1112
fun getFemaleMatchings(): Call<List<MatchingResponse>>
1213

1314
@POST("members/matchings/{matchingId}/select")
1415
fun selectMatching(@Path("matchingId") matchingId: Long): Call<Void>
16+
17+
@GET("members/status")
18+
suspend fun getMyStatus(): MyStatusResponse
1519
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.apptive.japkor.data.model
2+
3+
data class MyStatusResponse(
4+
val memberId: Long,
5+
val name: String,
6+
val status: UserStatus
7+
)

app/src/main/java/com/apptive/japkor/navigation/AppNavHost.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ fun AppNavHost(
5252
composable(Screen.RequiredInfo.route) { RequiredInfoScreen(navController) }
5353
composable(Screen.RequiredInfoComplete.route) { RequiredInfoCompleteScreen(navController) }
5454

55-
composable(Screen.PendingApproval.route) { PendingApprovalRouteScreen() }
56-
composable(Screen.PendingConnecting.route) { PendingConnectingRouteScreen() }
55+
composable(Screen.PendingApproval.route) { PendingApprovalRouteScreen(navController) }
56+
composable(Screen.PendingConnecting.route) { PendingConnectingRouteScreen(navController) }
5757

5858
composable(Screen.Connected.route) { MainRouteScreen(navController) }
5959
composable(Screen.Blacklisted.route) { BlacklistedRouteScreen() }
Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.apptive.japkor.navigation
22

3+
import android.util.Log
34
import androidx.compose.runtime.Composable
45
import androidx.compose.runtime.LaunchedEffect
56
import androidx.compose.runtime.remember
67
import androidx.compose.ui.platform.LocalContext
78
import androidx.navigation.NavHostController
9+
import com.apptive.japkor.data.api.ServiceFactory
810
import com.apptive.japkor.data.local.DataStoreManager
911
import com.apptive.japkor.data.local.TokenProvider
1012
import com.apptive.japkor.data.model.UserStatus
@@ -21,42 +23,50 @@ fun RouterScreen(
2123

2224
LaunchedEffect(Unit) {
2325
val token = dataStore.getUserToken().first()
24-
25-
// 1️⃣ 토큰 없으면 → Language
26+
// 토큰 없으면 -> Language
2627
if (token.isBlank()) {
2728
navController.navigate(Screen.Language.route) {
2829
popUpTo(Screen.Router.route) { inclusive = true }
30+
launchSingleTop = true
2931
}
3032
return@LaunchedEffect
3133
}
3234

33-
// 2️⃣ 토큰 있으면 메모리에 세팅
35+
// 토큰 있으면 메모리에 세팅
3436
TokenProvider.setToken(token)
3537

36-
// 3️⃣ status 읽기
37-
val statusStr = dataStore.getUserStatus().first()
38+
// 서버에서 현재 status 확인
3839
val status = runCatching {
39-
UserStatus.valueOf(statusStr)
40-
}.getOrNull()
40+
val res = ServiceFactory.matchingService.getMyStatus()
41+
42+
dataStore.saveUserName(res.name)
43+
dataStore.saveUserStatus(res.status.name)
44+
res.status
45+
}.getOrElse { e ->
46+
// 서버 호출 실패 시 fallback: DataStore 값
47+
Log.e("ROUTER_DEBUG", "server status fetch failed, fallback datastore", e)
48+
val statusStr = dataStore.getUserStatus().first()
49+
runCatching { UserStatus.valueOf(statusStr) }.getOrNull()
50+
?: UserStatus.PENDING_APPROVAL // fallback 기본값(원하면 Login 등으로)
51+
}
4152

42-
// 4️⃣ status → 목적지 결정
53+
// status에 따른 화면 이동
4354
val targetRoute = when (status) {
4455
UserStatus.INCOMPLETE_PROFILE -> Screen.RequiredInfo.route
4556
UserStatus.PENDING_APPROVAL -> Screen.PendingApproval.route
57+
4658
UserStatus.APPROVED -> Screen.PendingConnecting.route
59+
4760
UserStatus.CONNECTING,
4861
UserStatus.CONNECTED -> Screen.Connected.route
4962
UserStatus.BLACKLISTED -> Screen.Blacklisted.route
50-
null -> Screen.Login.route
5163
}
5264

53-
// 5️⃣ Router 제거 + 이동
65+
Log.d("ROUTER_DEBUG", "status=$status -> target=$targetRoute")
66+
5467
navController.navigate(targetRoute) {
5568
popUpTo(Screen.Router.route) { inclusive = true }
5669
launchSingleTop = true
5770
}
5871
}
59-
60-
// 👀 사용자에게 보이는 UI (간단한 로딩/스플래시)
61-
//SplashLoadingScreen()
6272
}

app/src/main/java/com/apptive/japkor/ui/status/PendingApprovalRouteScreen.kt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,32 @@ import androidx.compose.runtime.collectAsState
55
import androidx.compose.runtime.getValue
66
import androidx.compose.runtime.remember
77
import androidx.compose.ui.platform.LocalContext
8+
import androidx.navigation.NavHostController
89
import com.apptive.japkor.R
910
import com.apptive.japkor.data.local.DataStoreManager
11+
import com.apptive.japkor.data.model.UserStatus
12+
import com.apptive.japkor.navigation.Screen
13+
import com.apptive.japkor.ui.common.StatusAdvanceEffect
1014

1115
@Composable
12-
fun PendingApprovalRouteScreen() {
16+
fun PendingApprovalRouteScreen(navController: NavHostController) {
1317
val context = LocalContext.current
1418
val dataStore = remember { DataStoreManager(context.applicationContext) }
15-
1619
val name by dataStore.getUserName().collectAsState(initial = "")
1720

21+
StatusAdvanceEffect(
22+
navController = navController,
23+
nextRoute = Screen.PendingConnecting.route,
24+
popUpFromRoute = Screen.PendingApproval.route,
25+
shouldAdvance = { status ->
26+
status == UserStatus.APPROVED ||
27+
status == UserStatus.CONNECTING ||
28+
status == UserStatus.CONNECTED
29+
},
30+
//pollMs = 5000L,
31+
debugTag = "ADV_APPROVAL"
32+
)
33+
1834
PendingApprovalScreen(
1935
name = name.ifBlank { "회원" },
2036
logoRes = R.drawable.ampersand_bg

app/src/main/java/com/apptive/japkor/ui/status/PendingConnectingRouteScreen.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,29 @@ import androidx.compose.runtime.collectAsState
55
import androidx.compose.runtime.getValue
66
import androidx.compose.runtime.remember
77
import androidx.compose.ui.platform.LocalContext
8+
import androidx.navigation.NavHostController
89
import com.apptive.japkor.R
910
import com.apptive.japkor.data.local.DataStoreManager
11+
import com.apptive.japkor.data.model.UserStatus
12+
import com.apptive.japkor.navigation.Screen
13+
import com.apptive.japkor.ui.common.StatusAdvanceEffect
1014

1115
@Composable
12-
fun PendingConnectingRouteScreen() {
16+
fun PendingConnectingRouteScreen(navController: NavHostController) {
1317
val context = LocalContext.current
1418
val dataStore = remember { DataStoreManager(context.applicationContext) }
15-
1619
val name by dataStore.getUserName().collectAsState(initial = "")
1720

21+
StatusAdvanceEffect(
22+
navController = navController,
23+
nextRoute = Screen.Connected.route,
24+
popUpFromRoute = Screen.PendingConnecting.route,
25+
shouldAdvance = { status -> status == UserStatus.CONNECTING },
26+
//pollMs = 3000L,
27+
debugTag = "ADV_CONNECTING"
28+
)
29+
30+
1831
PendingConnectingScreen(
1932
name = name.ifBlank { "회원" },
2033
logoRes = R.drawable.ampersand_bg
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.apptive.japkor.ui.common
2+
3+
import android.util.Log
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.LaunchedEffect
6+
import androidx.compose.runtime.remember
7+
import androidx.compose.ui.platform.LocalContext
8+
import androidx.compose.ui.platform.LocalLifecycleOwner
9+
import androidx.lifecycle.Lifecycle
10+
import androidx.lifecycle.repeatOnLifecycle
11+
import androidx.navigation.NavHostController
12+
import com.apptive.japkor.data.api.ServiceFactory
13+
import com.apptive.japkor.data.local.DataStoreManager
14+
import com.apptive.japkor.data.model.UserStatus
15+
import kotlinx.coroutines.delay
16+
17+
/**
18+
* 단방향 전이(이전 단계로 돌아가지 않음) 앱용:
19+
* - 화면이 STARTED 될 때 서버 status 재조회
20+
* - "다음 단계 조건"이 되면 단 한 번 navigate하고 이전 화면은 popUpTo로 제거
21+
* - 절대 이전 상태로 보내는 navigate는 하지 않는다
22+
*/
23+
@Composable
24+
fun StatusAdvanceEffect(
25+
navController: NavHostController,
26+
nextRoute: String,
27+
popUpFromRoute: String,
28+
shouldAdvance: (UserStatus) -> Boolean,
29+
pollMs: Long = 5000L, // 0이면 포커싱 시 1회만, 아니면 n ms마다 폴링
30+
debugTag: String = "ADVANCE"
31+
) {
32+
val context = LocalContext.current
33+
val dataStore = remember { DataStoreManager(context.applicationContext) }
34+
val lifecycleOwner = LocalLifecycleOwner.current
35+
36+
LaunchedEffect(lifecycleOwner) {
37+
lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
38+
while (true) {
39+
runCatching {
40+
val res = ServiceFactory.matchingService.getMyStatus()
41+
42+
// ✅ 서버 값 그대로 캐시
43+
dataStore.saveUserName(res.name)
44+
dataStore.saveUserStatus(res.status.name)
45+
46+
Log.d(debugTag, "status=${res.status}")
47+
48+
if (shouldAdvance(res.status)) {
49+
Log.d(debugTag, "advance -> $nextRoute (popUpFrom=$popUpFromRoute)")
50+
navController.navigate(nextRoute) {
51+
popUpTo(popUpFromRoute) { inclusive = true } // ✅ 이전 단계 제거
52+
launchSingleTop = true
53+
}
54+
return@repeatOnLifecycle
55+
}
56+
}.onFailure { e ->
57+
Log.e(debugTag, "status check failed", e)
58+
}
59+
60+
if (pollMs <= 0L) break
61+
delay(pollMs)
62+
}
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)