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
Rj>G@}002ovPDHLkV1mFy>yH2c
literal 0
HcmV?d00001
From c2892e3ee741fabf9a16c8ee2e2d4347bcd6d205 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:00:22 +0900
Subject: [PATCH 25/36] [feat] #4 PolicyScreen
---
.../login/singup/screen/PolicyScreen.kt | 177 ++++++++++++++++++
1 file changed, 177 insertions(+)
create mode 100644 feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
diff --git a/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt b/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
new file mode 100644
index 00000000..9ed73b68
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
@@ -0,0 +1,177 @@
+package com.record.login.singup.screen
+
+import androidx.compose.animation.animateContentSize
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+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.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import com.record.designsystem.R.drawable.ic_check_16
+import com.record.designsystem.R.drawable.ic_check_24
+import com.record.designsystem.R.drawable.ic_signup
+import com.record.designsystem.theme.RecordyTheme
+import com.record.login.singup.SignUpState
+
+@Composable
+fun PolicyScreen(
+ padding: PaddingValues = PaddingValues(horizontal = 16.dp),
+ uiState: SignUpState,
+ onCheckAllClick: () -> Unit,
+ onCheckServiceClick: () -> Unit,
+ onCheckPolicyClick: () -> Unit,
+ onCheckAgeClick: () -> Unit,
+) {
+ Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Top) {
+ Spacer(modifier = Modifier.height(33.dp))
+ Image(
+ painter = painterResource(id = ic_signup),
+ null,
+ modifier = Modifier
+ .width(84.dp)
+ .padding(start = 12.dp)
+ .aspectRatio(1f),
+ )
+ Spacer(modifier = Modifier.height(9.dp))
+ Text(
+ text = "유영하러 오신 것을 \n환영합니다!",
+ modifier = Modifier
+ .padding(start = 16.dp)
+ .fillMaxWidth()
+ .padding(padding),
+ style = RecordyTheme.typography.title1,
+ color = RecordyTheme.colors.gray01,
+ )
+ Spacer(modifier = Modifier.height(33.dp))
+ RecordyCheckAllBox(
+ "전체 동의",
+ padding = padding,
+ checked = uiState.allChecked,
+ onClickEvent = { onCheckAllClick() },
+ )
+ RecordyCheckBox(
+ "(필수) 서비스 이용약관 동의",
+ padding = padding,
+ checked = uiState.serviceTermsChecked,
+ onClickEvent = { onCheckServiceClick() },
+ )
+ RecordyCheckBox(
+ "(필수) 개인정보 수집이용 동의",
+ padding = padding,
+ checked = uiState.privacyPolicyChecked,
+ onClickEvent = { onCheckPolicyClick() },
+ )
+ RecordyCheckBox(
+ "(필수) 만 14세 이상입니다",
+ padding = padding,
+ checked = uiState.ageChecked,
+ onClickEvent = { onCheckAgeClick() },
+ )
+ }
+}
+
+@Composable
+fun RecordyCheckAllBox(contentText: String = "", padding: PaddingValues, checked: Boolean = false, onClickEvent: () -> Unit) {
+ Box(
+ modifier = Modifier
+ .padding(padding)
+ .fillMaxWidth()
+ .height(48.dp)
+ .background(RecordyTheme.colors.gray04, RoundedCornerShape(8.dp))
+ .clickable(onClick = onClickEvent, indication = null, interactionSource = remember { MutableInteractionSource() })
+ .padding(start = 20.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Start,
+ modifier = Modifier.fillMaxWidth(),
+ ) {
+ Icon(
+ ImageVector.vectorResource(id = ic_check_24),
+ contentDescription = null,
+ modifier = Modifier
+ .height(24.dp)
+ .padding(vertical = 2.dp)
+ .aspectRatio(1f),
+ tint = if (checked) RecordyTheme.colors.gray01 else RecordyTheme.colors.gray05,
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(
+ text = contentText,
+ style = RecordyTheme.typography.subtitle.copy(color = RecordyTheme.colors.gray01),
+ )
+ }
+ }
+}
+
+@Composable
+fun RecordyCheckBox(contentText: String = "", padding: PaddingValues, checked: Boolean = false, onClickEvent: () -> Unit) {
+ Column {
+ Spacer(modifier = Modifier.height(9.dp))
+ Box(
+ modifier = Modifier
+ .padding(padding)
+ .fillMaxWidth()
+ .height(40.dp)
+ .clickable(onClick = onClickEvent, indication = null, interactionSource = remember { MutableInteractionSource() })
+ .padding(start = 20.dp),
+ contentAlignment = Alignment.Center,
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Start,
+ modifier = Modifier.fillMaxWidth(),
+ ) {
+ Icon(
+ ImageVector.vectorResource(id = ic_check_16),
+ contentDescription = null,
+ modifier = Modifier
+ .animateContentSize { initialValue, targetValue -> }
+ .height(24.dp)
+ .padding(vertical = 2.dp)
+ .aspectRatio(1f),
+ tint = if (checked) RecordyTheme.colors.gray01 else RecordyTheme.colors.gray05,
+ )
+ Spacer(modifier = Modifier.width(16.dp))
+ Text(
+ text = contentText,
+ style = RecordyTheme.typography.caption1.copy(color = RecordyTheme.colors.gray01),
+ )
+ Spacer(modifier = Modifier.weight(1f))
+ Text(
+ text = "더보기",
+ textAlign = TextAlign.End,
+ modifier = Modifier.clickable(
+ onClick = { /*TODO*/ },
+ indication = null,
+ interactionSource = remember { MutableInteractionSource() },
+ ),
+ style = RecordyTheme.typography.caption1U.copy(color = RecordyTheme.colors.gray01),
+ )
+ }
+ }
+ }
+}
From c1a767a6dbac6b77dca2ea046d7595ac655e7a9d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:00:36 +0900
Subject: [PATCH 26/36] [feat] #4 NamingScreen
---
.../login/singup/screen/NamingScreen.kt | 38 +++++++++++++++++++
.../login/singup/screen/PolicyScreen.kt | 2 +-
2 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 feature/login/src/main/java/com/record/login/singup/screen/NamingScreen.kt
diff --git a/feature/login/src/main/java/com/record/login/singup/screen/NamingScreen.kt b/feature/login/src/main/java/com/record/login/singup/screen/NamingScreen.kt
new file mode 100644
index 00000000..0d2b5272
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/screen/NamingScreen.kt
@@ -0,0 +1,38 @@
+package com.record.login.singup.screen
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+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.unit.dp
+import com.record.designsystem.component.textfield.RecordyValidateTextfield
+import com.record.designsystem.theme.RecordyTheme
+import com.record.login.singup.SignUpState
+
+@Composable
+fun NamingScreen(uiState: SignUpState, onTextChangeEvent: (String) -> Unit) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Top,
+ ) {
+ Spacer(modifier = Modifier.height(55.dp))
+ Text(
+ text = "당신의 첫 번째 기록, \n닉네임을 설정해주세요.",
+ modifier = Modifier.padding(start = 16.dp),
+ style = RecordyTheme.typography.title1,
+ color = RecordyTheme.colors.gray01,
+ )
+ Spacer(modifier = Modifier.height(30.dp))
+ RecordyValidateTextfield(
+ errorState = uiState.nicknameValidate,
+ onValueChange = { text ->
+ onTextChangeEvent(text)
+ },
+ )
+ }
+}
diff --git a/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt b/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
index 9ed73b68..b1b9713d 100644
--- a/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
+++ b/feature/login/src/main/java/com/record/login/singup/screen/PolicyScreen.kt
@@ -44,7 +44,7 @@ fun PolicyScreen(
onCheckPolicyClick: () -> Unit,
onCheckAgeClick: () -> Unit,
) {
- Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Top) {
+ Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Top) {
Spacer(modifier = Modifier.height(33.dp))
Image(
painter = painterResource(id = ic_signup),
From aab6d7e02ba4c06a43ee8e5fef5e865d41cc8366 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:07:12 +0900
Subject: [PATCH 27/36] [feat] #4 SignUpState, SignUpViewModel
---
.../com/record/login/singup/SignUpState.kt | 21 ++++
.../record/login/singup/SignUpViewModel.kt | 113 ++++++++++++++++++
2 files changed, 134 insertions(+)
create mode 100644 feature/login/src/main/java/com/record/login/singup/SignUpState.kt
create mode 100644 feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpState.kt b/feature/login/src/main/java/com/record/login/singup/SignUpState.kt
new file mode 100644
index 00000000..36711667
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpState.kt
@@ -0,0 +1,21 @@
+package com.record.login.singup
+
+import com.record.model.ValidateResult
+import com.record.ui.base.SideEffect
+import com.record.ui.base.UiState
+
+data class SignUpState(
+ val allChecked: Boolean = false,
+ val serviceTermsChecked: Boolean = false,
+ val privacyPolicyChecked: Boolean = false,
+ val ageChecked: Boolean = false,
+
+ val btnEnable: Boolean = false,
+
+ val nicknameText: String = "",
+ val nicknameValidate: ValidateResult = ValidateResult.Inputting,
+
+ val title: String = "이용약관",
+) : UiState
+
+sealed interface SignUpEffect : SideEffect
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
new file mode 100644
index 00000000..4a47423e
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
@@ -0,0 +1,113 @@
+package com.record.login.singup
+
+import com.record.model.ValidateResult
+import com.record.ui.base.BaseViewModel
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+@HiltViewModel
+class SignUpViewModel @Inject constructor() : BaseViewModel(SignUpState()) {
+
+ fun allCheckEvent() {
+ intent {
+ val isChecked = !allChecked
+ copy(
+ allChecked = isChecked,
+ serviceTermsChecked = isChecked,
+ privacyPolicyChecked = isChecked,
+ ageChecked = isChecked,
+ btnEnable = isChecked,
+ )
+ }
+ }
+
+ fun checkServiceEvent() {
+ intent {
+ copy(serviceTermsChecked = !serviceTermsChecked)
+ }
+ allChecked()
+ }
+
+ fun checkPrivacyPolicyEvent() {
+ intent {
+ copy(privacyPolicyChecked = !privacyPolicyChecked)
+ }
+ allChecked()
+ }
+
+ fun checkAgeEvent() {
+ intent {
+ copy(ageChecked = !ageChecked)
+ }
+ allChecked()
+ }
+
+ fun navScreen(screenNumber: Int) {
+ when (screenNumber) {
+ 0 -> {
+ allChecked()
+ intent {
+ copy(title = TITLE_POLICY_NAME)
+ }
+ }
+
+ 1 -> {
+ checkValidateNickName()
+ intent {
+ copy(title = TITLE_NAMING_NAME)
+ }
+ }
+ 2 -> { // todo 화면이동
+ intent {
+ copy(title = TITLE_SIGNUP_NAME)
+ }
+ }
+ }
+ }
+
+ fun updateNickName(nickname: String) {
+ intent {
+ copy(nicknameText = nickname)
+ }
+ checkValidateNickName()
+ }
+
+ fun checkValidateNickName() =
+ when {
+ uiState.value.nicknameText.isBlank() -> {
+ intent { copy(nicknameValidate = ValidateResult.Inputting, btnEnable = false) }
+ }
+
+ !nickNameDuplication(uiState.value.nicknameText) -> {
+ intent { copy(nicknameValidate = ValidateResult.OverlapError, btnEnable = false) }
+ }
+
+ !nickNameRegex(uiState.value.nicknameText) -> {
+ intent { copy(nicknameValidate = ValidateResult.ValidationError, btnEnable = false) }
+ }
+
+ else -> {
+ intent { copy(nicknameValidate = ValidateResult.Success, btnEnable = true) }
+ }
+ }
+
+ fun nickNameRegex(nickname: String): Boolean = Regex(NICKNAME_PATTERN).matches(nickname)
+ fun nickNameDuplication(nickname: String): Boolean = true
+
+ private fun allChecked() {
+ intent {
+ if (serviceTermsChecked && privacyPolicyChecked && ageChecked) {
+ copy(allChecked = true, btnEnable = true)
+ } else {
+ copy(allChecked = false, btnEnable = false)
+ }
+ }
+ }
+
+ companion object {
+ const val NICKNAME_PATTERN = "^[가-힣ㄱ-ㅎㅏ-ㅣ0-9_]+$"
+ const val TITLE_POLICY_NAME = "이용약관"
+ const val TITLE_NAMING_NAME = "닉네임 설명"
+ const val TITLE_SIGNUP_NAME = "회원가입 완료"
+ }
+}
From 9a09a883805560ab5d63fcd635593bdc6da2448a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:08:15 +0900
Subject: [PATCH 28/36] [feat] #4 SignUpScreen.kt
---
.../com/record/login/singup/SignUpScreen.kt | 141 ++++++++++++++++++
1 file changed, 141 insertions(+)
create mode 100644 feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
new file mode 100644
index 00000000..72331ceb
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
@@ -0,0 +1,141 @@
+package com.record.login.singup
+
+import androidx.activity.compose.BackHandler
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.ExperimentalFoundationApi
+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.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.pager.HorizontalPager
+import androidx.compose.foundation.pager.rememberPagerState
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.record.designsystem.component.button.RecordyButton
+import com.record.designsystem.component.progressbar.RecordyProgressBar
+import com.record.designsystem.theme.RecordyTheme
+import com.record.login.singup.screen.NamingScreen
+import com.record.login.singup.screen.PolicyScreen
+import com.record.login.singup.screen.SignUpSucessScreen
+import kotlinx.coroutines.launch
+
+@OptIn(ExperimentalFoundationApi::class)
+@Composable
+fun SignUpRoute(
+ padding: PaddingValues = PaddingValues(horizontal = 16.dp),
+ viewModel: SignUpViewModel = hiltViewModel(),
+) {
+ val pagerState = rememberPagerState(initialPage = 0, pageCount = { 3 })
+ val uiState by viewModel.uiState.collectAsStateWithLifecycle()
+ val coroutineScope = rememberCoroutineScope()
+ val focusManager = LocalFocusManager.current
+ BackHandler(enabled = pagerState.currentPage >= 1) {
+ coroutineScope.launch {
+ viewModel.navScreen(pagerState.currentPage - 1)
+ pagerState.animateScrollToPage(
+ pagerState.currentPage - 1,
+ animationSpec = tween(
+ durationMillis = 500,
+ delayMillis = 300,
+ ),
+ )
+ viewModel.navScreen(pagerState.currentPage - 1)
+ }
+ }
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(brush = Brush.verticalGradient(listOf(Color(0x339babfb), Color(0x00000000)))),
+ ) {
+ Text(
+ text = uiState.title,
+ modifier = Modifier
+ .padding(vertical = 16.dp)
+ .fillMaxWidth(),
+ textAlign = TextAlign.Center,
+ style = RecordyTheme.typography.title3,
+ color = RecordyTheme.colors.white,
+ )
+ // todo 추후 앱바 구현에 따른 변경
+ Spacer(modifier = Modifier.height(12.dp))
+ RecordyProgressBar(
+ completionRatioNumerator = pagerState.currentPage + 1,
+ completionRatioDenominator = pagerState.pageCount,
+ )
+
+ HorizontalPager(
+ state = pagerState,
+ userScrollEnabled = false,
+ modifier = Modifier
+ .fillMaxSize(),
+ ) { page ->
+ when (page) {
+ 0 -> PolicyScreen(
+ padding = padding,
+ uiState = uiState,
+ onCheckAllClick = viewModel::allCheckEvent,
+ onCheckServiceClick = viewModel::checkServiceEvent,
+ onCheckPolicyClick = viewModel::checkPrivacyPolicyEvent,
+ onCheckAgeClick = viewModel::checkAgeEvent,
+ )
+
+ 1 -> NamingScreen(uiState = uiState, onTextChangeEvent = viewModel::updateNickName)
+ 2 -> SignUpSucessScreen()
+ }
+ }
+ }
+ Box(modifier = Modifier.fillMaxSize()) {
+ Column(modifier = Modifier.align(alignment = Alignment.BottomCenter)) {
+ RecordyButton(
+ text = "다음",
+ enabled = uiState.btnEnable,
+ onClick = {
+ coroutineScope.launch {
+ pagerState.animateScrollToPage(
+ pagerState.currentPage + 1,
+ animationSpec = tween(
+ durationMillis = 500,
+ delayMillis = 0,
+ ),
+ )
+ }
+ focusManager.clearFocus()
+ viewModel.navScreen(pagerState.currentPage + 1)
+ },
+ modifier = Modifier
+ .imePadding(),
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ }
+ }
+}
+
+@Preview
+@Composable
+fun PreviewSignUp(
+ padding: PaddingValues = PaddingValues(horizontal = 16.dp),
+ viewModel: SignUpViewModel = hiltViewModel(),
+) {
+ RecordyTheme {
+ SignUpRoute(padding = padding, viewModel = viewModel)
+ }
+}
From 7edef48e4c65f3261b4bf405129578591e11bd1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:08:31 +0900
Subject: [PATCH 29/36] [feat] #4 SignUpSucessScreen
---
.../login/singup/screen/SignUpSucessScreen.kt | 52 +++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 feature/login/src/main/java/com/record/login/singup/screen/SignUpSucessScreen.kt
diff --git a/feature/login/src/main/java/com/record/login/singup/screen/SignUpSucessScreen.kt b/feature/login/src/main/java/com/record/login/singup/screen/SignUpSucessScreen.kt
new file mode 100644
index 00000000..d1c83cb0
--- /dev/null
+++ b/feature/login/src/main/java/com/record/login/singup/screen/SignUpSucessScreen.kt
@@ -0,0 +1,52 @@
+package com.record.login.singup.screen
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Column
+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.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.record.designsystem.R.drawable.ic_signup
+import com.record.designsystem.theme.RecordyTheme
+
+@Composable
+fun SignUpSucessScreen() {
+ Column(modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
+ Spacer(modifier = Modifier.height(174.dp))
+ Image(
+ painter = painterResource(id = ic_signup),
+ contentDescription = null,
+ modifier = Modifier
+ .fillMaxWidth(0.3f)
+ .aspectRatio(1f),
+ )
+ Spacer(modifier = Modifier.height(36.dp))
+ Text(
+ "회원가입이 완료되었어요!",
+ style = RecordyTheme.typography.title1,
+ color = RecordyTheme.colors.gray01,
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ Text(
+ "지금 영상을 둘러보고 나만의 공간 취향을 발견해 보세요.",
+ style = RecordyTheme.typography.caption2,
+ color = RecordyTheme.colors.gray03,
+ )
+ }
+}
+
+@Preview
+@Composable
+fun PreviewSignUpSucessScreen() {
+ RecordyTheme {
+ SignUpSucessScreen()
+ }
+}
From 3f7caab28aa235bbfe086420a50dfc5bcf66f847 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:08:49 +0900
Subject: [PATCH 30/36] [mod] #4 RecordyValidateTextfield
---
.../component/textfield/RecordyValidateTextfield.kt | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/core/designsystem/src/main/java/com/record/designsystem/component/textfield/RecordyValidateTextfield.kt b/core/designsystem/src/main/java/com/record/designsystem/component/textfield/RecordyValidateTextfield.kt
index 81a8c6bd..0a4d9133 100644
--- a/core/designsystem/src/main/java/com/record/designsystem/component/textfield/RecordyValidateTextfield.kt
+++ b/core/designsystem/src/main/java/com/record/designsystem/component/textfield/RecordyValidateTextfield.kt
@@ -36,7 +36,7 @@ import com.record.model.ValidateResult
@Composable
fun RecordyValidateTextfield(
modifier: Modifier = Modifier,
- errorState: ValidateResult = ValidateResult.ValidationError,
+ errorState: ValidateResult = ValidateResult.Inputting,
placeholder: String = "EX) 레코디둥이들",
maxLines: Int = 1,
maxLength: Int = 10,
@@ -46,8 +46,8 @@ fun RecordyValidateTextfield(
keyboardActions: KeyboardActions = KeyboardActions.Default,
padding: PaddingValues = PaddingValues(horizontal = 16.dp),
overlapErrorMessage: String = "이미 사용중인 닉네임이에요",
- validationErrorMessage: String = "한글, 숫자, 밑줄 및 마침표만 사용할 수 있어요",
- successMessage: String = "사용 가능한 닉네임이에요",
+ validationErrorMessage: String = "ⓘ 한글, 숫자, 밑줄 및 마침표만 사용할 수 있어요",
+ successMessage: String = "ⓘ 사용 가능한 닉네임이에요",
inputtingMessage: String = "",
) {
var value by remember { mutableStateOf("") }
@@ -56,7 +56,8 @@ fun RecordyValidateTextfield(
Column(
modifier = Modifier
- .fillMaxSize()
+ .wrapContentHeight()
+ .fillMaxWidth()
.padding(padding)
.clip(shape),
) {
From 52129defb5271fde45b9ccc60f8fb119d5ce089c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 00:10:08 +0900
Subject: [PATCH 31/36] [chore] #4 ktlint format
---
.../main/java/com/record/login/LoginScreen.kt | 60 ++++++++++++++++---
.../com/record/navigator/MainNavigator.kt | 2 +-
2 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/feature/login/src/main/java/com/record/login/LoginScreen.kt b/feature/login/src/main/java/com/record/login/LoginScreen.kt
index e929eaa3..bb5b9ca3 100644
--- a/feature/login/src/main/java/com/record/login/LoginScreen.kt
+++ b/feature/login/src/main/java/com/record/login/LoginScreen.kt
@@ -1,5 +1,6 @@
package com.record.login
+import androidx.activity.ComponentActivity
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -15,23 +16,70 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.record.designsystem.theme.Kakao
import com.record.designsystem.theme.RecordyTheme
+import dagger.hilt.android.EntryPointAccessors
import kakaoLogo
+import kotlinx.coroutines.flow.collectLatest
@Composable
fun LoginRoute(
- padding: PaddingValues,
+ padding: PaddingValues = PaddingValues(vertical = 16.dp),
modifier: Modifier = Modifier,
-// viewModel: LoginViewModel = hiltViewModel(),
+ viewModel: LoginViewModel = hiltViewModel(),
) {
-// val loginState by viewModel.loginState.collectAsState() // 추후 상태에 따라 이동
+ val uiState by viewModel.uiState.collectAsStateWithLifecycle()
+ val context = LocalContext.current as ComponentActivity
+ val entryPoint = EntryPointAccessors.fromActivity(context)
+ val oAuthInteractor = entryPoint.getOAuthInteractor()
+
+ LaunchedEffect(Unit) {
+ viewModel.sideEffect.collectLatest { sideEffect ->
+ when (sideEffect) {
+ is LoginSideEffect.StartLogin -> {
+ var result = oAuthInteractor.loginByKakao()
+ result.onSuccess {
+ viewModel.handleLoginSuccess(it)
+ }.onFailure {
+ viewModel.handleLoginError(it.message.toString())
+ }
+ }
+
+ is LoginSideEffect.LoginSuccess -> {
+ // 필요 시 LoginSuccess 추가 처리
+ }
+ is LoginSideEffect.LoginError -> {
+ // 필요 시 LoginError 추가 처리
+ }
+ }
+ }
+ }
+ LoginScreen(
+ padding = padding,
+ modifier = modifier,
+ uiState = uiState,
+ onLogInClick = { viewModel.startKakaoLogin() },
+ )
+}
+
+@Composable
+fun LoginScreen(
+ padding: PaddingValues,
+ modifier: Modifier = Modifier,
+ uiState: LoginState,
+ onLogInClick: () -> Unit,
+) {
Column(
modifier = modifier
.fillMaxSize()
@@ -48,7 +96,7 @@ fun LoginRoute(
kakaoLogo(),
null,
modifier = Modifier
- .height(120.dp)
+ .fillMaxWidth(0.3f)
.aspectRatio(1f),
)
@@ -65,9 +113,7 @@ fun LoginRoute(
Spacer(modifier = Modifier.weight(1f))
Button(
- onClick = {
-// viewModel.loginWithKakao() // 로그인 함수 호출`
- },
+ onClick = onLogInClick,
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
diff --git a/feature/navigator/src/main/java/com/record/navigator/MainNavigator.kt b/feature/navigator/src/main/java/com/record/navigator/MainNavigator.kt
index fc5098bc..9f71c718 100644
--- a/feature/navigator/src/main/java/com/record/navigator/MainNavigator.kt
+++ b/feature/navigator/src/main/java/com/record/navigator/MainNavigator.kt
@@ -17,7 +17,7 @@ import com.record.video.navigation.navigateVideo
internal class MainNavigator(
val navController: NavHostController,
) {
- val startDestination = HomeRoute.route
+ val startDestination = LoginRoute.route
private val currentDestination: NavDestination?
@Composable get() = navController
.currentBackStackEntryAsState().value?.destination
From ba891909dec15e8f5ef6abb4c72a3858c635bfc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 03:28:45 +0900
Subject: [PATCH 32/36] [mod] #4 login,SignUp adjust background & view
---
.../main/java/com/record/login/LoginScreen.kt | 30 +++++++++++++++----
.../com/record/login/singup/SignUpScreen.kt | 27 +++++++++++++++--
2 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/feature/login/src/main/java/com/record/login/LoginScreen.kt b/feature/login/src/main/java/com/record/login/LoginScreen.kt
index bb5b9ca3..fc22b9bb 100644
--- a/feature/login/src/main/java/com/record/login/LoginScreen.kt
+++ b/feature/login/src/main/java/com/record/login/LoginScreen.kt
@@ -2,6 +2,7 @@ package com.record.login
import androidx.activity.ComponentActivity
import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
@@ -18,11 +19,18 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -34,7 +42,7 @@ import kotlinx.coroutines.flow.collectLatest
@Composable
fun LoginRoute(
- padding: PaddingValues = PaddingValues(vertical = 16.dp),
+ padding: PaddingValues,
modifier: Modifier = Modifier,
viewModel: LoginViewModel = hiltViewModel(),
) {
@@ -68,21 +76,32 @@ fun LoginRoute(
LoginScreen(
padding = padding,
modifier = modifier,
- uiState = uiState,
onLogInClick = { viewModel.startKakaoLogin() },
)
}
@Composable
fun LoginScreen(
- padding: PaddingValues,
+ padding: PaddingValues = PaddingValues(horizontal = 16.dp),
modifier: Modifier = Modifier,
- uiState: LoginState,
onLogInClick: () -> Unit,
) {
+ var columnSize by remember {
+ mutableStateOf(IntSize.Zero)
+ }
Column(
modifier = modifier
.fillMaxSize()
+ .onGloballyPositioned { layoutCoordinates ->
+ columnSize = layoutCoordinates.size
+ }
+ .background(
+ brush = Brush.verticalGradient(
+ listOf(Color(0x339babfb), Color(0x00000000)),
+ startY = columnSize.height.toFloat() * 0.1f,
+ endY = columnSize.height.toFloat() * 0.6f,
+ ),
+ )
.padding(padding),
horizontalAlignment = Alignment.CenterHorizontally,
) {
@@ -116,7 +135,8 @@ fun LoginScreen(
onClick = onLogInClick,
modifier = Modifier
.fillMaxWidth()
- .height(48.dp),
+ .height(48.dp)
+ .padding(horizontal = 16.dp),
colors = ButtonDefaults.buttonColors(containerColor = Kakao),
shape = RoundedCornerShape(10.dp),
) {
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
index 72331ceb..74aaaa43 100644
--- a/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
@@ -18,14 +18,19 @@ import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -47,6 +52,10 @@ fun SignUpRoute(
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val coroutineScope = rememberCoroutineScope()
val focusManager = LocalFocusManager.current
+
+ var columnSize by remember {
+ mutableStateOf(IntSize.Zero)
+ }
BackHandler(enabled = pagerState.currentPage >= 1) {
coroutineScope.launch {
viewModel.navScreen(pagerState.currentPage - 1)
@@ -64,7 +73,16 @@ fun SignUpRoute(
Column(
modifier = Modifier
.fillMaxSize()
- .background(brush = Brush.verticalGradient(listOf(Color(0x339babfb), Color(0x00000000)))),
+ .onGloballyPositioned { layoutCoordinates ->
+ columnSize = layoutCoordinates.size
+ }
+ .background(
+ brush = Brush.verticalGradient(
+ listOf(Color(0x339babfb), Color(0x00000000)),
+ startY = columnSize.height.toFloat() * 0.1f,
+ endY = columnSize.height.toFloat() * 0.6f,
+ ),
+ ),
) {
Text(
text = uiState.title,
@@ -122,7 +140,8 @@ fun SignUpRoute(
viewModel.navScreen(pagerState.currentPage + 1)
},
modifier = Modifier
- .imePadding(),
+ .imePadding()
+ .padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.height(16.dp))
}
@@ -136,6 +155,8 @@ fun PreviewSignUp(
viewModel: SignUpViewModel = hiltViewModel(),
) {
RecordyTheme {
- SignUpRoute(padding = padding, viewModel = viewModel)
+ Box(modifier = Modifier.background(color = RecordyTheme.colors.background)) {
+ SignUpRoute(padding = padding, viewModel = viewModel)
+ }
}
}
From ba9879c7ff890e9d31eef2ff25d14fde71985827 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 03:29:06 +0900
Subject: [PATCH 33/36] [mod] #4 ktlint formatting
---
.../src/main/java/com/record/login/singup/SignUpViewModel.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
index 4a47423e..daf2df70 100644
--- a/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
@@ -55,7 +55,7 @@ class SignUpViewModel @Inject constructor() : BaseViewModel { // todo 화면이동
intent {
From c565e7da4728ea926c71019a18e298e9bece9040 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Thu, 11 Jul 2024 04:20:45 +0900
Subject: [PATCH 34/36] [add] #4 yml update - kakao native Key
---
.github/workflows/android-pull-request-ci.yml | 50 ++++++++++---------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/.github/workflows/android-pull-request-ci.yml b/.github/workflows/android-pull-request-ci.yml
index 77cf0da4..44911dfb 100644
--- a/.github/workflows/android-pull-request-ci.yml
+++ b/.github/workflows/android-pull-request-ci.yml
@@ -1,34 +1,36 @@
name: Android Pull Request CI
on:
- pull_request:
- branches: [ develop ]
+ pull_request:
+ branches: [ develop ]
jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout the code
- uses: actions/checkout@v4
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the code
+ uses: actions/checkout@v4
- - name: Setup JDK 17
- uses: actions/setup-java@v4
- with:
- distribution: 'corretto'
- java-version: '17'
+ - name: Setup JDK 17
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'corretto'
+ java-version: '17'
- - name: Setup Android SDK
- uses: android-actions/setup-android@v3
+ - name: Setup Android SDK
+ uses: android-actions/setup-android@v3
- - name: Grant execute permission for gradlew
- run: chmod +x gradlew
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
- - name: Add Local Properties
- env:
- BASE_URL: ${{ secrets.BASE_URL }}
- KAKAO_NATIVE_KEY: ${{ secrets.KAKAO_NATIVE_KEY }}
- run: |
- echo base.url=\"$BASE_URL\" >> ./local.properties
+ - name: Add Local Properties
+ env:
+ BASE_URL: ${{ secrets.BASE_URL }}
+ KAKAO_NATIVE_KEY: ${{ secrets.KAKAO_NATIVE_KEY }}
+ run: |
+ echo base.url=\"$BASE_URL\" >> ./local.properties
+ echo kakao.native.key=\"KAKAO_NATIVE_KEY\" >> ./local.properties
+ echo kakaoNativeKey=\"$KAKAO_NATIVE_KEY\" >> ./local.properties
- - name: Run ktlint
- run: ./gradlew ktlintCheck
+ - name: Run ktlint
+ run: ./gradlew ktlintCheck
From 7c9bba2501f3c029b6e9796552997c1a66acc166 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E1=84=80=E1=85=B5=E1=86=B7=E1=84=86=E1=85=A7=E1=86=BC?=
=?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=A8?=
<75840431+cacaocoffee@users.noreply.github.com>
Date: Fri, 12 Jul 2024 04:34:06 +0900
Subject: [PATCH 35/36] [chore] #4 apply code review
---
.../com/recordy/oauth/di/KakaoAuthModule.kt | 3 ++-
.../com/record/login/singup/SignUpScreen.kt | 22 +++++++++++++++----
.../record/login/singup/SignUpViewModel.kt | 4 ++--
...SucessScreen.kt => SignUpSuccessScreen.kt} | 0
4 files changed, 22 insertions(+), 7 deletions(-)
rename feature/login/src/main/java/com/record/login/singup/screen/{SignUpSucessScreen.kt => SignUpSuccessScreen.kt} (100%)
diff --git a/data/oauth/src/main/java/com/recordy/oauth/di/KakaoAuthModule.kt b/data/oauth/src/main/java/com/recordy/oauth/di/KakaoAuthModule.kt
index 97bcad26..166e8130 100644
--- a/data/oauth/src/main/java/com/recordy/oauth/di/KakaoAuthModule.kt
+++ b/data/oauth/src/main/java/com/recordy/oauth/di/KakaoAuthModule.kt
@@ -1,5 +1,6 @@
package com.recordy.oauth.di
+import com.recordy.oauth.repository.KakaoAuthManager
import com.recordy.oauth.repository.OAuthInteractor
import dagger.Binds
import dagger.Module
@@ -13,6 +14,6 @@ abstract class KakaoAuthModule {
@Binds
@ActivityScoped
abstract fun provideKakaoAuthRepository(
- kakaoAuthInteractor: com.recordy.oauth.repository.KakaoAuthManager,
+ kakaoAuthInteractor: KakaoAuthManager,
): OAuthInteractor
}
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
index 74aaaa43..65b286f6 100644
--- a/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpScreen.kt
@@ -106,8 +106,9 @@ fun SignUpRoute(
modifier = Modifier
.fillMaxSize(),
) { page ->
- when (page) {
- 0 -> PolicyScreen(
+
+ when (SignUpScreen.fromScreenNumber(page)) {
+ SignUpScreen.Policy -> PolicyScreen(
padding = padding,
uiState = uiState,
onCheckAllClick = viewModel::allCheckEvent,
@@ -116,8 +117,8 @@ fun SignUpRoute(
onCheckAgeClick = viewModel::checkAgeEvent,
)
- 1 -> NamingScreen(uiState = uiState, onTextChangeEvent = viewModel::updateNickName)
- 2 -> SignUpSucessScreen()
+ SignUpScreen.Naming -> NamingScreen(uiState = uiState, onTextChangeEvent = viewModel::updateNickName)
+ SignUpScreen.Success -> SignUpSucessScreen()
}
}
}
@@ -160,3 +161,16 @@ fun PreviewSignUp(
}
}
}
+
+enum class SignUpScreen(val screenNumber: Int) {
+ Policy(0),
+ Naming(1),
+ Success(2),
+ ;
+
+ companion object {
+ fun fromScreenNumber(screenNumber: Int): SignUpScreen {
+ return entries.firstOrNull { it.screenNumber == screenNumber } ?: Success
+ }
+ }
+}
diff --git a/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
index daf2df70..bafaa4bf 100644
--- a/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
+++ b/feature/login/src/main/java/com/record/login/singup/SignUpViewModel.kt
@@ -91,7 +91,7 @@ class SignUpViewModel @Inject constructor() : BaseViewModel
Date: Fri, 12 Jul 2024 05:16:47 +0900
Subject: [PATCH 36/36] [chore] #4 apply redesign login view
---
.../src/main/res/drawable/ic_signup.png | Bin 13579 -> 0 bytes
.../main/res/drawable/img_bubble_checked.png | Bin 0 -> 1678927 bytes
.../src/main/res/drawable/img_onboarding.png | Bin 0 -> 2276895 bytes
.../main/java/com/record/login/LoginScreen.kt | 19 ++++---
.../java/com/record/login/logo/KakaoLogo.kt | 49 ------------------
.../com/record/login/singup/SignUpScreen.kt | 8 +--
.../login/singup/screen/PolicyScreen.kt | 12 ++---
.../singup/screen/SignUpSuccessScreen.kt | 12 +++--
8 files changed, 28 insertions(+), 72 deletions(-)
delete mode 100644 core/designsystem/src/main/res/drawable/ic_signup.png
create mode 100644 core/designsystem/src/main/res/drawable/img_bubble_checked.png
create mode 100644 core/designsystem/src/main/res/drawable/img_onboarding.png
delete mode 100644 feature/login/src/main/java/com/record/login/logo/KakaoLogo.kt
diff --git a/core/designsystem/src/main/res/drawable/ic_signup.png b/core/designsystem/src/main/res/drawable/ic_signup.png
deleted file mode 100644
index 3448305279f73ffb587553179fe2cf55acd6d88e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 13579
zcmV+mHT24fP);Az`mMG0{Lg1Tr-sx(Dl;Jr9gTEj%WbdP7n@uOwjx~6NDv!D14yJvpC&h87!{Js
zAi;=DL<2Vp+PRRvP3x7Qm?k7Z=BiX`IP*FGxaYmsy6;;1Kb7?JBv6&4fPS9rs$Kto
z&Ohz_u5Z2H`@P@Vf3fh5zoqEe?euKVf_r*4jVq^Tx6`&g3+`#$o(1KNg9Ib_`J0DzJ
zJTIdkq3wqb?sad!v2oz6=lrbO^q&8PFWvd#pSpBa8p3
zIWs%=vdK>KWp2$r+pW1dcX^l#Hefc}^ejqki{*;5LRg~UQpuu}6y}O#UJ}nGld9wl
z$8T|Fan9|!>$|EG)FFNT&FuWdtCDC>@0LIR=l8B{Y<~8QZ@lbljIkfMD*Azf`@8S{
z%L~rg-FeNzRP$%rH9uyY4TPY>#3)vRMNIIFF_}4zQ#g*uxy2-7909B(%X!IoDFCLl
zxdc+BrI=zxSvVjHo)x)6f?FjoeP#*IZP#n_o!Yr`JEm{=>%aN?(Put$+oz8nJ@(h{
zeCMyP(hq3+fq;AEd%k$~x%)bAou6nvzwO$wC-@Pmc)uhS2`*x;C{>InoLEkb7ogUn
zRCtE4vn(xvV?kN2$|MEGsU)DunTEP#f=VecNL(<7gOeRraB#DkrFO9W>!Dpbjm
zG9%XpPDPpIAXY@HDhj1#L=GL0fO~UG;gcB4k;CO?ix!SyHGX
z&(%-~)lUjaOG0p4%2-mDpUR3FT#GsZ{2LL_|S$l?CofR+c5Oq!QU_P-JS9
zGNyl)nNohhq$oiL_*)d3qM_AD2~lJM*b@WaI*u=xo!evy%MvVGjk*`Kn0myr+K_5i
z>{vXhSv>BRS;QNi$&1dt;EL-%eEsuef8%X$UR)f|GqgQp;9m3Z|Mcf)E;!>qG$$Ja
z?pmwNv9@w)_p`7Vh`fxPtc)|{BobxDY?X3LmJwH3j%o%#2R;q&Ooe4h9-b>j{!96wJ5>nz
zzcP>YIjx-}{jJXYYOQ
z;;&qF)#71#n%mO`_sVyF>hkl>+5P6Jsm7zeW373%vx(_HP+{-}Tt`u!rA3za5T=_oMc+|g&zF--Fx5P-TdD7zU7y%y6O)O)6>|VmT~ht@BP%TUVLER
zTXs$~54UZ5wWh?n?3dlVzwyE_+qr0+0=_h5A}-j
z{e9d1)h)8$H(Xyk!(U(e%jt0apHDHKO(t2on_KxAUL)wERriBC~c){YhwJS8eTOCY3$aF{E8G3};lzBL%-!)~9+
zVl&Ly2BgTEOML0dAu1YHOuNYl~!3e_09ZPz*He|BMh=b@Qh`@Ys*
zIPW#_+SZ?|jg=3Vo6CE$URHKDlA^bnmB-g2L|Im1$`=XJT{23ba-%%PADN*j&TI%b
z20`Z(mgoMAK1KxvD@}c;48Tc}7;OS=cc$gBN$~S1AJH%w_QO1j`-xsGw(M1i%dI3T28C60^KAX)Nz~(s
zOenP!`AvsfI#N+1C}vI!lrX~dW+aEbUuH*+`L(SwOOFgn&-Kzh7ryvEq?_yC&C>O&
z5BCT1*f1_PoVd(t4_A)A=z*^H@gp|-4&3q>Kopd}$adw
z5%Vg{3UaK1MRCEn)kH>gEzz12Qw!(s8>Fv&7tu}skxp?tmyW->_Acrc1KE>6l6r-?ch6c9iraTHykN{B7^hM1lbQ&VXU1mIey%51p*I4X1`E5s4Z{#rlgbn}Sue?DtkTkI
z*qUZPp8_mMIm*B!Dc%HZZKy%JYgwG#Y4zv<9Ad&yDb{lp`-_rq^8G-Yj_8&(d@#<75~klu$$M
zDHueL!^nl1g+zf!fk^=4MFX2*T9ySOtjKVpn3(ueB=PJy^@dzPO*|7OvIFK^UjzH8
z?5mjNKbdWIm78@{h8@LP$w4?VBu9)}l3^K==9;ifG{^vaI2@@);D5O+K9TXB(5z+r4m3XaI%=4G`I)n)a!Te>Dcw@_A$6j{f$u+=4m!^JrxbZBIg}9DV7sQ18a;eX8aa1
zatPB?>NmlZ#9TGgMRTF!K={<$7XQ#L=x1ELQy|vY~2QPouyDz={
znyYWU`(!XXDR37T-#^oL#H*%uF0A3mv~C&3G9Q&JPf|>$qRC@|WoSd8vqFOhK#gGq
zfDy4m-v{qHjz>-q09cJKBAgpz>p&?h6@eF-NY`A6*ays#RvtV^qcHt$yIs2(?#zRk
zwC-8wD5K4r49)SmnTsDbXplMN;CE~5o+|88TNJvmkp2Ez;lkM@T}BrSmKoHAv=pbz
ze5MQ(m+&M9$bzBciM4WQMQQ1P@UmuFL^ZcFbcEmCF?aUbX!H1+@R66F3~na{?(+KT
zRl(T@^2tWMn-+OL%?q?-vQRn{3y%4u1n3Z9rHUlalDg&C(6})Y=fjM}}f;K}0
zL@eUAvfxHId1Nt$h-Q{w=M2W$R*K)Etm9eNt%=THYT}H|<<`O_zx%tFUU=Pg-#>c4
zFSs|}_-6}W|A)W(F|R+`y7SIEh8JFVag?}aGgn0DPXq%BxIid)=KnPn>hBN@&`5?jh*F|XH$wy+12
zGY8h=^`mdZ0bTL5!Trty5B%?=QO>=!qk{t%zGwtT3lebz;;JV~&v{0f?|Z31Rah{-
zkfF8Y84O5MgpptXdJqD1Ohmy#R7{eFnQ9jnmw>UyAGUB_ujdOdfg^@?XQvF
zg8u?e-dLAauYl
z!m$zrIK()7x->@5sTg_O8#L;3u~PPB^mHQkqc{Dh7iZmpw=g?9!ej}pI!{_&J+@$`
zprFhfL6AY&7ct7u1fP!ajfem7AI-6Cb~;R(j{S)V!`F>QmuZUV&>=)~
zNA-dpq*WU{i??=Bt3Xj{S53+iN-SX+`ph0Qv0sB0DIJ*$^d~^Z3r)MokV)bs7TS-;
zK%mtjvVnpR7jC5KH8)&|BK5md+#f6xutwc;P#i7e@Q4cu$hP~rf;m*#$#;gNq>L`a0i{!I5_?S|cWz9`6Qq43Z{kkW)6qKbvnPsfeZkC5oqSese
ztRYKt3%v~p_!`HwM6iiRbxHDve<-YV&{F>Anze^^Z@6-;>gUri9~19zBao
zcZk3Yr>EPAit%C1dKP$I>RMKAbEoi>Wm<+DvqtH@BHFfbl)#6LX*7&zfW6xvX&=?R
zZ-TNk)5V0Y`4O=K3IaVg1ElUrpvj|qjuegpS~{``4n9cH)`L_l?jfEnofnOgH(J7J
zKK@uWxDP-4FzDeB?muj3LUXbH)6;)?I?<(Spy>fUdi|PS52ZBMrE`Xf6sictv#)
z9EPQ>`*%1XWl>oxMVS^d-;DB7KV6Rc$TfD<9TWp@H!h{`u{~+z-gL`fUO4E+bIs0<
zd)u?K>14Z}GIU-7;p7(VXveZa4OC`sk-J%5dLodeg61t4fyY70C>-a;b
z*^GA|I3v?y-1mcAuZDqpBGH~jfC(5+2yrwLIUX-d6`LamTQu5jve9DI?!Q*G0Ed{s
znaxfEKya@9(?#XxqV6A{(Xu(BDI~pgL)o=
z_IQAGr78awN5R=
z%q>@!Hqz-`qKM&wBuR{RtyPGoBkPbw$Qq#70*p!{t$Z-`s586IfQzP~F{{yYG@feE
zXc#LHoiflzifO+=haP#DR=STu(_RFW8nk<1FP-_EAET}8>$Ge4*%Yqs+SzWmS+Cbq
zCkOBrZEkLw;)J^UbO;+UHwSbRx22q94bZ_|q8cUI0HR1}`?3r}rLCYk_e;Sog|?MK
zi6nc-v^8jX4(At>G+SCbo)JvARQsqx{1o2%^QQ!^Q>(qGJvFfj%(8X=8y|!oBOF3khjS<4E&o+ml^dZ9QHMbZ-
zC$fagjbaF=Ih1Sb>vAq04WyP@s3)|q8=>QX>cSW<_4X8XCU($+4}6#EwTRlyn9ewJ
zj%Ii7p$8v52uU_e7Ft5}T8)+t52!?f3%prGd7=5(nxEg}96NSzOy7Gu0k8&F-|vp8
z0U=B^H&CwDW__1=UZ(0MhYId!&P6=F_oPG61E!A1c^=hRLpCiT~He3gDyEF!ug-Dh%1?{?U
z{-x2AB4$Hf?dqO42On6LStn;?l!ubD(W>h;pEN%YDFofSYyX+X%sF`EFddi%xLW%{
zievwwE@>-QczsR-5p@7=4FgZ`;QzVO%?
ztqWWJTzkr*+LUrciz}vUhmvNJWM?oW;ZPsT66v{^
zUKSO~f^D3$!ndr>;^HF5E>8;FsGqeHdyuz-7U-MhC9vffu~HSv1#ld;2GSRcmba8u
zw4?*joVrva0#U#tg-7Li`TO|75K~Jtu1^fZz#@29P6uCi+pRxuQkQ&?V>NTsRi=*t6lElOd)$PpqHTbyCrAyhHuv$9g9NPoXmsxxK>q33iRV7|
z(QxBUh{qBd3sCuU@J1ry?nThsPM_by3DpROY
zv{YL4GD9aN3}|DtMF*FLPR7Yvm3E8eSAPF?HR@<1BwLq*Kp>cCq|56$T#?N};nT6gP
zWM#{po9I0EvW<<^&+8Pz8=$V9fB}RqG@4o*jiM*Q@d?3oU0*Z;_^ZCJYQ6_aRg)CdKs*qLyabrX{OdpU5URaFZ40$CAG7=rf7PmZM@vltPq7^2*CH9b+I`K
zx7MURPM!Su1JsSCX=%AmQE&$(^AR1q>i|u;ZE8*S=|y{w)5`jYwl<$njoJGNmDB&Q
zNMq;DbHyuO^NyQ6*L!IWP;fW^XAG=*3`lMKltl%gt_JBu)Kb+T#;_^_DjXd{lI*Z@-$x;4at?a$PO#lQQFKl(!rY*BIpY^fLO
z8UECfhuOlJ*;(b;o9>X-J36wrcf-N@A6@|s#7vq%3}My?^D9tcR(ERfl=Qj=LK$D9
zn%qsj)jq9=P@OcmFudb9$wUMbnKvi!xy)ojX3PNn*@afnC<};bPf0IfhDAq0yCWu2
zr8XJp;d}2hIyZ&KizG<<_C1fj{oQ}0>AnAq+Viv22sF@=z+igqC+WuzQ;6l`t2{|lt3u0Hw#F}OiSH`FN}Q&pmTIB8dJ}|VE1lw
z+(FQOy`IMw#{fAx${_zhJ=&NTLKzvTk3|?Ms3q67EF6O;^vXv)t2z8&izX*rnu5tw
z4=nSz?^TA=>T+L(-TVJ5`8HIWCpz_6u!X0uC9;BcU^Rspo^<4f{cIibMc}N&x9@t8
z%}lnfV4}{DWUQd(GY_8u3Bi}vS9laBFt#mYIzSsG!=+SVpSbxb>efXh*pn_VyZZI9BP_MJb(%h!N|h()gg_xHg0zsV#{vS
zn{Bu^zO6f0sg3!?gL+WHxCu`h+>ImaD=~VmqFEFD?m$=(r2JOjig1GU*(P(#m`}A)
z@%V5)ZOL<3cX^V)0C2z$HjKD1@!aMXs7Tw0wNt{v~1WA$Yc
zIx2%e7ckZs@W<1|)2oZY*3J8OO_Xmtq3#S)F_x>%TM^S0e0r{!PFG#u~MFd=xShby{C(8R)s1kENOV@J7sW
z=x1?0=HYF%z$z`Q7iMjCL)uv0K((J|Q{LKLSvG{6tpVWNN^{4`v)E!t07;SFLr=0j
zA-Es-z}v#t{oA*1Sb^s*%+@g%r$u+YXXgP&ClnLVVVLuVGhbxKFa!F5fFoi?4n
zJ4Up8n~p5Qay<7XB%1RyLc=rf!{hbqX0UV!If%#}d;>?SO0#0qxIup!;P@D{Tx)U6
zx;QOh3`zL8HliAprmXl^8mOxTs*`EA8>1biyVttdkq@Z67onuDD+r|md#Og2Dl!`d
zqqi{}9y}#*^;TofKXKc6o~MLUdbZWH8zPnk9}IK7xYEj^k_R;hZAmzvxfIKr^#lE6
z_Fr==bWs*kvmVk}XSr3^LGQ@;$h$N(-JvPyU!AOyRH9oe0IpB5IENzms~Ol^^KOXD
z&9tWhPEWY*V$=}DuI_zmJqTbx1-i|EK{RV|LGHSRq<5HTrU0;jbPY4c9#{QZ1?Vz3
zghcec(j+sz=>aIA9Bfd_XqZqByQXQ)-FW|p5jldPk(fHt4je6gExRlVZ!^nkN4vdm
zpE9_PUAw1@vmf`{EicL}M~r--l7Tx+260psd;eN3G;IMiWA4LF|8B@KXKQM>M&NYwdM0}Epd8d=+)(7?F>
zHH>9~rjkhWa>e&LVqMIx1Oqe}nb9L#=K%9XD#fxwFzMbFS<3QVrUi*R;>_I|W!5O#
zxa*X`otvHb+o%^_nNK!-4~?^7Xgh3V2{#B>7bS2voO|hD~3dPMT9L48xq&151b0KS_8(nx$WPO{0
z7G#`_1c-#DjZp2LaZ|EZ3KFp3ZVyFDZhCctj8(+|9^XRqdj{pVi(Y06Dn$c51kj%A
zngP%>!lXJ;25W%Bs5DV*W5##^ilijLjG6xl#^XC@Urn53q$pB=Ww`p4MgGS;U5s&T*xLpsz+F(SFEFYqc-a1XSchUKn9eZXcO<4?k
z%Um(6=|ty&W*yX&RCXs^XcQ`y|Lpm$UhHo{7|f=6}vjf$$JS}3>SZPcde2+HS&zj+_+o1LM5wtqLMs;*a28SSm0kz-V6
z#`ZK-88_9Q((5TKeQB5etYX@>FL;wj|KIg_8hNQ=K{$+Cy?+0TPZ`|Av2N!5!N2hW
zzfmvaUJ$e(f!vqsL;zclY*DQ@kmFrfK=3!AE0M_^oje${@VJaclxX9ogP&`KI$@kt
zP^uIER`0hBFPUn~T++a}sp9k%le({_fyi8gtly)?guLCuS{0UAwJ
z8i33DXo!C4?ni0=Oh6Z$(MGaGxeaU7#h~f6D6pH+3c~xtr4!J{T4DH>G6jrnIrC+{
za6uT~J#@TUeH5jex8HR0x1KV%SHI)+_rC9jKiUZ6L9-DwgNENYH_OF1(zx06yw|~H
z05si)O1xL@Q1uotWllf~el|8$rK(obsPQdPWvrOeS$`FXzM|K>T?H;513gx%
z;8eX=1B0NYSTE5Zdjxr*tGeoT0%BTURD#}L#RpbQ4;*;qqX4+?V-%z$eK$y}?ZxtE(+pr2>{s0xJ2
zfT^k}v}DZtNma%1cI!sVFb9#C>4ksVlK`lN+#bkkrZsCG?Ve@hWmO|54-OR?iE*D(f`OF|MAT%7r(UDUm0}V
z;AQx`Ibz$E
zL==n4iPMV-a|?+$ex%spFWn1Au)R5qrjH+A{X;s5?WC6NyIJ;07BpYo?H+5_cyJ8I
zx3Rq0n3`^O41KvsVvJYX(*UL;Kvo%j+tR33UsTMY8PnY7?8NiwM6L{lDw`}pPb%I!{$Og|0?Iba&7B4
zt#5A7Fw|>tD`U2zhcN)W(x?1!9RYqKviXVUZS$V742`}WFVHjlV~=e=&qUbvV^+nz
zI;ypjFi~iYZ|y3%TI1L1j*b4kmU8;NH5GW{$FcG8zhB?piG-`@V6uaPpDDphiHz8T!P($6kV!Y<`-u#^gn
zrgc4^1kS3W1!k_~k>z8}EMxmsPRV2RG1j-jEG5;-etSK^cz}q;hBrH*hqoz6omlKh
z)tf%1^2UV?jiufAalP>>j&;{WtBTPmq8!cEWY7m4#Hbw66!jC7#30yO@?X}E9c|b_
zdv>WGe)3D7{LB$L$?c@U)!#1nzMDSrTQx8Et6n+`JDz`U9Pr(iEa#KZ*iJO+CbS0a
zDYa1x8RG(Ey*$bHoD(*nGEUUC(iof8?6E?^l+t6)Jkd3vF@HbKiygDj2`=BhZ|0(6
zkAW%1SFbBsNj3EM^u^UF_ApLqfLSMyJ6xt+Wc^hnF~S{oXaKXQmVLd~)lInx}PHtFKrxi%fMy8_s;JpfLPA_Gr1`6FSi~cznce4~E{g
z^fD{j^J-Ol6lZ9ZW+-`6vtF2Fb)8&cbU6UUtnvV?zMM-pL`O2AX#m@4mETo=es%
zcl2%=jpzwQI57l?@gLOKFkxd^Mn+}{Q#u=Ofr%5*yiFTs8`s3TQ(!8&vbsXkTs@@w
zY-VACeC&0+QXf@!LX9I|FI7?IJsiA;trw`EPv&x1n*dg?S+CXe4emw%wAvp|)SUW4
zJPNP9{@UwLDv3QUa6kIdkEXx(;kUdcWX|V1c6%0;=TfUy{x>vv|CLM-1(;Gg+s3Hm
z93d+H)4W%zv0PF{4yo$At0}JsASYurnyW4iPqONoVcK39!~Tb2WjpIvx9V{N@mME<
z>-G`bj`MN#r~7r(<8{OMV1}-49lvYlquEaUtV&948|s{oXN
z5ap^aSy^>o(}3O`&;||@QH%G)XGj5y-qpZLcp}N*jJfhw7p;!n>93H#t?z`W`
zo}@>1TENxY?_7P|cYAAx-&UsK6zFZP=9WwCcK%ftjRd%aG*i!Ls*$2*M>7(w0FJ$C
zcT3a#HB(mK>Zlt7O6Cf8S(Vl%8cqFWIFhNycGHiiYH+H-*nXa#iugSI-X1?zn)MIh
zR=lo(&(Of?3%}8*2LDIYsp~4NKsz?>P3~r2bX?2X+KT3rZW^v_4c~;$?o<9w-lz2i
zLcej<;(uE{a?hLdbTFM2Y)8$PtDTwh^M1gF9y$eWKc@+_dje0J)TLS6Y#ETNs50vd
zxLM0)0Ou!wER7`F-pwDK?Z@{kU!ww=tI}NE?qDz+fG4PWO;%R!m;glu_&LzgEcMkw
zXo#cd(15qlZsr&S%#a{EI=|1o)%87Zb!B~5+Kpm)=eyrER};?R9_u
zsdv2NQZx;3qR!+_X{%L#s{Cs=r01%by+CH@o7#l|H%6yEh3llH7v)vL(pM%FdZi7k
z43@&M=3^G5W)Lx6SjQ{rN;++s@5G?->KWYXzL)-T0Kuv|9zqz9X0R=WhJOho6clc+%||{i4jb{NbloA+C=hD4zwPyFex=(JiZL9U&lj@80
zg!XL4{DpC%nq`c{h7*OffPt;Qb`h?>_6)QOrn?kHCEc`LVIo-z{;_T~rVIYj-mk4a
z-Eovwr7?a7nqm6OUhUHGIyZo$tq+OVa@f&bJ0|}DK6BJvT5liOSe_YDVHZrj0l@wp
zJ;U2+_=;Ck#k}u>?|##lo#|a45)<=#o08Vsu3QcL^3R7c-yiw%d0C_;vbfL-&?z2Q
zVA^n@Oiy=4DfSqa`S5!0H*o9P4fW^n^L$`l)k_4a{bYa$+=|y>^=?vHE;^C=Q
z^KP$h_qSFyTgwk0+noqCJM`&`0aqXW#Pv5kt;F?Y+iCl9;w!KI=-q$u7nl9?{m1tI
z`sC!!*Ur>y6LzUK8cx3E+v?WB<9UBVZG&kr`>8i0^>Xx#aZLfgOBW9Ul~kMjh5W0
z#;++H3Ei)3}}1uho9#E6wHdAAi;2&)$5_)brl9qci(2n{I6ynzLJ4<*4DQI|G}4
zEy>vqmb0D8Kbk^q}Spj>#~s0{wjc}qnq4tEP09O
zO@zfqHs?e54!H01ZO_v7mA=?iuc7keaIj~vwOQX948cn39;+j+ZSQaY{o?Bu6Z!#d
zKhXcm;Ny$8uHoiJ?4SO3i~sfoldYYvsQWq
z{SdYv*8gy#u3!9|zDUnpsCVUiUVC<{Huo=lW}j!3r!n5B}aw_v7aN
z?Vn%$)}O8|h}J&e3Ob0swr$yMJE+z4!e8cTk<8HgfaEXKitVVCh3M$&D;ID1k@|mm
z^!6k5A0KURfBJ#1=%tI_rvJ&er|m5~yFK~#EV!p}dluZ&xUpydgU{2q{r}HBKvjVF
Rj>G@}002ovPDHLkV1mFy>yH2c
diff --git a/core/designsystem/src/main/res/drawable/img_bubble_checked.png b/core/designsystem/src/main/res/drawable/img_bubble_checked.png
new file mode 100644
index 0000000000000000000000000000000000000000..bfc12fd77db8780bd048755d25850a87168393fe
GIT binary patch
literal 1678927
zcmeFYdo-Kr`ZwO$d(U)c_h7~xv?$X9rY9NIAcX9WwyI8pDW%A?ibhCEoPs2?=TJ3@
zDJmo(MNxH{HVA^uOjW9pL>-b6q!ki`q!AK1zuE78e=~c&YrpH=d#&G}bFY<^=eZw;
z=eh3BeO=e*b6rpV=Yc-E{%ZNxZQHi(@;!GtWZSl#_y6&E`z_NFb^A=OR$s
zw(WQO$LEbRn|~QXk#T?X
z#C_AAW*6<|x@-T(U%&hFq1|pf-9Fl#>iDPcKLnxH{Z(nI%=-`eRXG=@c45ileKUU|
zmehlE*zlm%Y%Zm`bFQ;_MO07t$IbsS{;Qv1^%$W9~St-
z0)JTG4-5SNX@RdGxcWD?ZI$YMaYrYD_O)z=D(K42c0F9rl3UT`R-5A@1cPbz#j(ye
ze*L#EIRX4%PfQ0t9n3oQ=D$pQ<#Tw~w$}%nxt4V1KmOPmokr4b2G{MNU$+tp49dqB
z*j3dn@{1Wxb33U{F)RD$-8ocv-^rjWeaFp$cv+b*jyqAKWW24kW5GC*cn?xLaMm#6
ze;a~d!hx%V-%Ypm_Z0M`R~}60D<)z0R6hw*=2_gPlj;m$7eH*Eq`FHvdTd#BVJ7CF2L<-9P=y1N>C??;a?jj=R;bmGTBY
zl1tj@UM+Gf^RV|^E5bc
zleI_oh+3}g#JRYRA;
zl8wqI#c8R`v9o53@u)|Ekj0p1j@i}Eyn1`AW0jPNBuepI@3iS>p=?l$Ew}slW?jYf
zrXYW#D?f`ADDxp_Zt~%|pD=E=$Lyoihg@B$&-wB#pXVG8S>OAd+OiVQKmYpRx_4jO
ze(~#>=^*O^fJsjIZM^=(gcSpDVry0{rQzt8g!C;7`a`HNFE7uPo5f?3p+W~&EvHp}
zGSeuvROw$&0d17C30LalwtlfJ4mH`S-s7|@6U^PJ?O;vawa~Q
z(iJ;|=^L5eWR>Wtw;@HLByWDY)0}cDftT?xY?gGHrwpdB-*ZXkpE2un(Tl8lq&?CD
z)zkL{<>o0c?ZsxtwJz+&%pEj7XGDYHCsf7vJ;OdSoWx(t22bvve<%V0)StapgU^`N
z7d>Pkc)7U3OmFq|!uEEh5$b<`+(^5@NYN!c;me+Hxz%CJQYXobey_WSa_#I7{D?#P7iLSRrjt^3ajDe
zFr{{YiCs^kHLyCTXGY>CZvkfGIB0fqDW?sQO@t>?$Rm}3=n)~<$4spF07M%oa1YOm
z-f-DD+dy_%2gKcI={b#LpuQ#hZ^f)Wj4;T6Qth%Cck9*Gyjd)isl{1u3M}WKLS7ML
z+!D8V6gtfM7wf&F+y3Eir`xvKJlS#NU(dnkVcT9ZCXfaZa<^%-n6(}9gpn)VLyV?;UEFdI92_KGq6mQFme93K
zISu_{pJ)k9y;O@WPb!KnBng{_W>S*yGvQ6}nN4*wUB7S%4pE4zCIhlC{RL
ziN>%Sqp}xS#-3d>F=ETG3?MU5VAXgR)kpRw+BEM3vZPT8$UW9MAZ
z>>mPHI0`MrQDV?XL_C-rkOgW+<998hmi=f@;p6?0*KW9|fUbT+sJYU`)T6PVc~m_z
z=zN@_7`QS}rt#BXE*taUI_LH(NR$w&z5^X*{zGK`=g?jJ4;<)MwkPN+ljR4707Wz$
zvXIuKHREMPR2vyibDNO&OW`?pgj!gkUyhr}j~3)tPtFL%t`YI$m9Mb~a8IiCwU7@`W$>{kaKRq+L&|Ql`yd1+VxH7TBbE&fp
zB1*UWG5I6eTB+9x1hn(EmpHZ$JdUOgjf0R8f&^pUel5LsrS|hCzrjXWQ75~xkCTTf
zGcHV>VJXz4^k>$Y*i7~7lZT;Ej&^@N4$OfQS?UhpI*0ip-axW)+|&bCpD~PA3*r5m
z?2S*Y4X-SXI?i!Hj1Yj87pT>U
z5m+tO<34)7Tv^~0!>97PxdWGkU8Y;s8xV!GuENgVkh+C0Bzxo`MGwD7t`+sAh2Fw9
z+cDbN@LW>j1SBZ**!6VaX~U}r#qye2M%MU7sMHR(-In3sLx;{6&_WA!34p+d(#O$N
z2fa4m6ObEUFlzvOZ0g@rr*%@!+<87Di_Rp7^X!IfZRX#GEJL`x(+LnHc;5jW?1T|q
zlw$A7^S%YG4qFh|qJGJQv^W{or60gIqpcEBb39jTMajx2A}FWAm0y)woGf7V2+Vg)
z9+nO3XRRgGLnW$vqL|*)TLfxQD!?^JiLPFAoNwFhq@6XDZBt<_`)%vv1=$iPiu@VB;#Zn8e9jbD;GnRJ?fu+^I$m9
zf8xR3o5QGPv!>*L{!M&!n_T~TRm|JEaZ7r4&P|P~=T1Br(4$)XG*0hT{iHdl{Yq};Q-P|U
z{T?I-UE~gc#_Nd=JSXgu>Naj5DXUQBUD!F7?b+Z$Mt2sFuou_CeudpKMFcqr$X+R?
zdz@h*bFY6-P=Fa(RCJ6Mai7@vC?7oCFq@m=&UNE3PYr(CEb$s@H}mF3tb5MkGtmgf
zav7(CI(ydVc@UVt>-VsGO^DMe(hRy;aw
z7|l$9sI;k_L-pj?*+>*UIY;+tHliG74q_GA4RgJ%axbs`EUPPdJ&EYZ
z&agR{R1LX0q#^?za`oPGh2qSBiPc^Nsv0%iSocf$#_clT0qS_fyK=0?qk+x4mKV|BgBU}IBUipXgMKZ0`%7alovxG^7c5M
zZn4SN-P-9*Bp0B2@-aYEi}ugO4;LcWKE*ktmM`1-u+vnKcKHlOVoLImm_;P!#jmTn
z4VU;I?A0yb59xnSY<&->mq2mpg^;b6m!OeCq1-@^5?+3RNh#Dm!u1Y~&ji3{(!GzJ
z3|h1X`BhT>zJDDK9kO@uVS}mfk&9wC(C){bR2?TH8gtCmoZ{$01IK&VzzH;JkVQ9|6!lb4g^8O41!^)4HmMXlZgG>OOfj
zbsyb7MhKH0jCmyVBgc*;YgcQ^U9y)5VE%MjoBD%jP=Z<9P4~y6;=SCl1kxtor9E+~
zB}aW^Vqslp!EmR+JSb>llU&soy1W@c8KQGiukhO;r2wm4PoMey3iH@pC)-;YcwfxtztR6~+g=8r|MO2lw^VaENUDiasvwjh<|D0yxW#<0n8j&JIh?Fxf3k*+
z6i%O1SaSRzae*FfayRySyy-JwR$PQo5fUqft^DseIqXh8rUHmuyeFn?+pgpaWW@Vu
zw#K$U>%~Td@J*HjFZ{OR8Otjbp^Uyo&lvYHqXs>S=a)UT6<;%siMtoD@CARr>9fw3A4iIAeH(&g;75k}wtriRL@@ybvJ?EP~vZtR5GAk4Z%kHK^HzLD!X#I!+4PBNT4?ois2)A*AJI
zpjdA@0_zNuqh`+yqTFiwNJh+Dad2aF>LrZvT@=mUE0L8TnDMFN;NtU14OdN!Uxa0&
zgG8X>r7^{YmP_loY^J&Rdi8qC5Yx=$7?vqDV}sib>k%F;a>UbG+U34z;bm%)m#=uK
zCQVpyQIclxf#rFejUXj
zmfNtaI;qSc#TEtuj9cw3DIQV!O_Q*p2VCi+_vg#wD{4PK+z2GGg^z|ZGsP)|j2=*X
z3f&_O-dAS7a%P-`*Pm&fmzOV|o?xw;IHjn$=o?_4QDP3%o=@-y2j
z)qu&^Pl6lawEKc|b&lrM%xPA!SImKdB&Ye1R9ZMMc>=aFD(=OkJy)@YtT}C5%l_l|
zUC8VLQbV$9&hiOy>ciT=VX=1BOmsg&Ji~*x$FqNw)QKOdt>UclB{?HoD?fOyYFnJy
zs3H8W)64+()l|Uacxhipr}_gtX7ZLRrvO`R*c5^Ylo;bha2lBCgN%o`a?*y)u9ltwK+5N55=+VBOf@4bwDAR!9~3MW
zJy@8Pz;AK<3f~lI4&+qC=zg}eEe053L^vJ2O^(yvF-k8@iOqCX`X<$H>x?CBnf;!I
ze{b=7HK=UNr0PlfRdcimp*vOvxhOQe-axj=7q{!_wki8!@`vkldTuBt9N*(GVJ0#+
zwB=@ULggpoD!oz(mv3(MEzHEBPxwS3u1LQyEk8#pt@G#Ia#8_um76!o1F1K=k>|N&
zd`hA1kQ4Wa9dxj7TE-#DOZpdS1Y56mCl$@s2hLKFs}354w8N^b=>+g%q$0IQ9*)Qe
zzTXH4(7_8Uq_q;PgX#{x>vD|WzVGF
N+U0#T`RkzIh~YH6@=2u<;iO(;Z<
zRhRhlx|)!3R>FRGOm*7SLXy;1D&J0qar;Q#w;(j)6@VE7Btk%#<6xvHo(%>#Wm1`P
z2j0Uc%ze$oxph-c?Y#h9<6kbMv7nuPl)>Iv(Tu2ms29(HRS(bX1W|{X!H+m&3urd8
z1jJHj6i%OblE{!RGE8v*6;Lv@@tTIeefyne`E=L|3g(T
zd+RGmcqex&LMJd*(NU&^=Y)RUQi_0Tk=$-1SvPr;b~#3fhOyybM{VAH%1O*%eX+cU
zTfy)29`Pg-dxr$M#%_}amT_CL(%e2Y!*|e=aw4t(qQhPKj|(krIj9N2F4|2~==feo
zY{pFNb?)ye+e_gb9tb|4-z{r*QQNJM8b*vS)qCI=?KgHqtFD;#^M%sM%w}bapeJlYJ784wa`&Gz>#FAevo+O+zx*vh#Kbf-|;kF
zf-dy}2Ow+{Yrp(`x+>ah+!e|}y;uY$1&T*{a`qfdm^+Di0bPu4#Vp+Ns~%P)$ZtC8
zC&0~PXAEOkIf{~WcBu3rTYW4MpP6KXY8_(*i+8kVK77q57oWf<1RqGy-jGjTz@qo0
z_I31xRpBf6Dz$T?4EHj6F)3U7m20`K`=qcUb5kn)K#nFrHs4&*k0QM&esi3M`E8AM
z;*4ah)KUCCwPnH_gfC^$QFp-Rn%=)*6*)%JQL_v2dZ-=2ztCK2`j`<@A@F
z8JUhPi)xo|7ihSEcDb}y+s?~+L0|WS=eqShYDtMs98|c?w#sMqhp`Rh^4XL^z%Xhg
z*;M=K$Q!pD00Z@wI8~0y2}`(fUo8rn^@r<*#+!SG!o3USV-pu8cZm8u7_Qw47*`1b
zNc}cYn9gFkR`|gt*^^j@O>VePfh^2~lfn7PlRc*mK7c^^0nym%LEH-}IxM!D^Vr)z
znJosbo6+2=+t2OQ=1X
z7bfmWDbVpHxw15Y$|MMZIIV0yWe*tBp
z-pA3q>&sbL27QPBUg)|)_MpB%QJFYLWljWOy%-_XbQjKjq)R4j*e0=vnw;+pSuID5
zCoD{W$UH>&mB(5P`#6yR3=)UnYz`!#?9)*R?D0oE4k|PiABQrcit+i+AJ_X&R5pS*
ziNgf_=xG)fB{<*2N4=V4q4^)0yoD#Rw5ib}XwWPynDQEg`YLl9HEsfBz4p1>E#}
zf&{7OBG*hZQF9*j*{x=1LAMLt`tjnC8~j(-=|hSyhJZEz?$*gWp$o^ReroC|BGFJ#
z-qvLp2d-N^A|=GkRS3680AS^9T@f-Hsmy4jkwni@{Ks9xT5)WG=Qykc^YlZq%{
zWgeufo?G|Nl7rsMq}iD&7(Tk|wyi*w8Dmd7%4(BQKlCSRkn*--iUY3Xb=$7L$)agN
zLyZp$s`Ca0XCBuSr_+tPC=|5u>2fdWl6Xezh7ZtxGJdS*NkdvCeZ+eqbMeR!CzPe<
zf{jFn2#R0>+<|8Eslk4*S|hXbnOm{41admJli5#Zkoa9woJal-2jyc+mSmgtus|XS
zD;V5@w~K6`EQx?r4sOZFXYl*bM4EbvBc2_|JzLA(&PheI_Ato$rrfg_a(a2MI_H`K
zl*r7W;~O^sWg)H+#2>Gk1stE^_f_&$eq7m=zU0)_NZiMU34A`jA%mFi3Y0W(x~`f<
zP>!n6^Z}c7b|xBTV$^Ymov@%hmUAo7gRCAusp<)n>Qj*@X~$`Hh%*knC{C$vOb*-_
zO%A-e=aJz@^;tf`3tGSI%qE)!sQ>Of;wb{E7j7d`U9`!B=%Fdx>;ygcY?ru)i7C|1
z@Jc|;)b~Nmhny|lb4zkirg7X7LV{>)d0SOm@WU%U
zcfQXn2j}`ueb^Y1vH!?a*{<*Xn-9GAfp2)ry}LV$E`0bAHu>JgPvo
zTTJTbz1$p|;V7(OP~d&$8y_1XuOFj$7-b~KQt3{GSP%Sq!`rsa6l8AuDkn$3$rGA$
zWOKQ>`I*J@#@u|y<*j7DsK_bDl${m~ySC0@i|q;$*-^efXBdVpqvar+0P@X%J0w@~
zUxv{x$%hz>FYsCCgvaD(pQW_2#|(eB*vz>F=+AOoQv`peTCaO}Eak7k8r-@+%1fm_
z0D@=(OO@5fI-{i}9Y`O58YO?!<*LPS-6+ogIF}Z(i|ZIzR7;y747n7vdvr39PV3{Ifo;ITHWy}
z6A1yX7{@>jM6h&`wnpmUG$?wxn=|)LWouq+@2{@Bi&18mRN^;6AGD#56M~7{(FfI>
z!oY`|{_{C7%19<5T{>sh3*~>3{+6POe^{cqcm0PHi0+M9iKuS_jrn9c$Zu?5Hn9=o
zc}8%il>uY5E*q4JyNct}h@gAUsQgo^+VFUdd=A_k`ys0-hLiAGGqB+hPQN*$<)y^_
zP}0SBI|tc+vb0_HSyPwIg-c@zv%}Y?i|3FmQeH{H1j+BtLs5&iq?p2{29BX`1~N8-
zHNK}L)@PB4@QmbudUxU&w9l^Su#0nP@bowAN9tPbe3i|$M#YL4D!|8!-I4;TK7itVI&5c{d#ivGcJ4%3TI5MVRg2&L2JjjZ|&bziOBG=f?}pFO>-&^_8$p7nmcRc06e
zDFr|(Ji{+t0QWnNaRj4&w1=!)pVW1DlRQ6rdX$@8+~ok
zX|0vW)R0T(2&E(4v{Mp@Ao*SpwExzHPOD5(^8%QLSTAVie`J@CSW-%A8_w`J|K1s9
z3heFP?)a9eg^|3~PE5(>%xbN_=+)!G4a(k)sqG$xw$UGi7Pl!15y22YN(Yp*95t|M
zb@h9MYuH}Z^_ED?^PXG5oRD)d(`&9*;N$5Ttrh7P!&w6h4{)@J2RXqHq~ApcQPvQY
zy&X1+g4~vP!G&AyVU}qr{XE^vbZKkc^2XJH813>@36$8Sy^GoiQ1QIrK+5hwYQ30<
zC9OdvJ7ajyTxTVh-!^&W)|$K+@wF8yu-iUwu1&q{T9clxowHjDRi#uHOt=I@CLGSD
zmZ5iRS_Tg4FIH~y9^Uxbr?8Xr!8e{}4P^I3NN+W3(oRcNByxn4`%GKo3m{&UeAa2S{osLx**;Abk*5jxd9_Ez4`L5
zW58VZ`)d3@FLqlD{4SaQ=j>NG^4;5Bt2RyjJ+ksGu%}iANZCj*7TC2R6vXna>uw{O
z4qVr1yCmgUl&fgR*VvK-i9J9bwS5?;m^H_5iGH|eoKL+p&q9(ngp?65nhc7yv
zWx)cg_kHbU^Vv~LpJj(^0LYbLzn1s-WAz-8pahJkQuFF`KSE~CVb_DX3qL>ch6!v-
zHxwIFhsc-k7FNUPtbseEkdtD!Ak#LtZ+ev~t{25t+p#0#1);OG&BVHeKJ6EuSp={@
zz13?`SE+3Qg}yT;#oTtQ9Dlu``DAVUp8N^oXar!u?b!^#MblD{z0p-y1k{YKj(ntO
zQST32FTmR*vU&6?bY^5g)wKJ*x)ybTS$dTg?W~wYjpgn*8r{oX4$Af-lQ%kb17C}7
zU1+L_TXU#D+&G1M9SE0Bp7YdSt$43YMG)9_rCefCo8z^R;Qozq0gw_Fv#xyrt8!38
zBh6S~tK5@oC82Od^BqFxUk9EA9o{)@lT;oQ=?&bJ#GDSj)IKy4PVQueem|EEf|D7s
z&hQgNm8W0IlMyC&)Ztj{u5Y-`MW-~k;#tD`n;Yrlpto|WJD1|Q4<-{oVpam%>rVP4
za0B4d?WTk-9!()0C4^Es_^$VQm!q)PdT->ZKbEh((zH9u)4C1ge!6_YyM`fi+&YwV?+D;OFaOm4`pw_9d;D|ye@8H~%7h$-oz3i~tDiLk(lH1_8HycK
zS}#YcsaJjTh<9<3BotRjwB
z^p|4UE*4{)lMZO5rgE>upB|1z*T7R4jtm+lWwsZU
zD86%5P2E%R`qQS8^FvHVXzClpJB9u$j5t1H$M2fX}+ypLdZaBHbgQ9nK1k{wQTJikK*2X
zoS=50g!NC6Y*FR@vR3rIpA5gW)inLgMUp#(?#^w+@dNQyaOX~-r=NcM2W#8D9$SJn
zf%WOqOdVeNu78!tk&uAt`Y^}m!ZL(coA-#&%!cI%($QUX58r7!joK5q>E_3C&O+Cs
ztB|(-)t#A5Di-3Wk1t@v#^yVl9$0xW)yrJaUq9n`NrD?SUQ_Uo>v
z*TJ`*ZBMJ>WcYGNsrJHYSyjV*VB^mTtrXvo_1@ic;ViQT&db%@#VIt`*=47@zz3hb
zJEw6hrn8gm%4(+!Jz36nFGX%1*+k+S6i3>8PYrxD{Eq0tO;O$lwd#^K?p~i(`ed)>
z%-lz5yD$Nwr0wH%m9!>M1!~EkhKz4%0PSD0xf3s1>gexEOn~(|Y55)9@kT>)0Q~J3
z(O4hbiJ(hl=eJULch@xTy@|>vmT&c=T!IA=$T`NBLu>84M2Hfssyni|0CqUsSkW_h
zW&InaV72m{ctP{V`*Pq@W*O5IfT|0AG)r-FU$HNZ~%+F9n)S
zSEm=%z;deUIguyn9T7q>lZ9up#N}CZNN!?2ZrnB6aL3Njh0IA${XL>uUjBRR{9m2Z
zYspWhHcuOTw@o#6+?-5~*1fVTN>K$lro1ixaj;%wRan&_Q!#o6^A4BU4S@bK++?Wr
zHS!hcd~$Tqm_hCOELejaE7Ue1a}R-vZL5bbYK4bwBR+?tD=BdT|
z@V)lKs)1`@X5^hHy98>_52Wp4UrkcyvxMPLioN4f_cy8#{x=1!gX2!V@M+&cxoOR=~F#p&jJ8!a+q;n)D3BCw4+N
z>vqmM?dS|L>x>W&b+34b6Y|&!`fN;0>2F(e#prt$klP!JHFx!UoX(;%Za&wYr4uc`
zW=p<}@D_L8;Bp!3B3b^sGl}HR#6YK&y)sM?OYq5)vIc$5cmghjH$$?O1wdHL
z&j#-&v=f}Izh?Kl&9-wBv*_r}@!s+=_^7q4ZkT8A{!yJF{ka3a>-l!dC%`sONk2L$
zx`ZU^3`O#$K6u5-NpP^aQf^C}YPU%wLM!ZKegNbw>c8FP_rs&haQucs;gv?^X~%am*#)$nNX&UD$DTQF1+%s>?2w`FPpDt
zY8bGJ@-2I_66h~s(_(Y6ouLO1;|pF4E8luwuysz8tA2uNs=4YQAAkJN#C9xc_tU*R
z&SMq6)0du4r{;(7JveRkvub-_-*x%l68URqtHPNlq-&SUx7_0PW>RN|@gLh(uiewW
zTd)wsIH0%fxaxY#L_*Y#i^NvjF
zbHohmly-`M?IK=H%5-M^X`$&+Yho6)wnfcHGM`_!)qY;0L+UC%de5IV8IE@8
z_;~FwFh6e(i!v?sH#BumCo+zA&fJdGK!cXWVGWCk>CMYebfb|jicN$5NZSR}XQQC5
zhR!n-d(4}5bThjg-bmC6jMWV6h-a*i1)cwS<&YxFdewr4L
zL))%MLQLXhW$faEp4GG+NoU~{(ZnOCwK{Gcu{UWqP!{a+HcElXZxDS)qEA{*zBm*!)S;BSzXYO9&{n{REivJUHIL#O8XvE`gwA%qUw
zV#)-lQpu$FP2o>2MZW29S=M;YQ1;CReQ(J`c>vku@i1Y$2SxR2Git&ZXYHPzI^Ja_(b&|_d=nxsTiA6Zs!jCYVD
z3w(=Zf`G%4*fWZj<;D-H{K+(^A2NPde|rpkyt{&sY=BkmPc&+(m8vs*AL=vOJTL~D
zfHWW|n|#7!U+j7$MVbgyJLstoiu1lyUh@>pLFQ&2X9V|oHm5Xaes+%K|Is44iHUgfiIPubf_~`mJs5AK=>R{5$S<<^2DHIMpw|FX#Sq`Z{3ljh}dTZM8MF
z?w96Wqt&*6lsTyW?{?Mpsv5i9%c~jrvDS@t2uG1!bwR1pfwMa?o?MuHg<0R{lexeq17zQ!DdT>F!WM@-y
zteBWuf}O*Z+liG~WlA5s6^uS}uWJz16k>FIQ;}4j;J25^71fVcbdW>hht1-9d3gsw
z#JlMTm%3Z&q`1miQb7lFHSJX-d_Bn#HJ$*3XpW)OuXhBbA{?S0|Gcb`W&AwiCoXY_
zE?wv}T&`2cj%88u%~f}PSW+r4c6z$AT;T)oNZhS4sfnrwUQzVS@p@Xtj7g4R;08g~
zyga@k*tqqfBI$&>-(tCunq5`HcH)7qk+a((cf_}TA*ElOzaG-ajb}Upo))LSTq?Nq
zs=qC$IeirR1!j9Q`(cMY#-(wyqd`m$uR}FWCvl7weQT7~!njyk=KiI~DX-9TmoY`|
z<@)T@YfmPi;pF5%aS42&4oBfRB!s|=V58dor^o42sxV=s@#kg9SRcqNUhn!iY&vhx
zNN=V7M7m~X6{Xw&&PAaLhXi^l2HL0kPO
z)kw#0m6CP$Vx<2ELjU~w3i|%mzlT!pzs24BzHPaMTXf@h^w;a=wu+7I_^h_INxP!`
zfqta@qr-rj^N`TPe!3(`BGy`AZkt-7qwBxxUzmxy028dS?Xa(3`fF~*mMRM<
z2QUpaF8SVNq?wZg{ln(kyTG!sd*l#@Wrx#x_A79G#L7$#T6z801^DPgn`jb~(h6+C
zS$A;Oez@8q(I3+D9)M^p6Q`BmRXlTVQzfiVQTBcfLyj5m&UQC@y|I@$k&&VNJhi$n
z^WYjUD6To$k+PwFZU#3RN2y763I4r4aYbX;ih4g@DlC$sj4hw(tf}x!C)k!+LQ`
zr8Jg)Jd&V<#w!Z0p*A9r>vaJq2(GA>xK=;j*K3T{-K*N2+(aoSEVSw!o@BZI9E8Pw
z(!zmhwZ?w)&n7f=+#gEtAu>XH`{b?WwMp%yvYZkqu>ShmTT6%63wlCh~$4)g~zS{rf-756q52)y3qDoJ1N
zYfB=%N9!5SL61%orl6ECU+waaJKS|5MZc5_XQdLA>0GzU(9w+-3+~C~-DNEaEo`gt
z#sydCAqTNAaGIHGzm_})ke8`&r!)d6E;}E`k*U3rm6~wQ?>*PcW?SRG)hWOG_c5~M
z&tJ8lXa&*-Asc@-zJl}(Qap4_ztzXeOZcptG`%@51bNR^#y9B#i81p;?+1Rl9-9a}
zc4&J9-!EdGyftM76Nn4JIqFd+MacDK!Gv}WZvr?s-o3}s%RiCZC)+t#ERTKnL8mR`
z92?Av5gu9tx-Fw#*NtG_uNp+u$uq3$jSAN1=|$$s{?Q(52jn`{Twv`mEC?#yz)>LQ
zS23e0q0iqSNuTeB8^$I5!ztz#iYL$bnRBJeNFvx{)x{jTbpXEk9N&3E5v)Ku06@t8
zW(mq|DJJ*j8J1boxt1N;zV6zTQ5kM%sdMTK`W|6Aaar>V|hq=4}j&h25kyg6!?yYHi$gL1pKV
z4Ct+%lT0o73{(&vN3z^~YZC?47QDXtwls%=i>VZ|<;i6wl
zi2vKU4LtjA1@x`SgPEfV5Up);`Icx(nrRZsNQM{Yu9?a#Q{+^c=dIoI9Fo}e%_YE$
z>*Izkzzfb{K+2vHFRS^Kcj#L~$ELN-
zR(Gj#jqL|<(0wdq=S6lJ4#+Q;j8-Ap_2iai>2>gVZTy7H&dZJOOH=u-^i-z#65t_<
zx`JSL7Db6mrSmku46CWMFsh4t!vrLoV5h!J_ofx
zBhMR?N{#_>a@H}BZ1$RGJ9z8_UHah~1RcGxB3ThHWmp%8ic8*?ZAISq+?L+99_ysn
z22#=jK7$7kJ7=eqD?ErSAP}V~y12h%(j-lRSx)dP%6|HOjbk_Mg<$Z`eGBx7a>Gzt
zar6!PQLc6PYTuknw*OMZ;Y{}5G%cOa5J8LgWuN_Z%Pbc?xrA8
z(xHLPuoF478<@N>F|nY{xBZk&lSn%WT4)tG$9G@V_z=_&t?Z$e=TY}
zxfJnN-yzG`3C~T