From a82304920a95f7abe30af7867751d9e92e3c8a0c Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:23:58 +0900 Subject: [PATCH 01/28] =?UTF-8?q?[add]=20#4=20navigation,=20hilt-navigatio?= =?UTF-8?q?n=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++++ gradle/libs.versions.toml | 32 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0e65ecc..b636886 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -67,7 +67,11 @@ dependencies { // Hilt implementation(libs.hilt) kapt(libs.hilt.compiler) + implementation(libs.androidx.hilt.navigation) // Timber implementation(libs.timber) + + // Navigation + implementation(libs.androidx.navigation) } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5ebbd3c..cafff75 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,18 +1,20 @@ [versions] agp = "8.7.0-alpha08" -kotlin = "2.0.0" -coreKtx = "1.10.1" +kotlin = "2.0.10" +coreKtx = "1.13.1" junit = "4.13.2" -junitVersion = "1.1.5" -espressoCore = "3.5.1" -lifecycleRuntimeKtx = "2.6.1" -activityCompose = "1.8.0" -composeBom = "2024.04.01" -dagger-hilt = "2.50" +junitVersion = "1.2.1" +espressoCore = "3.6.1" +lifecycleRuntimeKtx = "2.8.6" +activityCompose = "1.9.3" +composeBom = "2024.10.00" +daggerHilt = "2.52" timber = "5.0.1" -compose-runtime = "1.5.0" -viewmodel-compose = "2.6.1" -kotlinx-coroutines = "1.5.2" +compose-runtime = "1.7.4" +viewmodel-compose = "2.8.6" +kotlinx-coroutines = "1.8.1" +navigation = "2.8.3" +navigationHilt = "1.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -29,16 +31,18 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3" } -hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "dagger-hilt" } -hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "dagger-hilt" } +hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "daggerHilt" } +hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "daggerHilt" } timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" } androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime", version.ref = "compose-runtime" } androidx-lifecycle = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "viewmodel-compose" } kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } +androidx-navigation = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation"} +androidx-hilt-navigation = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "navigationHilt"} [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "dagger-hilt" } +dagger-hilt = { id = "com.google.dagger.hilt.android", version.ref = "daggerHilt" } kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } \ No newline at end of file From 37bf7b2257c5aba725e08f70ca5cdaef0acae83a Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:25:47 +0900 Subject: [PATCH 02/28] =?UTF-8?q?[feat]=20#4=20HomeRoute,=20HomeScreen=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeRoute.kt | 8 ++++++++ .../and/presentation/ui/home/HomeScreen.kt | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt new file mode 100644 index 0000000..48ad387 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt @@ -0,0 +1,8 @@ +package org.sopt.and.presentation.ui.home + +import androidx.compose.runtime.Composable + +@Composable +fun HomeRoute() { + HomeScreen() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt new file mode 100644 index 0000000..5ba77d7 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -0,0 +1,19 @@ +package org.sopt.and.presentation.ui.home + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import org.sopt.and.ui.theme.ANDANDROIDTheme + +@Composable +fun HomeScreen() { + Text("Home Screen") +} + +@Preview(showBackground = true) +@Composable +fun HomePreview() { + ANDANDROIDTheme { + HomeScreen() + } +} \ No newline at end of file From 9e800080c8d731fb315a2b7a0b85092d9a23e9cf Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:26:20 +0900 Subject: [PATCH 03/28] =?UTF-8?q?[mod]=20#4=20LoginRoute,=20LoginScreen?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC(LoginActivity=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/auth/login/LoginActivity.kt | 249 ------------------ .../presentation/ui/auth/login/LoginRoute.kt | 88 +++++++ .../presentation/ui/auth/login/LoginScreen.kt | 136 ++++++++++ 3 files changed, 224 insertions(+), 249 deletions(-) delete mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginActivity.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginRoute.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginScreen.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginActivity.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginActivity.kt deleted file mode 100644 index 323165e..0000000 --- a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginActivity.kt +++ /dev/null @@ -1,249 +0,0 @@ -package org.sopt.and.presentation.ui.auth.login - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.activity.viewModels -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.ime -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.launch -import org.sopt.and.R -import org.sopt.and.presentation.ui.auth.register.RegisterActivity -import org.sopt.and.presentation.ui.auth.register.SocialLoginRow -import org.sopt.and.presentation.ui.component.TextWithHorizontalDivider -import org.sopt.and.presentation.ui.component.ThreeTextWithVerticalDivider -import org.sopt.and.presentation.ui.component.WaveAllButton -import org.sopt.and.presentation.ui.component.WaveAllTopBar -import org.sopt.and.presentation.ui.component.WaveTextField -import org.sopt.and.presentation.ui.component.WaveTextFieldWithShowAndHide -import org.sopt.and.presentation.ui.my.MyActivity -import org.sopt.and.ui.theme.ANDANDROIDTheme -import org.sopt.and.ui.theme.GrayBlack -import timber.log.Timber - -@AndroidEntryPoint -class LoginActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - val loginViewModel: LoginViewModel by viewModels() - - setContent { - ANDANDROIDTheme { - val loginState by loginViewModel.uiState.collectAsState() - val loginEffect = loginViewModel.uiEffect - - val snackBarHostState = remember { SnackbarHostState() } - val coroutineScope = rememberCoroutineScope() - - LaunchedEffect(loginEffect) { - loginEffect.collect { loginEffect -> - when (loginEffect) { - is LoginContract.LoginEffect.ShowSuccessSnackBar -> { - coroutineScope.launch { - // TODO SharedSnackBar 만들어서 액티비티 이동해도 SnackBar가 뜨도록 구현 - snackBarHostState.showSnackbar(loginEffect.successMessage) - } - } - - is LoginContract.LoginEffect.ShowFailSnackBar -> { - coroutineScope.launch { - snackBarHostState.showSnackbar(loginEffect.failMessage) - } - } - } - } - } - - LaunchedEffect(loginState.loginStatus) { - if (loginState.loginStatus == LoginContract.LoginStatus.Success) { - navigateToMyActivity(applicationContext) - } - } - - Scaffold( - modifier = Modifier.fillMaxSize() - ) { innerPadding -> - LoginScreen( - modifier = Modifier.padding(innerPadding), - email = loginState.email, - password = loginState.password, - showPassword = loginState.showPassword, - onEmailChange = { - loginViewModel.setEvent( - LoginContract.LoginEvent.EmailChanged(it) - ) - }, - onPasswordChange = { - loginViewModel.setEvent( - LoginContract.LoginEvent.PasswordChanged(it) - ) - }, - onPasswordVisibilityChange = { - loginViewModel.setEvent( - LoginContract.LoginEvent.PasswordVisibilityChanged - ) - }, - onLoginBtnClick = { - loginViewModel.setEvent( - LoginContract.LoginEvent.OnLoginBtnClicked( - successMessage = applicationContext.getString(R.string.login_success), - failMessage = applicationContext.getString(R.string.login_fail) - ) - ) - }, - onNavigateToRegisterBtnClick = { - navigateToRegisterActivity(applicationContext) - }, - snackBarHostState = snackBarHostState - ) - } - } - } - } -} - -@Composable -fun LoginScreen( - modifier: Modifier = Modifier, - email: String, - password: String, - showPassword: Boolean, - onEmailChange: (String) -> Unit, - onPasswordChange: (String) -> Unit, - onPasswordVisibilityChange: () -> Unit, - onLoginBtnClick: () -> Unit, - onNavigateToRegisterBtnClick: () -> Unit, - snackBarHostState: SnackbarHostState -) { - Box( - modifier = modifier - .fillMaxSize() - .background(GrayBlack) - .padding(horizontal = 15.dp), - ) { - Column( - verticalArrangement = Arrangement.Top, - modifier = modifier - .fillMaxSize(), - ) { - WaveAllTopBar( - title = stringResource(R.string.login_title), - position = Alignment.CenterStart, - icon = R.drawable.ic_arrow_back_btn_24, - onIconClick = { Timber.tag("버튼 클릭").d("작동 안함") } - ) - - Spacer(modifier = Modifier.height(30.dp)) - - WaveTextField( - placeholder = stringResource(R.string.login_id_hint), - value = email, - onValueChange = { onEmailChange(it) } - ) - - WaveTextFieldWithShowAndHide( - placeholder = stringResource(R.string.login_password_hint), - value = password, - onValueChange = { onPasswordChange(it) }, - showPassword = showPassword, - changePasswordVisibility = { onPasswordVisibilityChange() } - ) - - Spacer(modifier = Modifier.height(25.dp)) - - WaveAllButton( - buttonText = stringResource(R.string.login_button), - onClickButton = { onLoginBtnClick() } - ) - - Spacer(modifier = Modifier.height(25.dp)) - - ThreeTextWithVerticalDivider( - dividerLeftText = stringResource(R.string.login_find_id), - dividerCenterText = stringResource(R.string.login_find_password), - dividerRightText = stringResource(R.string.register), - onDividerRightTextClick = { onNavigateToRegisterBtnClick() } - ) - - TextWithHorizontalDivider( - modifier = Modifier.height(50.dp), - dividerText = stringResource(R.string.login_social_account) - ) - - SocialLoginRow() - } - - SnackbarHost( - hostState = snackBarHostState, - modifier = Modifier - .align(Alignment.BottomCenter) - .fillMaxWidth() - .padding(vertical = 15.dp) - .padding(WindowInsets.ime.asPaddingValues()) - ) - } -} - -private fun navigateToRegisterActivity(context: Context) { - val intent = Intent(context, RegisterActivity::class.java) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(intent) -} - -private fun navigateToMyActivity(context: Context) { - val intent = Intent(context, MyActivity::class.java) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(intent) -} - - -@Composable -fun LoginScreenPreview() { - LoginScreen( - email = "jieun@ac.kr", - password = "password", - showPassword = false, - onEmailChange = {}, - onPasswordChange = {}, - onPasswordVisibilityChange = {}, - onNavigateToRegisterBtnClick = {}, - onLoginBtnClick = {}, - snackBarHostState = SnackbarHostState() - ) -} - -@Preview(showBackground = true) -@Composable -fun PreviewLoginScreen() { - LoginScreenPreview() -} diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginRoute.kt new file mode 100644 index 0000000..49c90b4 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginRoute.kt @@ -0,0 +1,88 @@ +package org.sopt.and.presentation.ui.auth.login + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.hilt.navigation.compose.hiltViewModel +import kotlinx.coroutines.launch +import org.sopt.and.R + +@Composable +fun LoginRoute( + paddingValues: PaddingValues, + loginViewModel: LoginViewModel = hiltViewModel(), + navigateToRegister: () -> Unit, + navigateToHome: () -> Unit +) { + val loginState by loginViewModel.uiState.collectAsState() + val loginEffect = loginViewModel.uiEffect + + val snackBarHostState = remember { SnackbarHostState() } + val coroutineScope = rememberCoroutineScope() + val context = LocalContext.current + + LaunchedEffect(loginEffect) { + loginEffect.collect { loginEffect -> + when (loginEffect) { + is LoginContract.LoginEffect.ShowSuccessSnackBar -> { + coroutineScope.launch { + // TODO SharedSnackBar 만들어서 액티비티 이동해도 SnackBar가 뜨도록 구현 + snackBarHostState.showSnackbar(loginEffect.successMessage) + } + } + + is LoginContract.LoginEffect.ShowFailSnackBar -> { + coroutineScope.launch { + snackBarHostState.showSnackbar(loginEffect.failMessage) + } + } + } + } + } + + LaunchedEffect(loginState.loginStatus) { + if (loginState.loginStatus == LoginContract.LoginStatus.Success) { + navigateToHome() + } + } + + LoginScreen( + modifier = Modifier.padding(paddingValues), + email = loginState.email, + password = loginState.password, + showPassword = loginState.showPassword, + onEmailChange = { + loginViewModel.setEvent( + LoginContract.LoginEvent.EmailChanged(it) + ) + }, + onPasswordChange = { + loginViewModel.setEvent( + LoginContract.LoginEvent.PasswordChanged(it) + ) + }, + onPasswordVisibilityChange = { + loginViewModel.setEvent( + LoginContract.LoginEvent.PasswordVisibilityChanged + ) + }, + onLoginBtnClick = { + loginViewModel.setEvent( + LoginContract.LoginEvent.OnLoginBtnClicked( + successMessage = context.getString(R.string.login_success), + failMessage = context.getString(R.string.login_fail) + ) + ) + }, + onNavigateToRegisterBtnClick = navigateToRegister, + snackBarHostState = snackBarHostState + ) +} diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginScreen.kt new file mode 100644 index 0000000..05ab750 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginScreen.kt @@ -0,0 +1,136 @@ +package org.sopt.and.presentation.ui.auth.login + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.ime +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.sopt.and.R +import org.sopt.and.presentation.ui.auth.register.SocialLoginRow +import org.sopt.and.presentation.ui.component.TextWithHorizontalDivider +import org.sopt.and.presentation.ui.component.ThreeTextWithVerticalDivider +import org.sopt.and.presentation.ui.component.WaveAllButton +import org.sopt.and.presentation.ui.component.WaveAllTopBar +import org.sopt.and.presentation.ui.component.WaveTextField +import org.sopt.and.presentation.ui.component.WaveTextFieldWithShowAndHide +import org.sopt.and.ui.theme.GrayBlack +import timber.log.Timber + +@Composable +fun LoginScreen( + modifier: Modifier = Modifier, + email: String, + password: String, + showPassword: Boolean, + onEmailChange: (String) -> Unit, + onPasswordChange: (String) -> Unit, + onPasswordVisibilityChange: () -> Unit, + onLoginBtnClick: () -> Unit, + onNavigateToRegisterBtnClick: () -> Unit, + snackBarHostState: SnackbarHostState +) { + Box( + modifier = modifier + .fillMaxSize() + .background(GrayBlack), + ) { + Column( + verticalArrangement = Arrangement.Top, + modifier = Modifier + .padding(horizontal = 15.dp) + .fillMaxSize(), + ) { + WaveAllTopBar( + title = stringResource(R.string.login_title), + position = Alignment.CenterStart, + icon = R.drawable.ic_arrow_back_btn_24, + onIconClick = { Timber.tag("버튼 클릭").d("작동 안함") } + ) + + Spacer(modifier = Modifier.height(30.dp)) + + WaveTextField( + placeholder = stringResource(R.string.login_id_hint), + value = email, + onValueChange = { onEmailChange(it) } + ) + + WaveTextFieldWithShowAndHide( + placeholder = stringResource(R.string.login_password_hint), + value = password, + onValueChange = { onPasswordChange(it) }, + showPassword = showPassword, + changePasswordVisibility = { onPasswordVisibilityChange() } + ) + + Spacer(modifier = Modifier.height(25.dp)) + + WaveAllButton( + buttonText = stringResource(R.string.login_button), + onClickButton = { onLoginBtnClick() } + ) + + Spacer(modifier = Modifier.height(25.dp)) + + ThreeTextWithVerticalDivider( + dividerLeftText = stringResource(R.string.login_find_id), + dividerCenterText = stringResource(R.string.login_find_password), + dividerRightText = stringResource(R.string.register), + onDividerRightTextClick = { onNavigateToRegisterBtnClick() } + ) + + TextWithHorizontalDivider( + modifier = Modifier.height(50.dp), + dividerText = stringResource(R.string.login_social_account) + ) + + SocialLoginRow() + } + + SnackbarHost( + hostState = snackBarHostState, + modifier = Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .padding(WindowInsets.ime.asPaddingValues()) + .padding(vertical = 15.dp) + ) + } +} + +@Composable +fun LoginScreenPreview() { + LoginScreen( + modifier = Modifier.padding(15.dp), + email = "jieun@ac.kr", + password = "password", + showPassword = false, + onEmailChange = {}, + onPasswordChange = {}, + onPasswordVisibilityChange = {}, + onNavigateToRegisterBtnClick = {}, + onLoginBtnClick = {}, + snackBarHostState = SnackbarHostState() + ) +} + +@Preview(showBackground = true) +@Composable +fun PreviewLoginScreen() { + LoginScreenPreview() +} From 9e77f91649c4aeade709676da39b3b3646b7662e Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:26:49 +0900 Subject: [PATCH 04/28] =?UTF-8?q?[mod]=20#4=20RegisterRoute,=20RegisterScr?= =?UTF-8?q?een=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC(RegisterActivity=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/auth/register/RegisterRoute.kt | 75 ++++++++++++++++++ ...{RegisterActivity.kt => RegisterScreen.kt} | 79 ------------------- 2 files changed, 75 insertions(+), 79 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterRoute.kt rename app/src/main/java/org/sopt/and/presentation/ui/auth/register/{RegisterActivity.kt => RegisterScreen.kt} (66%) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterRoute.kt new file mode 100644 index 0000000..2644887 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterRoute.kt @@ -0,0 +1,75 @@ +package org.sopt.and.presentation.ui.auth.register + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.hilt.navigation.compose.hiltViewModel +import org.sopt.and.R +import org.sopt.and.util.showToast + +@Composable +fun RegisterRoute( + registerViewModel: RegisterViewModel = hiltViewModel(), + navigateToLogin: () -> Unit +) { + val registerState by registerViewModel.uiState.collectAsState() + val registerEffect = registerViewModel.uiEffect + + val context = LocalContext.current + + LaunchedEffect(registerEffect) { + registerEffect.collect { registerEffect -> + when (registerEffect) { + is RegisterContract.RegisterEffect.ShowToast -> { + context.showToast(registerEffect.message) + } + } + } + } + + LaunchedEffect(registerState.registerStatus) { + if (registerState.registerStatus == RegisterContract.RegisterStatus.Success) { + navigateToLogin() + } + } + + Scaffold( + modifier = Modifier.fillMaxSize() + ) { innerPadding -> + RegisterScreen( + modifier = Modifier.padding(innerPadding), + email = registerState.email, + password = registerState.password, + showPassword = registerState.showPassword, + onEmailChange = { + registerViewModel.setEvent( + RegisterContract.RegisterEvent.EmailChanged(it) + ) + }, + onPasswordChange = { + registerViewModel.setEvent( + RegisterContract.RegisterEvent.PasswordChanged(it) + ) + }, + onPasswordVisibilityChange = { + registerViewModel.setEvent( + RegisterContract.RegisterEvent.PasswordVisibilityChanged + ) + }, + onBackBtnClick = { navigateToLogin() }, + onRegisterBtnClick = { + registerViewModel.setEvent( + RegisterContract.RegisterEvent.OnRegisterBtnClicked( + message = context.getString(R.string.register_toast), + ) + ) + }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterActivity.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterScreen.kt similarity index 66% rename from app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterActivity.kt rename to app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterScreen.kt index b11b541..63dc834 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterActivity.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterScreen.kt @@ -1,10 +1,5 @@ package org.sopt.and.presentation.ui.auth.register -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.activity.viewModels import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -16,12 +11,8 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Icon -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector @@ -31,84 +22,14 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import dagger.hilt.android.AndroidEntryPoint import org.sopt.and.R import org.sopt.and.presentation.ui.component.TextWithHorizontalDivider import org.sopt.and.presentation.ui.component.WaveAllTopBar import org.sopt.and.presentation.ui.component.WaveTextField import org.sopt.and.presentation.ui.component.WaveTextFieldWithShowAndHide -import org.sopt.and.ui.theme.ANDANDROIDTheme import org.sopt.and.ui.theme.Gray100 import org.sopt.and.ui.theme.GrayBlack import org.sopt.and.ui.theme.White -import org.sopt.and.util.showToast - -@AndroidEntryPoint -class RegisterActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - val registerViewModel: RegisterViewModel by viewModels() - - setContent { - ANDANDROIDTheme { - val registerState by registerViewModel.uiState.collectAsState() - val registerEffect = registerViewModel.uiEffect - - LaunchedEffect(registerEffect) { - registerEffect.collect { registerEffect -> - when (registerEffect) { - is RegisterContract.RegisterEffect.ShowToast -> { - applicationContext.showToast(registerEffect.message) - } - } - } - } - - LaunchedEffect(registerState.registerStatus) { - if (registerState.registerStatus == RegisterContract.RegisterStatus.Success) { - finish() - } - } - - Scaffold( - modifier = Modifier.fillMaxSize() - ) { innerPadding -> - RegisterScreen( - modifier = Modifier.padding(innerPadding), - email = registerState.email, - password = registerState.password, - showPassword = registerState.showPassword, - onEmailChange = { - registerViewModel.setEvent( - RegisterContract.RegisterEvent.EmailChanged(it) - ) - }, - onPasswordChange = { - registerViewModel.setEvent( - RegisterContract.RegisterEvent.PasswordChanged(it) - ) - }, - onPasswordVisibilityChange = { - registerViewModel.setEvent( - RegisterContract.RegisterEvent.PasswordVisibilityChanged - ) - }, - onBackBtnClick = { finish() }, - onRegisterBtnClick = { - registerViewModel.setEvent( - RegisterContract.RegisterEvent.OnRegisterBtnClicked( - message = applicationContext.getString(R.string.register_toast), - ) - ) - }, - ) - } - } - } - } -} @Composable fun RegisterScreen( From 6821a34f0450ab839dae28800b05e3b40c1229c8 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:28:38 +0900 Subject: [PATCH 05/28] =?UTF-8?q?[mod]=20#4=20MyRoute,=20MyScreen=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC(MyActivity=20=EC=82=AD=EC=A0=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/presentation/ui/my/MyRoute.kt | 8 ++++++++ .../ui/my/{MyActivity.kt => MyScreen.kt} | 16 ---------------- 2 files changed, 8 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt rename app/src/main/java/org/sopt/and/presentation/ui/my/{MyActivity.kt => MyScreen.kt} (91%) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt new file mode 100644 index 0000000..512dfa1 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt @@ -0,0 +1,8 @@ +package org.sopt.and.presentation.ui.my + +import androidx.compose.runtime.Composable + +@Composable +fun MyRoute() { + MyScreen() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyActivity.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt similarity index 91% rename from app/src/main/java/org/sopt/and/presentation/ui/my/MyActivity.kt rename to app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt index c3314f8..94d03d6 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyActivity.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt @@ -1,9 +1,5 @@ package org.sopt.and.presentation.ui.my -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -30,18 +26,6 @@ import org.sopt.and.ui.theme.Gray300 import org.sopt.and.ui.theme.GrayBlack import org.sopt.and.ui.theme.White -class MyActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - ANDANDROIDTheme { - MyScreen() - } - } - } -} - @Composable fun MyScreen() { Column( From 1146a8bfcfca171c3d016fc3177d3699e9ac2365 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:28:55 +0900 Subject: [PATCH 06/28] =?UTF-8?q?[feat]=20#4=20SearchRoute,=20SearchScreen?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/search/SearchRoute.kt | 8 ++++++++ .../presentation/ui/search/SearchScreen.kt | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt new file mode 100644 index 0000000..792668f --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt @@ -0,0 +1,8 @@ +package org.sopt.and.presentation.ui.search + +import androidx.compose.runtime.Composable + +@Composable +fun SearchRoute() { + SearchScreen() +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt new file mode 100644 index 0000000..5b32526 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt @@ -0,0 +1,19 @@ +package org.sopt.and.presentation.ui.search + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import org.sopt.and.ui.theme.ANDANDROIDTheme + +@Composable +fun SearchScreen() { + Text("Search Screen") +} + +@Preview(showBackground = true) +@Composable +fun HomePreview() { + ANDANDROIDTheme { + SearchScreen() + } +} \ No newline at end of file From 52422d5f00775120537313b2dafa67cd50dce58a Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:31:21 +0900 Subject: [PATCH 07/28] =?UTF-8?q?[feat]=20#4=20WaveBottomNavigation=20type?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/WaveBottomNavigationRoute.kt | 9 ++++ .../type/WaveBottomNavigationType.kt | 42 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/model/WaveBottomNavigationRoute.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/type/WaveBottomNavigationType.kt diff --git a/app/src/main/java/org/sopt/and/presentation/model/WaveBottomNavigationRoute.kt b/app/src/main/java/org/sopt/and/presentation/model/WaveBottomNavigationRoute.kt new file mode 100644 index 0000000..49de036 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/model/WaveBottomNavigationRoute.kt @@ -0,0 +1,9 @@ +package org.sopt.and.presentation.model + +sealed interface Route + +sealed interface WaveBottomNavigationRoute : Route { + data object HOME : WaveBottomNavigationRoute + data object SEARCH : WaveBottomNavigationRoute + data object MY : WaveBottomNavigationRoute +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/type/WaveBottomNavigationType.kt b/app/src/main/java/org/sopt/and/presentation/type/WaveBottomNavigationType.kt new file mode 100644 index 0000000..bbf60dc --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/type/WaveBottomNavigationType.kt @@ -0,0 +1,42 @@ +package org.sopt.and.presentation.type + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import org.sopt.and.R +import org.sopt.and.presentation.model.Route +import org.sopt.and.presentation.model.WaveBottomNavigationRoute + +enum class WaveBottomNavigationType( + @DrawableRes val bnvIcon: Int, + @StringRes val bnvText: Int, + val route: WaveBottomNavigationRoute +) { + HOME( + bnvIcon = R.drawable.ic_bnv_home_32, + bnvText = R.string.bnv_home, + route = WaveBottomNavigationRoute.HOME + ), + SEARCH( + bnvIcon = R.drawable.ic_bnv_search_32, + bnvText = R.string.bnv_search, + route = WaveBottomNavigationRoute.SEARCH + ), + MY( + bnvIcon = R.drawable.ic_bnv_my_32, + bnvText = R.string.bnv_my, + route = WaveBottomNavigationRoute.MY + ); + + companion object { + @Composable + fun find(bnvRoute: @Composable (WaveBottomNavigationRoute) -> Boolean): WaveBottomNavigationType? { + return entries.firstOrNull { bnvRoute(it.route) } + } + + @Composable + fun contains(route: @Composable (Route) -> Boolean): Boolean { + return entries.map { it.route }.any { route(it) } + } + } +} \ No newline at end of file From 128d56f964a8f0d72e541a97a222460cabcbc8cc Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:32:07 +0900 Subject: [PATCH 08/28] =?UTF-8?q?[feat]=20#4=20Custom=20component=20-=20Wa?= =?UTF-8?q?veBottomNavigation=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/navigator/WaveBottomNavigation.kt | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveBottomNavigation.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveBottomNavigation.kt b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveBottomNavigation.kt new file mode 100644 index 0000000..3393c75 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveBottomNavigation.kt @@ -0,0 +1,104 @@ +package org.sopt.and.presentation.ui.navigator + +import android.content.Context +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.sopt.and.presentation.type.WaveBottomNavigationType +import org.sopt.and.ui.theme.ANDANDROIDTheme +import org.sopt.and.ui.theme.Gray100 +import org.sopt.and.ui.theme.GrayBlack +import org.sopt.and.ui.theme.White + +@Composable +fun WaveBottomNavigation( + modifier: Modifier = Modifier, + isVisible: Boolean = false, + context: Context = LocalContext.current, + bottomNaviItems: List, + currentBottomNaviItem: WaveBottomNavigationType?, + onClickBottomNavItem: (WaveBottomNavigationType) -> Unit, +) { + AnimatedVisibility(visible = isVisible) { + Row( + modifier = modifier + .background(GrayBlack) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + bottomNaviItems.forEach { item -> + WaveBottomNavigationItem( + modifier = Modifier.weight(1f), + context = context, + waveBottomNavigationType = item, + isSelected = (currentBottomNaviItem == item), + onClickItem = { onClickBottomNavItem(item) }, + ) + } + } + } +} + +@Composable +fun WaveBottomNavigationItem( + context: Context, + waveBottomNavigationType: WaveBottomNavigationType, + isSelected: Boolean, + onClickItem: () -> Unit, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .clickable(onClick = onClickItem) + .padding(vertical = 8.dp) + .background(if (isSelected) GrayBlack else Color.Transparent), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + // svg 추출이 안돼서 png로 했음! 그래서 vectorResource 대신 painterResource 사용함! + painter = painterResource(waveBottomNavigationType.bnvIcon), + contentDescription = context.getString(waveBottomNavigationType.bnvText), + tint = if (isSelected) White else Gray100 + ) + + Spacer(Modifier.height(4.dp)) + + Text( + text = context.getString(waveBottomNavigationType.bnvText), + fontSize = 16.sp, + color = if (isSelected) White else Gray100 + ) + } +} + +@Preview +@Composable +fun WaveBottomNavigationPreview() { + ANDANDROIDTheme { + WaveBottomNavigation( + bottomNaviItems = WaveBottomNavigationType.entries.toList(), + currentBottomNaviItem = WaveBottomNavigationType.HOME, + onClickBottomNavItem = { } + ) + } +} \ No newline at end of file From ba187d0a3f32330a28fbb3eac53846654467d11c Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:32:36 +0900 Subject: [PATCH 09/28] =?UTF-8?q?[del]=20#4=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20activity=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 158f2c8..81de0ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,23 +14,13 @@ android:theme="@style/Theme.ANDANDROID" tools:targetApi="31"> + android:name=".MainActivity" + android:exported="true"> - - - \ No newline at end of file From 28c9293a7d8939455eb7e90a820198a85ae98c4f Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:52:24 +0900 Subject: [PATCH 10/28] =?UTF-8?q?[feat]=20#4=20HomeNavigator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeNavigator.kt | 23 +++++++++++++++++++ .../and/presentation/ui/home/HomeRoute.kt | 9 ++++++-- .../and/presentation/ui/home/HomeScreen.kt | 20 ++++++++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/home/HomeNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeNavigator.kt new file mode 100644 index 0000000..0d1226e --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeNavigator.kt @@ -0,0 +1,23 @@ +package org.sopt.and.presentation.ui.home + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import org.sopt.and.presentation.model.WaveBottomNavigationRoute + +fun NavController.homeNavigation(navOptions: NavOptions) { + navigate( + route = WaveBottomNavigationRoute.HOME::class.simpleName.orEmpty(), + navOptions = navOptions + ) +} + +fun NavGraphBuilder.homeNavGraph( + paddingValues: PaddingValues +) { + composable(route = WaveBottomNavigationRoute.HOME::class.simpleName.orEmpty()) { + HomeRoute(paddingValues = paddingValues) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt index 48ad387..cf1396f 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt @@ -1,8 +1,13 @@ package org.sopt.and.presentation.ui.home +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier @Composable -fun HomeRoute() { - HomeScreen() +fun HomeRoute( + paddingValues: PaddingValues +) { + HomeScreen(modifier = Modifier.padding(paddingValues)) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index 5ba77d7..f4b055a 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -1,13 +1,29 @@ package org.sopt.and.presentation.ui.home +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import org.sopt.and.ui.theme.ANDANDROIDTheme @Composable -fun HomeScreen() { - Text("Home Screen") +fun HomeScreen( + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .padding(horizontal = 15.dp) + .fillMaxSize() + .verticalScroll(rememberScrollState()) + ) { + Text("Home Screen") + } } @Preview(showBackground = true) From c35d96f9494281af9fdbdf4a9647136bc6f76e6d Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Wed, 23 Oct 2024 23:53:31 +0900 Subject: [PATCH 11/28] =?UTF-8?q?[feat]=20#4=20LoginNavigator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/auth/login/LoginNavigator.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginNavigator.kt new file mode 100644 index 0000000..f2bd1c2 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginNavigator.kt @@ -0,0 +1,34 @@ +package org.sopt.and.presentation.ui.auth.login + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable + +fun NavController.loginNavigation() { + navigate( + route = LoginRoute.LOGIN_ROUTE + ) { + popUpTo(graph.id) { + inclusive = true + } + } +} + +fun NavGraphBuilder.loginGraph( + paddingValues: PaddingValues, + navigateToRegister: () -> Unit, + navigateToHome: () -> Unit +) { + composable(route = LoginRoute.LOGIN_ROUTE) { + LoginRoute( + paddingValues = paddingValues, + navigateToRegister = navigateToRegister, + navigateToHome = navigateToHome + ) + } +} + +object LoginRoute { + const val LOGIN_ROUTE = "login" +} \ No newline at end of file From bfde2c87aacd3e3fbfc07b80d9eb814dca5e8fe5 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:02:24 +0900 Subject: [PATCH 12/28] =?UTF-8?q?[feat]=20#4=20RegisterNavigator=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/auth/register/RegisterNavigator.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterNavigator.kt new file mode 100644 index 0000000..fbe8349 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/register/RegisterNavigator.kt @@ -0,0 +1,27 @@ +package org.sopt.and.presentation.ui.auth.register + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable + +fun NavController.registerNavigation() { + navigate( + route = RegisterRoute.REGISTER_ROUTE + ) +} + +fun NavGraphBuilder.registerGraph( + navigateToLogin: () -> Unit +) { + composable(route = RegisterRoute.REGISTER_ROUTE) { + RegisterRoute( + navigateToLogin = { + navigateToLogin() + } + ) + } +} + +object RegisterRoute { + const val REGISTER_ROUTE = "register" +} \ No newline at end of file From 44130f21d83bb3a260f7b9a4df690841e02f75b8 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:02:43 +0900 Subject: [PATCH 13/28] =?UTF-8?q?[feat]=20#4=20SearchNavigator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/search/SearchNavigator.kt | 23 +++++++++++++++++++ .../and/presentation/ui/search/SearchRoute.kt | 9 ++++++-- .../presentation/ui/search/SearchScreen.kt | 20 ++++++++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/search/SearchNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchNavigator.kt new file mode 100644 index 0000000..cc01519 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchNavigator.kt @@ -0,0 +1,23 @@ +package org.sopt.and.presentation.ui.search + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import org.sopt.and.presentation.model.WaveBottomNavigationRoute + +fun NavController.searchNavigation(navOptions: NavOptions) { + navigate( + route = WaveBottomNavigationRoute.SEARCH::class.simpleName.orEmpty(), + navOptions = navOptions + ) +} + +fun NavGraphBuilder.searchNavGraph( + paddingValues: PaddingValues +) { + composable(route = WaveBottomNavigationRoute.SEARCH::class.simpleName.orEmpty()) { + SearchRoute(paddingValues = paddingValues) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt index 792668f..7385039 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchRoute.kt @@ -1,8 +1,13 @@ package org.sopt.and.presentation.ui.search +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier @Composable -fun SearchRoute() { - SearchScreen() +fun SearchRoute( + paddingValues: PaddingValues +) { + SearchScreen(modifier = Modifier.padding(paddingValues)) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt index 5b32526..75a0f28 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/search/SearchScreen.kt @@ -1,13 +1,29 @@ package org.sopt.and.presentation.ui.search +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import org.sopt.and.ui.theme.ANDANDROIDTheme +import org.sopt.and.ui.theme.GrayBlack @Composable -fun SearchScreen() { - Text("Search Screen") +fun SearchScreen( + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .fillMaxSize() + .background(GrayBlack) + .padding(horizontal = 15.dp) + ) { + Text("Search Screen") + } } @Preview(showBackground = true) From 577a152e4573e987f6de4065594a4546a3eca186 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:03:30 +0900 Subject: [PATCH 14/28] =?UTF-8?q?[feat]=20#4=20MyNavigator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/my/MyNavigator.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/my/MyNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyNavigator.kt new file mode 100644 index 0000000..b17b6a4 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyNavigator.kt @@ -0,0 +1,23 @@ +package org.sopt.and.presentation.ui.my + +import androidx.compose.foundation.layout.PaddingValues +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import org.sopt.and.presentation.model.WaveBottomNavigationRoute + +fun NavController.myNavigation(navOptions: NavOptions) { + navigate( + route = WaveBottomNavigationRoute.MY::class.simpleName.orEmpty(), + navOptions = navOptions + ) +} + +fun NavGraphBuilder.myNavGraph( + paddingValues: PaddingValues +) { + composable(route = WaveBottomNavigationRoute.MY::class.simpleName.orEmpty()) { + MyRoute(paddingValues = paddingValues) + } +} \ No newline at end of file From eca029ed258087fe55d3d10e351399fd3bd17a3c Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:15:43 +0900 Subject: [PATCH 15/28] =?UTF-8?q?[mod]=20#4=20MyScreen=20Scaffold=20paddin?= =?UTF-8?q?g=20=EC=A0=81=EC=9A=A9=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/and/presentation/ui/my/MyRoute.kt | 9 ++++-- .../sopt/and/presentation/ui/my/MyScreen.kt | 28 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt index 512dfa1..a37a8e5 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt @@ -1,8 +1,13 @@ package org.sopt.and.presentation.ui.my +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier @Composable -fun MyRoute() { - MyScreen() +fun MyRoute( + paddingValues: PaddingValues +) { + MyScreen(modifier = Modifier.padding(paddingValues)) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt index 94d03d6..8699cac 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Row 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.material3.Icon @@ -27,9 +28,11 @@ import org.sopt.and.ui.theme.GrayBlack import org.sopt.and.ui.theme.White @Composable -fun MyScreen() { +fun MyScreen( + modifier: Modifier = Modifier +) { Column( - modifier = Modifier + modifier = modifier .fillMaxSize() .background(GrayBlack) ) { @@ -37,21 +40,28 @@ fun MyScreen() { modifier = Modifier .fillMaxWidth() .background(Gray300) + .padding(horizontal = 15.dp, vertical = 20.dp) ) { MyProfile(userEmail = "@.com") + + Spacer(modifier = Modifier.height(8.dp)) + MyPurchaseBox(information = stringResource(R.string.my_purchase_event)) + + Spacer(modifier = Modifier.height(8.dp)) + MyPurchaseBox(information = stringResource(R.string.my_purchase_ticket)) } Column( modifier = Modifier .fillMaxWidth() - .background(GrayBlack) ) { MyListBox( title = stringResource(R.string.my_view_history), description = stringResource(R.string.my_view_history_none) ) + MyListBox( title = stringResource(R.string.my_interest_program), description = stringResource(R.string.my_interest_program_none) @@ -64,8 +74,7 @@ fun MyScreen() { fun MyProfile(userEmail: String) { Row( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 15.dp, vertical = 20.dp), + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { Icon( @@ -74,13 +83,16 @@ fun MyProfile(userEmail: String) { tint = White, modifier = Modifier.size(44.dp) ) + Text( text = stringResource(R.string.my_nickname, userEmail), modifier = Modifier .padding(start = 8.dp), color = White ) + Spacer(modifier = Modifier.weight(1f)) + Icon( painter = painterResource(R.drawable.ic_nofification_24), contentDescription = null, @@ -89,6 +101,7 @@ fun MyProfile(userEmail: String) { .clickable { } .padding(8.dp) ) + Icon( painter = painterResource(R.drawable.ic_support_24), contentDescription = null, @@ -105,13 +118,13 @@ fun MyPurchaseBox(information: String) { Column( modifier = Modifier .fillMaxWidth() - .padding(15.dp) ) { Text( text = information, color = Gray100, fontSize = 16.sp ) + Row( modifier = Modifier .clickable { } @@ -121,6 +134,7 @@ fun MyPurchaseBox(information: String) { color = White, fontSize = 16.sp ) + Icon( painter = painterResource(R.drawable.ic_arrow_right_btn_24), contentDescription = null, @@ -142,6 +156,7 @@ fun MyListBox(title: String, description: String) { fontSize = 20.sp, color = White ) + Icon( painter = painterResource(R.drawable.ic_block_44), contentDescription = null, @@ -150,6 +165,7 @@ fun MyListBox(title: String, description: String) { .padding(vertical = 30.dp), tint = Gray100 ) + Text( text = description, fontSize = 16.sp, From 478ecbb3804d9a7e5b9745c3ef7df1054322a0de Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:16:30 +0900 Subject: [PATCH 16/28] =?UTF-8?q?[chore]=20#4=20MainActivity=EA=B0=80=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=ED=95=9C=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../and/presentation/ui/main/MainActivity.kt | 47 ------------------- 2 files changed, 1 insertion(+), 48 deletions(-) delete mode 100644 app/src/main/java/org/sopt/and/presentation/ui/main/MainActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 81de0ce..a0b933e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,7 @@ android:theme="@style/Theme.ANDANDROID" tools:targetApi="31"> diff --git a/app/src/main/java/org/sopt/and/presentation/ui/main/MainActivity.kt b/app/src/main/java/org/sopt/and/presentation/ui/main/MainActivity.kt deleted file mode 100644 index 2d16160..0000000 --- a/app/src/main/java/org/sopt/and/presentation/ui/main/MainActivity.kt +++ /dev/null @@ -1,47 +0,0 @@ -package org.sopt.and - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import org.sopt.and.ui.theme.ANDANDROIDTheme - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - ANDANDROIDTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - Greeting( - name = "Android", - modifier = Modifier.padding(innerPadding) - ) - } - } - } - } -} - -@Composable -fun Greeting(name: String, modifier: Modifier = Modifier) { - Text( - text = "Hello $name!", - modifier = modifier - ) -} - -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - ANDANDROIDTheme { - Greeting("Android") - } -} \ No newline at end of file From f03a04f6be91c62928b764bd54c5ee5324cf084b Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:18:36 +0900 Subject: [PATCH 17/28] =?UTF-8?q?[feat]=20#4=20WaveNavigator(NavHostContro?= =?UTF-8?q?ller)=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/navigator/WaveNavigator.kt | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavigator.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavigator.kt b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavigator.kt new file mode 100644 index 0000000..c893d0b --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavigator.kt @@ -0,0 +1,80 @@ +package org.sopt.and.presentation.ui.navigator + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.navigation.NavDestination +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController +import androidx.navigation.NavOptions +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navOptions +import org.sopt.and.presentation.model.WaveBottomNavigationRoute +import org.sopt.and.presentation.type.WaveBottomNavigationType +import org.sopt.and.presentation.ui.auth.login.LoginRoute +import org.sopt.and.presentation.ui.auth.login.loginNavigation +import org.sopt.and.presentation.ui.auth.register.registerNavigation +import org.sopt.and.presentation.ui.home.homeNavigation +import org.sopt.and.presentation.ui.my.myNavigation +import org.sopt.and.presentation.ui.search.searchNavigation + +class WaveNavigator( + val navHostController: NavHostController +) { + private val currentDestination: NavDestination? + @Composable get() = navHostController.currentBackStackEntryAsState().value?.destination + + val startDestination = LoginRoute.LOGIN_ROUTE + + val currentWaveBottomNavigation: WaveBottomNavigationType? + @Composable get() = WaveBottomNavigationType.find { waveBottomNavigationRoute -> + currentDestination?.route == waveBottomNavigationRoute::class.simpleName + } + + fun navigateToLogin() { + navHostController.loginNavigation() + } + + fun navigateToRegister() { + navHostController.registerNavigation() + } + + fun navigateToWaveBottomNavigation(waveBottomNavigationType: WaveBottomNavigationType) { + navOptions { + popUpTo(WaveBottomNavigationRoute.HOME::class.simpleName.orEmpty()) { + saveState = true + } + launchSingleTop = true + restoreState = true + }.let { navOptions -> + when (waveBottomNavigationType) { + WaveBottomNavigationType.HOME -> navHostController.homeNavigation(navOptions) + WaveBottomNavigationType.SEARCH -> navHostController.searchNavigation(navOptions) + WaveBottomNavigationType.MY -> navHostController.myNavigation(navOptions) + } + } + } + + fun navigateToHome(navOptions: NavOptions? = null) { + navHostController.homeNavigation( + navOptions ?: navOptions { + popUpTo(navHostController.graph.findStartDestination().id) { + inclusive = true + } + launchSingleTop = true + } + ) + } + + @Composable + fun showBottomNavigation(): Boolean = WaveBottomNavigationType.contains { + currentDestination?.route == it::class.simpleName + } +} + +@Composable +fun rememberWaveNavigator( + navHostController: NavHostController = rememberNavController() +): WaveNavigator = remember(navHostController) { + WaveNavigator(navHostController = navHostController) +} \ No newline at end of file From d7ea52b73d63a56d0eaa9f6c6d1160630a7d7838 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:19:05 +0900 Subject: [PATCH 18/28] =?UTF-8?q?[feat]=20#4=20WaveNavHost=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/WaveNavHost.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavHost.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavHost.kt b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavHost.kt new file mode 100644 index 0000000..f6bc19c --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/navigator/WaveNavHost.kt @@ -0,0 +1,48 @@ +package org.sopt.and.presentation.ui.navigator + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.navigation.compose.NavHost +import org.sopt.and.presentation.ui.auth.login.loginGraph +import org.sopt.and.presentation.ui.auth.register.registerGraph +import org.sopt.and.presentation.ui.home.homeNavGraph +import org.sopt.and.presentation.ui.my.myNavGraph +import org.sopt.and.presentation.ui.search.searchNavGraph + +@Composable +fun WaveNavHost( + paddingValues: PaddingValues, + modifier: Modifier = Modifier, + navigator: WaveNavigator, +) { + Box( + modifier = modifier + .fillMaxSize() + .background(Color.White) + ) { + NavHost( + navController = navigator.navHostController, + startDestination = navigator.startDestination + ) { + loginGraph( + paddingValues = paddingValues, + navigateToRegister = navigator::navigateToRegister, + navigateToHome = navigator::navigateToHome + ) + + registerGraph(navigateToLogin = navigator::navigateToLogin) + + homeNavGraph(paddingValues = paddingValues) + + searchNavGraph(paddingValues = paddingValues) + + myNavGraph(paddingValues = paddingValues) + + } + } +} \ No newline at end of file From a6d8d2b1d01ae32cd091ff171a36ad733b1fde9e Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:19:34 +0900 Subject: [PATCH 19/28] =?UTF-8?q?[feat]=20#4=20MainActivity,=20MainScreen?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/and/presentation/ui/MainActivity.kt | 26 +++++++++++ .../sopt/and/presentation/ui/MainScreen.kt | 44 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/MainActivity.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/MainScreen.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/MainActivity.kt b/app/src/main/java/org/sopt/and/presentation/ui/MainActivity.kt new file mode 100644 index 0000000..a790d26 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/MainActivity.kt @@ -0,0 +1,26 @@ +package org.sopt.and.presentation.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import dagger.hilt.android.AndroidEntryPoint +import org.sopt.and.presentation.ui.navigator.WaveNavigator +import org.sopt.and.presentation.ui.navigator.rememberWaveNavigator +import org.sopt.and.ui.theme.ANDANDROIDTheme + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + enableEdgeToEdge() + setContent { + val navigator: WaveNavigator = rememberWaveNavigator() + + ANDANDROIDTheme { + MainScreen(navigator = navigator) + } + } + } +} diff --git a/app/src/main/java/org/sopt/and/presentation/ui/MainScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/MainScreen.kt new file mode 100644 index 0000000..04d4e0f --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/MainScreen.kt @@ -0,0 +1,44 @@ +package org.sopt.and.presentation.ui + +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import org.sopt.and.presentation.type.WaveBottomNavigationType +import org.sopt.and.presentation.ui.navigator.WaveBottomNavigation +import org.sopt.and.presentation.ui.navigator.WaveNavHost +import org.sopt.and.presentation.ui.navigator.WaveNavigator +import org.sopt.and.presentation.ui.navigator.rememberWaveNavigator +import org.sopt.and.ui.theme.ANDANDROIDTheme + +@Composable +fun MainScreen( + navigator: WaveNavigator = rememberWaveNavigator() +) { + Scaffold( + content = { paddingValues -> + WaveNavHost( + navigator = navigator, + paddingValues = paddingValues + ) + }, + bottomBar = { + WaveBottomNavigation( + isVisible = navigator.showBottomNavigation(), + bottomNaviItems = WaveBottomNavigationType.entries.toList(), + currentBottomNaviItem = navigator.currentWaveBottomNavigation, + onClickBottomNavItem = { navigator.navigateToWaveBottomNavigation(it) }, + modifier = Modifier.navigationBarsPadding() + ) + } + ) +} + +@Preview(showBackground = true) +@Composable +fun MainPreview() { + ANDANDROIDTheme { + MainScreen() + } +} \ No newline at end of file From 0efe72dddf5ce84d9e235dac5c440797c7f933cf Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 00:28:31 +0900 Subject: [PATCH 20/28] =?UTF-8?q?[feat]=20#4=20MyScreen=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EA=B0=80=EC=9E=85=ED=95=9C=20=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EC=9D=B4=20=ED=91=9C=EC=8B=9C=EB=90=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/and/presentation/ui/my/MyRoute.kt | 9 +++++++-- .../org/sopt/and/presentation/ui/my/MyScreen.kt | 7 ++++--- .../sopt/and/presentation/ui/my/MyViewModel.kt | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/my/MyViewModel.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt index a37a8e5..9defbdd 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyRoute.kt @@ -4,10 +4,15 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyRoute( - paddingValues: PaddingValues + paddingValues: PaddingValues, + myViewModel: MyViewModel = hiltViewModel() ) { - MyScreen(modifier = Modifier.padding(paddingValues)) + MyScreen( + modifier = Modifier.padding(paddingValues), + userName = myViewModel.getLocalUserMail() + ) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt index 8699cac..d4604e4 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt @@ -29,7 +29,8 @@ import org.sopt.and.ui.theme.White @Composable fun MyScreen( - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + userName: String ) { Column( modifier = modifier @@ -42,7 +43,7 @@ fun MyScreen( .background(Gray300) .padding(horizontal = 15.dp, vertical = 20.dp) ) { - MyProfile(userEmail = "@.com") + MyProfile(userEmail = userName) Spacer(modifier = Modifier.height(8.dp)) @@ -180,6 +181,6 @@ fun MyListBox(title: String, description: String) { @Composable fun MyPreview() { ANDANDROIDTheme { - MyScreen() + MyScreen(userName = "jieundaeun@naver.com") } } diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyViewModel.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyViewModel.kt new file mode 100644 index 0000000..b12ef0b --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyViewModel.kt @@ -0,0 +1,15 @@ +package org.sopt.and.presentation.ui.my + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import org.sopt.and.data.datasource.local.WaveLocalDataSource +import javax.inject.Inject + +@HiltViewModel +class MyViewModel @Inject constructor( + private val localDataSource: WaveLocalDataSource +) : ViewModel() { + fun getLocalUserMail(): String { + return localDataSource.userEmail + } +} \ No newline at end of file From 80dc97e3997c30330845dec1977c491ec8ce9709 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 02:49:00 +0900 Subject: [PATCH 21/28] =?UTF-8?q?[add]=20#4=20coil=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++++ app/src/main/AndroidManifest.xml | 3 +++ gradle/libs.versions.toml | 3 +++ 3 files changed, 10 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b636886..e3ea0bd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -74,4 +74,8 @@ dependencies { // Navigation implementation(libs.androidx.navigation) + + // Coil + implementation(libs.coil3.compose) + implementation(libs.coil3.network) } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a0b933e..dcfe6c5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + Date: Thu, 24 Oct 2024 02:49:22 +0900 Subject: [PATCH 22/28] =?UTF-8?q?[add]=20#4=20=ED=99=88=20=EB=B7=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20str?= =?UTF-8?q?ing=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/values/strings.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 046a2d9..a3cc2c7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,4 +42,20 @@ 시청내역이 없어요. 관심 프로그램 관심 프로그램이 없어요. + + + 뉴클래식 + 드라마 + 예능 + 영화 + 애니 + 해외 시리즈 + 시사교양 + 키즈 + 영화플러스 + LIVE + + %s/%s + 믿고 보는 웨이브 에디터 추천작 + 오늘의 TOP 20 \ No newline at end of file From 92315223a13be17d3e80aadb9aa8ce3f4342eccb Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 04:02:49 +0900 Subject: [PATCH 23/28] =?UTF-8?q?[feat]=20#4=20=ED=99=88=20=EB=B7=B0=20-?= =?UTF-8?q?=20=EC=B5=9C=EC=83=81=EB=8B=A8=20=EB=B0=B0=EB=84=88=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeContract.kt | 25 ++++ .../and/presentation/ui/home/HomeRoute.kt | 26 +++- .../and/presentation/ui/home/HomeScreen.kt | 118 +++++++++++++++++- .../and/presentation/ui/home/HomeViewModel.kt | 45 +++++++ 4 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt new file mode 100644 index 0000000..0b400fe --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt @@ -0,0 +1,25 @@ +package org.sopt.and.presentation.ui.home + +import org.sopt.and.presentation.util.UiEffect +import org.sopt.and.presentation.util.UiEvent +import org.sopt.and.presentation.util.UiState + +class HomeContract { + sealed class HomeEvent : UiEvent { + + } + + enum class HomeStatus { + Idle, Success, Fail + } + + data class HomeState( + val bannerImgList: List = listOf(), + val currentBannerPage: Int = 0, + val homeStatus: HomeStatus = HomeStatus.Idle + ) : UiState + + sealed class HomeSideEffect: UiEffect { + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt index cf1396f..be0e5df 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt @@ -3,11 +3,33 @@ package org.sopt.and.presentation.ui.home import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel @Composable fun HomeRoute( - paddingValues: PaddingValues + paddingValues: PaddingValues, + homeViewModel: HomeViewModel = hiltViewModel() ) { - HomeScreen(modifier = Modifier.padding(paddingValues)) + val homeState by homeViewModel.uiState.collectAsState() + + LaunchedEffect(homeState.homeStatus) { + if (homeState.homeStatus == HomeContract.HomeStatus.Idle) { + homeViewModel.setHomeImgList() + } + } + + + HomeScreen( + modifier = Modifier + .padding(paddingValues), + bannerImgList = homeState.bannerImgList, + numPages = homeState.bannerImgList.size.toString(), + onCurrentPageChanged = { page -> + homeViewModel.setCurrentBannerPage(page) + } + ) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index f4b055a..152b8d9 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -1,28 +1,132 @@ package org.sopt.and.presentation.ui.home +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import coil3.compose.AsyncImage +import coil3.request.ImageRequest +import coil3.request.crossfade +import org.sopt.and.R import org.sopt.and.ui.theme.ANDANDROIDTheme +import org.sopt.and.ui.theme.Gray100 +import org.sopt.and.ui.theme.GrayBlack @Composable fun HomeScreen( - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + bannerImgList: List, + numPages: String, + onCurrentPageChanged: (Int) -> Unit ) { Column( modifier = modifier - .padding(horizontal = 15.dp) .fillMaxSize() + .background(GrayBlack) .verticalScroll(rememberScrollState()) ) { - Text("Home Screen") + val pagerState = rememberPagerState(pageCount = { bannerImgList.size }) + val horizontalContentPadding = + ((LocalConfiguration.current).screenWidthDp * (1F - 0.85F) / 2).dp + + /* TODO + PagerState 자체를 인자로 받고 아래 LaunchedEffect를 HomeRoute로 옮기기 + */ + LaunchedEffect(pagerState.currentPage) { + onCurrentPageChanged(pagerState.currentPage) + } + + HorizontalPager( + state = pagerState, + contentPadding = PaddingValues(horizontal = horizontalContentPadding), + ) { page -> + HomeBannerItem( + bannerImg = bannerImgList[page], + currentPage = (page + 1).toString(), + numPages = numPages + ) + } + + } +} + +@Composable +fun HomeBannerItem( + bannerImg: String, + currentPage: String, + numPages: String +) { + Box( + modifier = Modifier + .padding(horizontal = 15.dp) + .fillMaxWidth() + .clip(RoundedCornerShape(15.dp)) + ) { + AsyncImage( + model = ImageRequest.Builder(context = LocalContext.current) + .data(bannerImg) + .crossfade(enable = true) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxWidth() + ) + + HomeBannerItemCountText( + modifier = Modifier + .align(Alignment.BottomEnd) + .padding(12.dp), + currentPage = currentPage, + pageCount = numPages + ) + } +} + +@Composable +fun HomeBannerItemCountText( + modifier: Modifier = Modifier, + currentPage: String, + pageCount: String +) { + Row( + modifier = Modifier + .clip(RoundedCornerShape(15.dp)) + .background(Gray100) + .padding(horizontal = 8.dp, vertical = 4.dp) + ) { + Text( + text = stringResource( + id = R.string.home_banner_page_count, + currentPage, + pageCount + ), + fontSize = 10.sp + ) } } @@ -30,6 +134,12 @@ fun HomeScreen( @Composable fun HomePreview() { ANDANDROIDTheme { - HomeScreen() + val homeViewModel = HomeViewModel() + + HomeScreen( + bannerImgList = homeViewModel.mockBannerItem, + numPages = "6", + onCurrentPageChanged = { } + ) } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt new file mode 100644 index 0000000..8f50316 --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt @@ -0,0 +1,45 @@ +package org.sopt.and.presentation.ui.home + +import dagger.hilt.android.lifecycle.HiltViewModel +import org.sopt.and.presentation.util.BaseViewModel +import javax.inject.Inject + +@HiltViewModel +class HomeViewModel @Inject constructor() : + BaseViewModel() { + + override fun createInitialState(): HomeContract.HomeState { + return HomeContract.HomeState() + } + + override fun handleEffect(effect: HomeContract.HomeSideEffect) { + TODO("Not yet implemented") + } + + override suspend fun handleEvent(event: HomeContract.HomeEvent) { + TODO("Not yet implemented") + } + + val mockBannerItem = listOf( + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1726468505828994516.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1727073001312600950.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728548543503727711.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728609264868811411.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1727679685902220639.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1725362669902656119.webp" + ) + + fun setCurrentBannerPage(page:Int) { + setState(currentUiState.copy(currentBannerPage = page)) + } + + fun setHomeImgList() { + setHomeBannerState() + + setState(currentUiState.copy(homeStatus = HomeContract.HomeStatus.Success)) + } + + private fun setHomeBannerState() { + setState(currentUiState.copy(bannerImgList = mockBannerItem)) + } +} \ No newline at end of file From 162432c222a56c7372bddca506c104b20d469936 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 04:36:55 +0900 Subject: [PATCH 24/28] =?UTF-8?q?[feat]=20#4=20=ED=99=88=20=EB=B7=B0=20-?= =?UTF-8?q?=20TextWithNavigateButton=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/component/TextWithNavigateButton.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 app/src/main/java/org/sopt/and/presentation/ui/component/TextWithNavigateButton.kt diff --git a/app/src/main/java/org/sopt/and/presentation/ui/component/TextWithNavigateButton.kt b/app/src/main/java/org/sopt/and/presentation/ui/component/TextWithNavigateButton.kt new file mode 100644 index 0000000..74dc44e --- /dev/null +++ b/app/src/main/java/org/sopt/and/presentation/ui/component/TextWithNavigateButton.kt @@ -0,0 +1,48 @@ +package org.sopt.and.presentation.ui.component + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.sopt.and.R +import org.sopt.and.ui.theme.White + +@Composable +fun TextWithNavigateButton( + @StringRes titleRes: Int, +) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp, horizontal = 8.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = stringResource(titleRes), + fontSize = 20.sp, + color = White + ) + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_arrow_right_btn_24), + contentDescription = null, + tint = White + ) + } +} + +@Preview +@Composable +fun TextWithNavigateButtonPreview() { + TextWithNavigateButton(R.string.home_editor_recommend_title) +} \ No newline at end of file From cc5aef324f2415e79ee219067b3edf5255a87095 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 04:37:09 +0900 Subject: [PATCH 25/28] =?UTF-8?q?[feat]=20#4=20=ED=99=88=20=EB=B7=B0=20-?= =?UTF-8?q?=20=EB=AF=BF=EA=B3=A0=20=EB=B3=B4=EB=8A=94=20=EC=9B=A8=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=20=EC=97=90=EB=94=94=ED=84=B0=20=EC=B6=94=EC=B2=9C?= =?UTF-8?q?=EC=9E=91=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeContract.kt | 1 + .../and/presentation/ui/home/HomeRoute.kt | 3 +- .../and/presentation/ui/home/HomeScreen.kt | 53 +++++++++++++++++-- .../and/presentation/ui/home/HomeViewModel.kt | 16 ++++++ 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt index 0b400fe..a1c1470 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt @@ -16,6 +16,7 @@ class HomeContract { data class HomeState( val bannerImgList: List = listOf(), val currentBannerPage: Int = 0, + val editorRecommendedList: List = listOf(), val homeStatus: HomeStatus = HomeStatus.Idle ) : UiState diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt index be0e5df..79db72a 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt @@ -30,6 +30,7 @@ fun HomeRoute( numPages = homeState.bannerImgList.size.toString(), onCurrentPageChanged = { page -> homeViewModel.setCurrentBannerPage(page) - } + }, + editorRecommendedImgList = homeState.editorRecommendedList ) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index 152b8d9..b03d519 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -1,15 +1,21 @@ package org.sopt.and.presentation.ui.home import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio 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.lazy.LazyListScope +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState @@ -18,6 +24,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -32,17 +39,21 @@ import androidx.compose.ui.unit.sp import coil3.compose.AsyncImage import coil3.request.ImageRequest import coil3.request.crossfade +import okhttp3.internal.cacheGet import org.sopt.and.R +import org.sopt.and.presentation.ui.component.TextWithNavigateButton import org.sopt.and.ui.theme.ANDANDROIDTheme import org.sopt.and.ui.theme.Gray100 import org.sopt.and.ui.theme.GrayBlack +import org.sopt.and.ui.theme.White @Composable fun HomeScreen( modifier: Modifier = Modifier, bannerImgList: List, numPages: String, - onCurrentPageChanged: (Int) -> Unit + onCurrentPageChanged: (Int) -> Unit, + editorRecommendedImgList: List ) { Column( modifier = modifier @@ -54,9 +65,7 @@ fun HomeScreen( val horizontalContentPadding = ((LocalConfiguration.current).screenWidthDp * (1F - 0.85F) / 2).dp - /* TODO - PagerState 자체를 인자로 받고 아래 LaunchedEffect를 HomeRoute로 옮기기 - */ + // TODO PagerState 자체를 인자로 받고 아래 LaunchedEffect를 HomeRoute로 옮기기 LaunchedEffect(pagerState.currentPage) { onCurrentPageChanged(pagerState.currentPage) } @@ -72,6 +81,21 @@ fun HomeScreen( ) } + TextWithNavigateButton( + titleRes = R.string.home_editor_recommend_title + ) + + LazyRow ( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ){ + itemsIndexed( editorRecommendedImgList, + key = {index, _ -> index}, + contentType = { _, item -> item} + ){ index, item -> + EditorRecommendedItem(recommendedItem = item) + } + } } } @@ -130,6 +154,24 @@ fun HomeBannerItemCountText( } } +@Composable +fun EditorRecommendedItem( + recommendedItem: String +) { + AsyncImage( + model = ImageRequest.Builder(context = LocalContext.current) + .data(recommendedItem) + .crossfade(enable = true) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(15.dp)) + .size(width = 144.dp, height = 192.dp) + ) +} + @Preview(showBackground = true) @Composable fun HomePreview() { @@ -139,7 +181,8 @@ fun HomePreview() { HomeScreen( bannerImgList = homeViewModel.mockBannerItem, numPages = "6", - onCurrentPageChanged = { } + onCurrentPageChanged = { }, + editorRecommendedImgList = homeViewModel.mockEditorRecommendedItem ) } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt index 8f50316..39130ca 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt @@ -29,12 +29,24 @@ class HomeViewModel @Inject constructor() : "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1725362669902656119.webp" ) + val mockEditorRecommendedItem = listOf( + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1729230112230270084.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202406/1717859400991205300.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/BMS/TVSeason/2023/K01_T2009-0520-2.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202309/1694062320658347760.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202408/1724292857510320522.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1729230427885490213.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/movieImg/MovieGroup/2023/GMV_CI01_LE0000011263-Vertical_LogoY.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/movieImg/MovieGroup/2023/GMV_CD01_WR0000011336-Vertical_LogoY_RTC.webp" + ) + fun setCurrentBannerPage(page:Int) { setState(currentUiState.copy(currentBannerPage = page)) } fun setHomeImgList() { setHomeBannerState() + setEditorRecommendState() setState(currentUiState.copy(homeStatus = HomeContract.HomeStatus.Success)) } @@ -42,4 +54,8 @@ class HomeViewModel @Inject constructor() : private fun setHomeBannerState() { setState(currentUiState.copy(bannerImgList = mockBannerItem)) } + + private fun setEditorRecommendState() { + setState(currentUiState.copy(editorRecommendedList = mockEditorRecommendedItem)) + } } \ No newline at end of file From 16a2d3d93be8c4b9c2d53fb114f009b412683116 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 04:51:43 +0900 Subject: [PATCH 26/28] =?UTF-8?q?[feat]=20#4=20=ED=99=88=20=EB=B7=B0=20-?= =?UTF-8?q?=20=EC=98=A4=EB=8A=98=EC=9D=98=20TOP20=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeContract.kt | 1 + .../and/presentation/ui/home/HomeRoute.kt | 3 +- .../and/presentation/ui/home/HomeScreen.kt | 61 ++++++++++++++++++- .../and/presentation/ui/home/HomeViewModel.kt | 18 ++++++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt index a1c1470..538ba98 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt @@ -17,6 +17,7 @@ class HomeContract { val bannerImgList: List = listOf(), val currentBannerPage: Int = 0, val editorRecommendedList: List = listOf(), + val todayTopRankingList: List = listOf(), val homeStatus: HomeStatus = HomeStatus.Idle ) : UiState diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt index 79db72a..42c5b27 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeRoute.kt @@ -31,6 +31,7 @@ fun HomeRoute( onCurrentPageChanged = { page -> homeViewModel.setCurrentBannerPage(page) }, - editorRecommendedImgList = homeState.editorRecommendedList + editorRecommendedImgList = homeState.editorRecommendedList, + todayTopRankingImgList = homeState.todayTopRankingList ) } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index b03d519..a0d21d8 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text @@ -53,7 +54,8 @@ fun HomeScreen( bannerImgList: List, numPages: String, onCurrentPageChanged: (Int) -> Unit, - editorRecommendedImgList: List + editorRecommendedImgList: List, + todayTopRankingImgList: List ) { Column( modifier = modifier @@ -81,6 +83,8 @@ fun HomeScreen( ) } + Spacer(Modifier.height(24.dp)) + TextWithNavigateButton( titleRes = R.string.home_editor_recommend_title ) @@ -96,6 +100,26 @@ fun HomeScreen( EditorRecommendedItem(recommendedItem = item) } } + + Spacer(Modifier.height(24.dp)) + + TextWithNavigateButton( + titleRes = R.string.home_today_top_ranking_title + ) + + LazyRow ( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ){ + itemsIndexed( todayTopRankingImgList, + key = {index, _ -> index}, + contentType = { _, item -> item} + ){ index, item -> + TodayTopRankingImgList(ranking = index, rankingItem = item) + } + } + + Spacer(Modifier.height(12.dp)) } } @@ -172,6 +196,38 @@ fun EditorRecommendedItem( ) } +@Composable +fun TodayTopRankingImgList( + ranking: Int, + rankingItem: String, +) { + Box( + modifier = Modifier + .fillMaxWidth() + ) { + AsyncImage( + model = ImageRequest.Builder(context = LocalContext.current) + .data(rankingItem) + .crossfade(enable = true) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(15.dp)) + .size(width = 180.dp, height = 240.dp) + ) + + Text( + text = (ranking + 1).toString(), + color = White, + fontSize = 42.sp, + modifier = Modifier + .align(Alignment.BottomStart) + ) + } +} + @Preview(showBackground = true) @Composable fun HomePreview() { @@ -182,7 +238,8 @@ fun HomePreview() { bannerImgList = homeViewModel.mockBannerItem, numPages = "6", onCurrentPageChanged = { }, - editorRecommendedImgList = homeViewModel.mockEditorRecommendedItem + editorRecommendedImgList = homeViewModel.mockEditorRecommendedItem, + todayTopRankingImgList = homeViewModel.mockTodayTopRankingItem ) } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt index 39130ca..9488082 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt @@ -40,6 +40,19 @@ class HomeViewModel @Inject constructor() : "https://image.wavve.com/v1/thumbnails/480_720_20_80/movieImg/MovieGroup/2023/GMV_CD01_WR0000011336-Vertical_LogoY_RTC.webp" ) + val mockTodayTopRankingItem = listOf( + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202409/1726468463104944317.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202311/1698908212143109040.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202311/1701072276533128034.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202311/1699601586197251349.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728017508965610221.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202309/1694062313324743958.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728548592019625574.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202309/1694567844509388076.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202405/1715069627941981919.webp", + "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728613201561457273.webp" + ) + fun setCurrentBannerPage(page:Int) { setState(currentUiState.copy(currentBannerPage = page)) } @@ -47,6 +60,7 @@ class HomeViewModel @Inject constructor() : fun setHomeImgList() { setHomeBannerState() setEditorRecommendState() + setTodayTopRankingState() setState(currentUiState.copy(homeStatus = HomeContract.HomeStatus.Success)) } @@ -58,4 +72,8 @@ class HomeViewModel @Inject constructor() : private fun setEditorRecommendState() { setState(currentUiState.copy(editorRecommendedList = mockEditorRecommendedItem)) } + + private fun setTodayTopRankingState() { + setState(currentUiState.copy(todayTopRankingList = mockTodayTopRankingItem)) + } } \ No newline at end of file From 34eb14361cc151f6abeb4004d4c7b0540150bbe1 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Thu, 24 Oct 2024 05:17:19 +0900 Subject: [PATCH 27/28] =?UTF-8?q?[chore]=20#4=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/auth/login/LoginContract.kt | 3 +- .../and/presentation/ui/home/HomeContract.kt | 2 +- .../and/presentation/ui/home/HomeScreen.kt | 30 ++++++++----------- .../and/presentation/ui/home/HomeViewModel.kt | 2 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginContract.kt index e50fbfe..8c8ae14 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginContract.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/auth/login/LoginContract.kt @@ -9,7 +9,8 @@ class LoginContract { data class EmailChanged(val email: String) : LoginEvent() data class PasswordChanged(val password: String) : LoginEvent() data object PasswordVisibilityChanged : LoginEvent() - data class OnLoginBtnClicked(val successMessage: String, val failMessage: String) : LoginEvent() + data class OnLoginBtnClicked(val successMessage: String, val failMessage: String) : + LoginEvent() } enum class LoginStatus { diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt index 538ba98..8eb29ac 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt @@ -21,7 +21,7 @@ class HomeContract { val homeStatus: HomeStatus = HomeStatus.Idle ) : UiState - sealed class HomeSideEffect: UiEffect { + sealed class HomeSideEffect : UiEffect { } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index a0d21d8..01c1e2a 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -7,25 +7,21 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.aspectRatio 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.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -33,14 +29,12 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil3.compose.AsyncImage import coil3.request.ImageRequest import coil3.request.crossfade -import okhttp3.internal.cacheGet import org.sopt.and.R import org.sopt.and.presentation.ui.component.TextWithNavigateButton import org.sopt.and.ui.theme.ANDANDROIDTheme @@ -89,14 +83,14 @@ fun HomeScreen( titleRes = R.string.home_editor_recommend_title ) - LazyRow ( + LazyRow( contentPadding = PaddingValues(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(12.dp) - ){ - itemsIndexed( editorRecommendedImgList, - key = {index, _ -> index}, - contentType = { _, item -> item} - ){ index, item -> + ) { + itemsIndexed(editorRecommendedImgList, + key = { index, _ -> index }, + contentType = { _, item -> item } + ) { index, item -> EditorRecommendedItem(recommendedItem = item) } } @@ -107,14 +101,14 @@ fun HomeScreen( titleRes = R.string.home_today_top_ranking_title ) - LazyRow ( + LazyRow( contentPadding = PaddingValues(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(12.dp) - ){ - itemsIndexed( todayTopRankingImgList, - key = {index, _ -> index}, - contentType = { _, item -> item} - ){ index, item -> + ) { + itemsIndexed(todayTopRankingImgList, + key = { index, _ -> index }, + contentType = { _, item -> item } + ) { index, item -> TodayTopRankingImgList(ranking = index, rankingItem = item) } } diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt index 9488082..1625489 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeViewModel.kt @@ -53,7 +53,7 @@ class HomeViewModel @Inject constructor() : "https://image.wavve.com/v1/thumbnails/480_720_20_80/meta/image/202410/1728613201561457273.webp" ) - fun setCurrentBannerPage(page:Int) { + fun setCurrentBannerPage(page: Int) { setState(currentUiState.copy(currentBannerPage = page)) } From 34bdb6ac117c5e44f0e84b4ce3b3bfc5ea28c5a5 Mon Sep 17 00:00:00 2001 From: JIEUNI Date: Fri, 1 Nov 2024 00:55:10 +0900 Subject: [PATCH 28/28] =?UTF-8?q?[chore]=20#4=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../and/presentation/ui/home/HomeContract.kt | 11 ++++--- .../and/presentation/ui/home/HomeScreen.kt | 32 ++++++++----------- .../sopt/and/presentation/ui/my/MyScreen.kt | 8 ++--- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt index 8eb29ac..9ac3a73 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeContract.kt @@ -1,5 +1,6 @@ package org.sopt.and.presentation.ui.home +import okhttp3.internal.immutableListOf import org.sopt.and.presentation.util.UiEffect import org.sopt.and.presentation.util.UiEvent import org.sopt.and.presentation.util.UiState @@ -10,15 +11,15 @@ class HomeContract { } enum class HomeStatus { - Idle, Success, Fail + Loading, Success, Fail } data class HomeState( - val bannerImgList: List = listOf(), + val bannerImgList: List = immutableListOf(), val currentBannerPage: Int = 0, - val editorRecommendedList: List = listOf(), - val todayTopRankingList: List = listOf(), - val homeStatus: HomeStatus = HomeStatus.Idle + val editorRecommendedList: List = immutableListOf(), + val todayTopRankingList: List = immutableListOf(), + val homeStatus: HomeStatus = HomeStatus.Loading ) : UiState sealed class HomeSideEffect : UiEffect { diff --git a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt index 01c1e2a..30e222f 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/home/HomeScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -155,21 +154,18 @@ fun HomeBannerItemCountText( currentPage: String, pageCount: String ) { - Row( - modifier = Modifier + Text( + text = stringResource( + id = R.string.home_banner_page_count, + currentPage, + pageCount + ), + modifier = modifier .clip(RoundedCornerShape(15.dp)) .background(Gray100) - .padding(horizontal = 8.dp, vertical = 4.dp) - ) { - Text( - text = stringResource( - id = R.string.home_banner_page_count, - currentPage, - pageCount - ), - fontSize = 10.sp - ) - } + .padding(horizontal = 8.dp, vertical = 4.dp), + fontSize = 10.sp + ) } @Composable @@ -226,14 +222,12 @@ fun TodayTopRankingImgList( @Composable fun HomePreview() { ANDANDROIDTheme { - val homeViewModel = HomeViewModel() - HomeScreen( - bannerImgList = homeViewModel.mockBannerItem, + bannerImgList = listOf(""), numPages = "6", onCurrentPageChanged = { }, - editorRecommendedImgList = homeViewModel.mockEditorRecommendedItem, - todayTopRankingImgList = homeViewModel.mockTodayTopRankingItem + editorRecommendedImgList = listOf(""), + todayTopRankingImgList = listOf("") ) } } \ No newline at end of file diff --git a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt index d4604e4..aed20ea 100644 --- a/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt +++ b/app/src/main/java/org/sopt/and/presentation/ui/my/MyScreen.kt @@ -2,6 +2,7 @@ package org.sopt.and.presentation.ui.my import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -41,16 +42,13 @@ fun MyScreen( modifier = Modifier .fillMaxWidth() .background(Gray300) - .padding(horizontal = 15.dp, vertical = 20.dp) + .padding(horizontal = 15.dp, vertical = 20.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) ) { MyProfile(userEmail = userName) - Spacer(modifier = Modifier.height(8.dp)) - MyPurchaseBox(information = stringResource(R.string.my_purchase_event)) - Spacer(modifier = Modifier.height(8.dp)) - MyPurchaseBox(information = stringResource(R.string.my_purchase_ticket)) }