From 6893f2ff191b39ae0cec9adfb7bf8d6e828d3c4c Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 00:37:33 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=95=95?= =?UTF-8?q?=EC=B6=95=20=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onboarding/nickname/NicknameScreen.kt | 12 ++-- .../presentation/utils/ImageUploadUtil.kt | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 presentation/src/main/java/com/keyme/presentation/utils/ImageUploadUtil.kt diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt index 017c51e..b24d0bd 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt @@ -2,7 +2,6 @@ package com.keyme.presentation.onboarding.nickname import android.annotation.SuppressLint import android.net.Uri -import android.util.Base64 import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts @@ -67,6 +66,8 @@ import com.keyme.presentation.designsystem.theme.white_alpha_15 import com.keyme.presentation.designsystem.theme.white_alpha_30 import com.keyme.presentation.designsystem.theme.white_alpha_40 import com.keyme.presentation.onboarding.OnboardingViewModel +import com.keyme.presentation.utils.ImageUploadUtil + @Composable fun NicknameScreen( @@ -369,7 +370,6 @@ fun NextButton( uploadProfileImage: (String) -> Unit, ) { val context = LocalContext.current - val contentResolver = context.contentResolver KeymeTextButton( text = "다음", @@ -379,12 +379,8 @@ fun NextButton( } else if (selectedImage == null) { Toast.makeText(context, "프로필 사진을 선택해주세요", Toast.LENGTH_SHORT).show() } else { - run { - val inputStream = contentResolver.openInputStream(selectedImage) - val imageBytes = inputStream?.readBytes() - val imageString = Base64.encodeToString(imageBytes, Base64.DEFAULT) - inputStream?.close() - + val imageString = ImageUploadUtil.getProfileImageString(context, selectedImage) + imageString?.let { uploadProfileImage.invoke(imageString) } } diff --git a/presentation/src/main/java/com/keyme/presentation/utils/ImageUploadUtil.kt b/presentation/src/main/java/com/keyme/presentation/utils/ImageUploadUtil.kt new file mode 100644 index 0000000..3dedd04 --- /dev/null +++ b/presentation/src/main/java/com/keyme/presentation/utils/ImageUploadUtil.kt @@ -0,0 +1,66 @@ +package com.keyme.presentation.utils + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import android.util.Base64 +import timber.log.Timber +import java.io.ByteArrayOutputStream + +object ImageUploadUtil { + + fun getProfileImageString(context: Context, uri: Uri): String? { + val resized = resize(context, uri, 360) + val result = resized?.let { + val compressed = compress(it) + Timber.d("><> compressed: ${compressed.byteCount}") + getStringImage(compressed) + } + + return result + } + + private fun resize(context: Context, uri: Uri, resizePx: Int): Bitmap? { + val options = BitmapFactory.Options() + + BitmapFactory.decodeStream(context.contentResolver.openInputStream(uri), null, options) + var width = options.outWidth + var height = options.outHeight + var samplesize = 1 + while (width > resizePx || height > resizePx) { + width /= 2 + height /= 2 + samplesize *= 2 + } + options.inSampleSize = samplesize + + val resized = BitmapFactory.decodeStream( + context.contentResolver.openInputStream(uri), + null, + options, + ) + + return resized?.let { + Bitmap.createScaledBitmap(resized, width, height, true) + } + } + + private fun compress(bitmap: Bitmap): Bitmap { + val baos = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos) + + return BitmapFactory.decodeByteArray( + baos.toByteArray(), + 0, + baos.toByteArray().size, + ) + } + + private fun getStringImage(bitmap: Bitmap): String { + val baos = ByteArrayOutputStream() + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos) + val imageBytes = baos.toByteArray() + return Base64.encodeToString(imageBytes, Base64.DEFAULT) + } +} From 1fea4d70dc818007e6c7187b4c7072bfe01c121b Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 00:59:16 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20required=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onboarding/OnboardingScreen.kt | 21 ++++++----- .../onboarding/OnboardingViewModel.kt | 3 +- .../onboarding/nickname/NicknameScreen.kt | 37 ++++++++++--------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt index c182b1d..acfbcdf 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt @@ -28,6 +28,9 @@ import com.keyme.presentation.onboarding.guide.Guide03Screen import com.keyme.presentation.onboarding.guide.Guide04Screen import com.keyme.presentation.onboarding.nickname.NicknameScreen import com.keyme.presentation.onboarding.signin.SignInScreen +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch @Composable @@ -50,7 +53,6 @@ fun OnboardingScreen( ) { val coroutineScope = rememberCoroutineScope() val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.animation_signin_background)) - val localOnboardingState by viewModel.userAuthState.collectAsState() val pagerState = rememberPagerState(initialPage = 0) val onboardingSteps = listOf( @@ -62,15 +64,16 @@ fun OnboardingScreen( OnboardingStepsEnum.GUIDE_04, ) - LaunchedEffect(localOnboardingState) { - localOnboardingState.let { - when { - it?.accessToken == null -> pagerState.scrollToPage(OnboardingStepsEnum.KAKAO_SIGN_IN.ordinal) - it.nickname == null -> pagerState.scrollToPage(OnboardingStepsEnum.NICKNAME.ordinal) - it.onboardingTestResultId == null -> pagerState.scrollToPage(OnboardingStepsEnum.GUIDE_01.ordinal) - else -> navigateToMyDaily.invoke() + LaunchedEffect(key1 = Unit){ + viewModel.userAuthState + .collectLatest { + when { + it?.accessToken == null -> pagerState.scrollToPage(OnboardingStepsEnum.KAKAO_SIGN_IN.ordinal) + it.nickname.isNullOrBlank() -> pagerState.scrollToPage(OnboardingStepsEnum.NICKNAME.ordinal) + it.onboardingTestResultId == null -> pagerState.scrollToPage(OnboardingStepsEnum.GUIDE_01.ordinal) + else -> navigateToMyDaily.invoke() + } } - } } when (pagerState.currentPage) { diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingViewModel.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingViewModel.kt index 54cce61..f7e0d18 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingViewModel.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingViewModel.kt @@ -103,7 +103,8 @@ class OnboardingViewModel @Inject constructor( originalUrl: String, thumbnailUrl: String, ) { - if (uploadProfileImageState.value == null) return + // todo 프로필 사진 선택 +// if (uploadProfileImageState.value == null) return apiCall(apiRequest = { updateMemberUseCase.invoke( nickname = nickname, diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt index b24d0bd..032a593 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt @@ -83,16 +83,6 @@ fun NicknameScreen( ActivityResultContracts.GetContent(), ) { uri -> uri?.let { selectedImage = uri } } - LaunchedEffect(key1 = uploadProfileImageState) { - uploadProfileImageState?.let { - viewModel.updateMember( - nickname = nickname, - originalUrl = it.originalUrl, - thumbnailUrl = it.thumbnailUrl, - ) - } - } - Column( modifier = Modifier .fillMaxSize() @@ -136,7 +126,13 @@ fun NicknameScreen( nickname = nickname, isNicknameValidated = verifyNicknameState?.valid ?: false, selectedImage = selectedImage, - uploadProfileImage = viewModel::uploadProfileImage, + uploadProfileImage = { + viewModel.updateMember( + nickname = nickname, + originalUrl = "", + thumbnailUrl = "", + ) + }, ) Spacer(modifier = Modifier.size(54.dp)) @@ -376,13 +372,18 @@ fun NextButton( onClick = { if (nickname.isBlank() || !isNicknameValidated) { Toast.makeText(context, "닉네임을 확인해주세요", Toast.LENGTH_SHORT).show() - } else if (selectedImage == null) { - Toast.makeText(context, "프로필 사진을 선택해주세요", Toast.LENGTH_SHORT).show() - } else { - val imageString = ImageUploadUtil.getProfileImageString(context, selectedImage) - imageString?.let { - uploadProfileImage.invoke(imageString) - } + } + // todo 프로필 사진 선택 +// else if (selectedImage == null) { +// Toast.makeText(context, "프로필 사진을 선택해주세요", Toast.LENGTH_SHORT).show() +// } + else { + // todo 프로필 사진 선택 +// val imageString = ImageUploadUtil.getProfileImageString(context, selectedImage) +// imageString?.let { +// uploadProfileImage.invoke(imageString) +// } + uploadProfileImage("") } }, modifier = Modifier From 24c3b18b78b7ff580c75c5f86e394daec64f06b1 Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 01:02:09 +0900 Subject: [PATCH 3/6] =?UTF-8?q?lint=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/keyme/presentation/onboarding/OnboardingScreen.kt | 5 +---- .../keyme/presentation/onboarding/nickname/NicknameScreen.kt | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt index 9adf475..ae92948 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier @@ -36,8 +35,6 @@ import com.keyme.presentation.onboarding.guide.Guide04Screen import com.keyme.presentation.onboarding.nickname.NicknameScreen import com.keyme.presentation.onboarding.signin.SignInScreen import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch @Composable @@ -71,7 +68,7 @@ fun OnboardingScreen( OnboardingStepsEnum.GUIDE_04, ) - LaunchedEffect(key1 = Unit){ + LaunchedEffect(key1 = Unit) { viewModel.userAuthState .collectLatest { when { diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt index b282fe8..30c3412 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/nickname/NicknameScreen.kt @@ -68,7 +68,6 @@ import com.keyme.presentation.designsystem.theme.white_alpha_40 import com.keyme.presentation.onboarding.OnboardingViewModel import com.keyme.presentation.onboarding.fadingAnimateFloatAsState - @Composable fun NicknameScreen( isVisible: Boolean, From ad1cec55b49e81c57b2cc4b27dbfe12dcd79089a Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 01:27:51 +0900 Subject: [PATCH 4/6] =?UTF-8?q?UserAuthEntity=20primary=20key=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/keyme/data/local/entity/UserAuthEntity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/src/main/java/com/keyme/data/local/entity/UserAuthEntity.kt b/data/src/main/java/com/keyme/data/local/entity/UserAuthEntity.kt index 370aed6..43d09bb 100644 --- a/data/src/main/java/com/keyme/data/local/entity/UserAuthEntity.kt +++ b/data/src/main/java/com/keyme/data/local/entity/UserAuthEntity.kt @@ -5,11 +5,11 @@ import androidx.room.PrimaryKey @Entity(tableName = "userAuth") data class UserAuthEntity( - @PrimaryKey(autoGenerate = false) val id: Int, + val id: Int = 0, val nickname: String?, val profileImage: String?, val profileThumbnail: String?, val friendCode: String?, val onboardingTestResultId: Int?, - val accessToken: String, + @PrimaryKey val accessToken: String, ) From 2b84fe5f1f9c790cac9853d11602897df9dc056e Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 02:15:38 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/keyme/app/ui/KeymeApp.kt | 11 +++++++++++ .../presentation/onboarding/OnboardingNavigation.kt | 2 ++ .../presentation/takekeymetest/TakeKeymeTestRoute.kt | 7 ++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/keyme/app/ui/KeymeApp.kt b/app/src/main/java/com/keyme/app/ui/KeymeApp.kt index 12997fd..b00cd73 100644 --- a/app/src/main/java/com/keyme/app/ui/KeymeApp.kt +++ b/app/src/main/java/com/keyme/app/ui/KeymeApp.kt @@ -53,15 +53,26 @@ fun KeymeApp() { appState.onBackClick() appState.navigate(DailyKeymeTestDestination) }, + nestedGraphs = { + takeKeymeTestGraph( + onBackClick = appState::onBackClick, + onTestSolved = { + appState.onBackClick() + appState.navigate(DailyKeymeTestDestination) + } + ) + } ) dailyKeymeTestGraph( navigateToTakeKeymeTest = { appState.navigate(TakeKeymeTestDestination, it) }, nestedGraphs = { takeKeymeTestGraph( onBackClick = appState::onBackClick, + onTestSolved = appState::onBackClick ) }, ) + // takeKeymeTestGraph -> 문제 풀이, 결과 확인 myProfileGraph( navigateToQuestionResult = { question -> diff --git a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingNavigation.kt b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingNavigation.kt index 6820857..d2e0c6e 100644 --- a/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingNavigation.kt +++ b/presentation/src/main/java/com/keyme/presentation/onboarding/OnboardingNavigation.kt @@ -13,6 +13,7 @@ object OnboardingDestination : KeymeNavigationDestination { fun NavGraphBuilder.onboardingGraph( navigateToOnboardingKeymeTest: (testId: Int) -> Unit, navigateToMyDaily: () -> Unit, + nestedGraphs: NavGraphBuilder.() -> Unit, ) { navigation( route = OnboardingDestination.route, @@ -24,5 +25,6 @@ fun NavGraphBuilder.onboardingGraph( navigateToMyDaily = navigateToMyDaily, ) } + nestedGraphs() } } diff --git a/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt b/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt index f11841d..b81aabc 100644 --- a/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt +++ b/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt @@ -19,6 +19,7 @@ object TakeKeymeTestDestination : KeymeNavigationDestination { fun NavGraphBuilder.takeKeymeTestGraph( onBackClick: () -> Unit, + onTestSolved: () -> Unit, ) { composable( route = "${TakeKeymeTestDestination.route}/{${TakeKeymeTestDestination.testIdArg}}", @@ -31,6 +32,7 @@ fun NavGraphBuilder.takeKeymeTestGraph( TakeKeymeTestRoute( onBackClick = onBackClick, onCloseClick = { onBackClick() }, + onTestSolved = { onTestSolved() } ) } } @@ -39,6 +41,7 @@ fun NavGraphBuilder.takeKeymeTestGraph( fun TakeKeymeTestRoute( takeKeymeTestViewModel: TakeKeymeTestViewModel = hiltViewModel(), onBackClick: () -> Unit, + onTestSolved: () -> Unit, onCloseClick: () -> Unit, ) { val loadTestUrl = takeKeymeTestViewModel.keymeTestUrl @@ -59,7 +62,9 @@ fun TakeKeymeTestRoute( KeymeTestResultScreen( myCharacter = myCharacter, testResult = keymeTestResult, - onCloseClick = onCloseClick, + onCloseClick = { + onTestSolved() + }, ) } } else { From 281960ff0834518f00b89a480d4efadf8a914075 Mon Sep 17 00:00:00 2001 From: DwEnn Date: Sat, 19 Aug 2023 02:19:10 +0900 Subject: [PATCH 6/6] =?UTF-8?q?lint=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/keyme/app/ui/KeymeApp.kt | 6 +++--- .../keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/keyme/app/ui/KeymeApp.kt b/app/src/main/java/com/keyme/app/ui/KeymeApp.kt index b00cd73..efc5f3f 100644 --- a/app/src/main/java/com/keyme/app/ui/KeymeApp.kt +++ b/app/src/main/java/com/keyme/app/ui/KeymeApp.kt @@ -59,16 +59,16 @@ fun KeymeApp() { onTestSolved = { appState.onBackClick() appState.navigate(DailyKeymeTestDestination) - } + }, ) - } + }, ) dailyKeymeTestGraph( navigateToTakeKeymeTest = { appState.navigate(TakeKeymeTestDestination, it) }, nestedGraphs = { takeKeymeTestGraph( onBackClick = appState::onBackClick, - onTestSolved = appState::onBackClick + onTestSolved = appState::onBackClick, ) }, ) diff --git a/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt b/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt index b81aabc..7423ae1 100644 --- a/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt +++ b/presentation/src/main/java/com/keyme/presentation/takekeymetest/TakeKeymeTestRoute.kt @@ -32,7 +32,7 @@ fun NavGraphBuilder.takeKeymeTestGraph( TakeKeymeTestRoute( onBackClick = onBackClick, onCloseClick = { onBackClick() }, - onTestSolved = { onTestSolved() } + onTestSolved = { onTestSolved() }, ) } }