Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import com.apptive.japkor.data.local.DataStoreManager
import com.apptive.japkor.data.local.TokenProvider
import com.apptive.japkor.data.model.UserStatus
import com.apptive.japkor.data.repository.AuthRepository
import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

class LoginScreenViewModel(
application: Application,
Expand Down Expand Up @@ -42,7 +46,12 @@ class LoginScreenViewModel(
Log.d("LoginVM", "signIn 호출: email=$email, password=$password")

try {
val fcmToken = dataStore.getFcmToken().first()
val fcmToken = getOrFetchFcmToken()
if (fcmToken.isBlank()) {
Log.e("LoginVM", "FCM token missing; aborting signIn")
onResult(false, null)
return@launch
}
val result = repository.signIn(email, password, fcmToken)
if (result != null) {
Log.d("LoginVM", "로그인 성공! token=${result.token}")
Expand Down Expand Up @@ -71,6 +80,36 @@ class LoginScreenViewModel(
}
}

private suspend fun getOrFetchFcmToken(): String {
val cachedToken = dataStore.getFcmToken().first()
if (cachedToken.isNotBlank()) return cachedToken

return try {
val token = fetchFcmToken()
if (token.isNotBlank()) {
dataStore.saveFcmToken(token)
}
token
} catch (e: Exception) {
Log.w("LoginVM", "FCM token fetch failed", e)
""
}
}

private suspend fun fetchFcmToken(): String = suspendCancellableCoroutine { cont ->
FirebaseMessaging.getInstance().token
.addOnCompleteListener { task ->
if (!cont.isActive) return@addOnCompleteListener
if (task.isSuccessful) {
cont.resume(task.result.orEmpty())
} else {
cont.resumeWithException(
task.exception ?: IllegalStateException("FCM token fetch failed")
)
}
}
}
Comment on lines +99 to +111
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The addOnCompleteListener callback may execute on the main thread, but there's no guarantee which thread it will run on. This could cause the coroutine continuation to resume on an unexpected thread. Consider using addOnCompleteListener with an explicit executor or adding .addOnCompleteListener(Dispatchers.Main.asExecutor()) to ensure consistent threading behavior, or alternatively use Tasks.await() from the kotlinx-coroutines-play-services library which handles this more idiomatically.

Copilot uses AI. Check for mistakes.

fun updateRememberedEmail(remember: Boolean, email: String) {
viewModelScope.launch {
if (remember && email.isNotBlank()) {
Expand Down
Loading