Skip to content

Commit

Permalink
Merge pull request #32 from YAPP-Github/feature/tgyuu/PC-254
Browse files Browse the repository at this point in the history
[PC-254] 코루틴 유틸함수 추가 및 LoginScreen 불필요한 Spacer 제거
  • Loading branch information
tgyuuAn authored Jan 12, 2025
2 parents 71398d1 + 9611622 commit b40ccda
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 48 deletions.
14 changes: 14 additions & 0 deletions core/common-ui/src/main/java/com/puzzle/common/ui/CoroutineUtil.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.puzzle.common.ui

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

fun LifecycleOwner.repeatOnStarted(block: suspend CoroutineScope.() -> Unit) {
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED, block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,15 @@ fun PieceLoginButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
border: BorderStroke? = null,
containerColor: Color = PieceTheme.colors.primaryDefault,
labelColor: Color = PieceTheme.colors.black
) {
Button(
onClick = onClick,
enabled = enabled,
shape = RoundedCornerShape(8.dp),
border = border,
colors = ButtonDefaults.buttonColors(
containerColor = containerColor,
contentColor = PieceTheme.colors.white,
Expand Down
1 change: 1 addition & 0 deletions core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<string name="accept_matching">매칭 수락하기</string>

<!--login-->
<string name="login_description">서로의 빈 곳을 채우며 맞물리는 퍼즐처럼.\n서로의 가치관과 마음이 연결되는 순간을 만들어갑니다.</string>
<string name="kakao_login">카카오로 시작하기</string>
<string name="google_login">구글로 시작하기</string>

Expand Down
1 change: 1 addition & 0 deletions feature/auth/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ android {
}

dependencies {
implementation(projects.core.common)
implementation(libs.kakao.user)
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package com.puzzle.auth.graph.login

import android.content.Context
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -26,11 +26,14 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.LocalLifecycleOwner
import com.airbnb.mvrx.compose.collectAsState
import com.airbnb.mvrx.compose.mavericksViewModel
import com.kakao.sdk.user.UserApiClient
import com.puzzle.auth.graph.login.contract.LoginIntent.Navigate
import com.puzzle.auth.graph.login.contract.LoginSideEffect
import com.puzzle.auth.graph.login.contract.LoginState
import com.puzzle.common.ui.repeatOnStarted
import com.puzzle.designsystem.R
import com.puzzle.designsystem.component.PieceLoginButton
import com.puzzle.designsystem.component.PieceSubCloseTopBar
Expand All @@ -40,29 +43,32 @@ import com.puzzle.navigation.AuthGraphDest
import com.puzzle.navigation.NavigationEvent

@Composable
fun LoginRoute(
internal fun LoginRoute(
viewModel: LoginViewModel = mavericksViewModel(),
) {
val state by viewModel.collectAsState()
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current

LoginScreen(
state = state,
loginKakao = {
UserApiClient.instance.loginWithKakaoAccount(context) { token, error ->
if (error != null) {
// Log.e("test", "로그인 실패", error)
} else if (token != null) {
// Log.i("test", "로그인 성공 ${token.accessToken}")
LaunchedEffect(Unit) {
lifecycleOwner.repeatOnStarted {
viewModel.sideEffects.collect { sideEffect ->
when (sideEffect) {
is LoginSideEffect.LoginKakao -> loginKakao(context)
}
}
},
}
}

LoginScreen(
state = state,
loginKakao = { viewModel.onSideEffect(LoginSideEffect.LoginKakao) },
navigate = { viewModel.onIntent(Navigate(it)) },
)
}

@Composable
fun LoginScreen(
private fun LoginScreen(
state: LoginState,
loginKakao: () -> Unit,
navigate: (NavigationEvent) -> Unit,
Expand All @@ -85,13 +91,9 @@ fun LoginScreen(
PieceSubCloseTopBar(
title = "",
onCloseClick = { },
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 14.dp),
modifier = Modifier.fillMaxWidth(),
)

Spacer(modifier = Modifier.height(20.dp))

Text(
text = buildAnnotatedString {
withStyle(style = SpanStyle(color = PieceTheme.colors.primaryDefault)) {
Expand All @@ -102,20 +104,20 @@ fun LoginScreen(
},
style = PieceTheme.typography.headingLSB,
color = PieceTheme.colors.black,
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp, bottom = 12.dp),
)

Spacer(modifier = Modifier.height(12.dp))

Text(
text = "서로의 빈 곳을 채우며 맞물리는 퍼즐처럼.\n서로의 가치관과 마음이 연결되는 순간을 만들어갑니다.",
text = stringResource(R.string.login_description),
style = PieceTheme.typography.bodySM,
color = PieceTheme.colors.dark3,
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 70.dp),
)

Spacer(modifier = Modifier.height(70.dp))

Image(
painter = painterResource(R.drawable.ic_puzzle1),
contentDescription = null,
Expand All @@ -129,34 +131,52 @@ fun LoginScreen(
PieceLoginButton(
label = stringResource(R.string.kakao_login),
imageId = R.drawable.ic_kakao_login,
onClick = {},
containerColor = Color(0xFFFFE812),
modifier = Modifier.fillMaxWidth()
onClick = loginKakao,
modifier = Modifier.fillMaxWidth(),
)

Spacer(modifier = Modifier.height(10.dp))

PieceLoginButton(
label = stringResource(R.string.google_login),
imageId = R.drawable.ic_google_login,
onClick = {},
containerColor = PieceTheme.colors.white,
border = BorderStroke(
width = 1.dp,
color = PieceTheme.colors.light1,
),
onClick = {},
modifier = Modifier
.fillMaxWidth()
.border(
width = 1.dp,
color = PieceTheme.colors.light1,
shape = RoundedCornerShape(8.dp)
),
.padding(vertical = 10.dp),
)
}
}

Spacer(modifier = Modifier.height(10.dp))
private fun loginKakao(context: Context) {
UserApiClient.instance.apply {
if (isKakaoTalkLoginAvailable(context)) {
loginWithKakaoAccount(context) { token, error ->
if (error != null) {
// Log.e("test", "로그인 실패", error)
} else if (token != null) {
// Log.i("test", "로그인 성공 ${token.accessToken}")
}
}
} else {
loginWithKakaoAccount(context) { token, error ->
if (error != null) {
// Log.e("test", "로그인 실패", error)
} else if (token != null) {
// Log.i("test", "로그인 성공 ${token.accessToken}")
}
}
}
}
}

@Preview
@Composable
fun PreviewAuthScreen() {
private fun PreviewAuthScreen() {
PieceTheme {
LoginScreen(
state = LoginState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class LoginViewModel @AssistedInject constructor(
) : MavericksViewModel<LoginState>(initialState) {
private val intents = Channel<LoginIntent>(BUFFERED)

private val _sideEffect = Channel<LoginSideEffect>(BUFFERED)
val sideEffect = _sideEffect.receiveAsFlow()
private val _sideEffects = Channel<LoginSideEffect>(BUFFERED)
val sideEffects = _sideEffects.receiveAsFlow()

init {
intents.receiveAsFlow()
Expand All @@ -43,10 +43,8 @@ class LoginViewModel @AssistedInject constructor(
}
}

private fun handleSideEffect(sideEffect: LoginSideEffect) {
when (sideEffect) {
else -> Unit
}
internal fun onSideEffect(sideEffect: LoginSideEffect) = viewModelScope.launch {
_sideEffects.send(sideEffect)
}

@AssistedFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.puzzle.auth.graph.login.contract

sealed class LoginSideEffect
sealed class LoginSideEffect {
data object LoginKakao : LoginSideEffect()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.puzzle.common.event.PieceEvent
import com.puzzle.common.ui.repeatOnStarted
import com.puzzle.designsystem.foundation.PieceTheme
import com.puzzle.navigation.MatchingGraph
import com.puzzle.navigation.NavigationEvent
Expand Down Expand Up @@ -42,7 +41,7 @@ class MainActivity : ComponentActivity() {
snackBarHostState = remember { SnackbarHostState() }

LaunchedEffect(Unit) {
repeatOnLifecycle(Lifecycle.State.STARTED) {
repeatOnStarted {
launch {
navigationHelper.navigationFlow.collect { event ->
handleNavigationEvent(
Expand Down

0 comments on commit b40ccda

Please sign in to comment.