diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8039127a..18ab8d7d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,7 +56,8 @@ + android:screenOrientation="portrait" + android:windowSoftInputMode="adjustResize" /> (R.layout.activity_onboarding) { private var _onboardingAdapter: OnboardingAdapter? = null - val onboardingAdapter + private val onboardingAdapter get() = requireNotNull(_onboardingAdapter) { getString(R.string.adapter_not_initialized_error_msg) } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/presentation/src/main/java/kr/genti/presentation/create/CreateActivity.kt b/presentation/src/main/java/kr/genti/presentation/create/CreateActivity.kt index 798ea3fc..fced7d87 100644 --- a/presentation/src/main/java/kr/genti/presentation/create/CreateActivity.kt +++ b/presentation/src/main/java/kr/genti/presentation/create/CreateActivity.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kr.genti.core.base.BaseActivity import kr.genti.core.extension.setOnSingleClickListener -import kr.genti.core.extension.setStatusBarColorFromResource import kr.genti.core.state.UiState import kr.genti.presentation.R import kr.genti.presentation.databinding.ActivityCreateBinding @@ -26,63 +25,39 @@ import kr.genti.presentation.util.AmplitudeManager.PROPERTY_PAGE @AndroidEntryPoint class CreateActivity() : BaseActivity(R.layout.activity_create) { private val viewModel by viewModels() - lateinit var navController: NavController + private lateinit var navController: NavController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initView() initBackBtnListener() - setCurrentFragment() observeProgressBar() observeGeneratingState() } private fun initView() { - setStatusBarColorFromResource(R.color.white) navController = binding.fcvCreate.getFragment().navController } private fun initBackBtnListener() { binding.btnBack.setOnSingleClickListener { when (navController.currentDestination?.id) { - R.id.defineFragment -> return@setOnSingleClickListener - - R.id.poseFragment -> { - AmplitudeManager.trackEvent( - EVENT_CLICK_BTN, - mapOf(PROPERTY_PAGE to "create2"), - mapOf(PROPERTY_BTN to "back"), - ) - navController.popBackStack() - viewModel.modCurrentPercent(-33) - } - - R.id.selfieFragment -> { - AmplitudeManager.trackEvent( - EVENT_CLICK_BTN, - mapOf(PROPERTY_PAGE to "create3"), - mapOf(PROPERTY_BTN to "back"), - ) - navController.popBackStack() - viewModel.modCurrentPercent(-34) - } + R.id.defineFragment -> finish() + R.id.poseFragment -> navigateBackFragment("create2", -33) + R.id.selfieFragment -> navigateBackFragment("create3", -34) } } } - private fun setCurrentFragment() { - if (::navController.isInitialized) { - when (viewModel.currentPercent.value) { - 66 -> navController.navigate(R.id.poseFragment) - 100 -> { - navController.navigate(R.id.poseFragment) - navController.navigate(R.id.selfieFragment) - } - - else -> return - } - } + private fun navigateBackFragment(tag: String, amount: Int) { + AmplitudeManager.trackEvent( + EVENT_CLICK_BTN, + mapOf(PROPERTY_PAGE to tag), + mapOf(PROPERTY_BTN to "back"), + ) + navController.popBackStack() + viewModel.modCurrentPercent(amount) } private fun observeProgressBar() { @@ -97,19 +72,13 @@ class CreateActivity() : BaseActivity(R.layout.activity_c interpolator = LinearInterpolator() start() } - binding.btnBack.isVisible = viewModel.currentPercent.value > 33 + binding.tvCreatePhase.text = getString(R.string.create_phase_text, percent / 33) }.launchIn(lifecycleScope) } private fun observeGeneratingState() { viewModel.totalGeneratingState.flowWithLifecycle(lifecycle).onEach { state -> - if (state == UiState.Loading) { - setStatusBarColorFromResource(R.color.background_white) - binding.layoutLoading.isVisible = true - } else { - setStatusBarColorFromResource(R.color.white) - binding.layoutLoading.isVisible = false - } + binding.layoutLoading.isVisible = state == UiState.Loading }.launchIn(lifecycleScope) } diff --git a/presentation/src/main/java/kr/genti/presentation/create/CreateGuideDialog.kt b/presentation/src/main/java/kr/genti/presentation/create/CreateGuideDialog.kt deleted file mode 100644 index 944750a2..00000000 --- a/presentation/src/main/java/kr/genti/presentation/create/CreateGuideDialog.kt +++ /dev/null @@ -1,35 +0,0 @@ -package kr.genti.presentation.create - -import android.os.Bundle -import android.view.View -import android.view.WindowManager -import kr.genti.core.base.BaseDialog -import kr.genti.core.extension.setOnSingleClickListener -import kr.genti.presentation.R -import kr.genti.presentation.databinding.DialogCreateGuideBinding - -class CreateGuideDialog : BaseDialog(R.layout.dialog_create_guide) { - override fun onStart() { - super.onStart() - dialog?.window?.apply { - setLayout( - WindowManager.LayoutParams.WRAP_CONTENT, - WindowManager.LayoutParams.WRAP_CONTENT, - ) - setBackgroundDrawableResource(R.color.transparent) - } - } - - override fun onViewCreated( - view: View, - savedInstanceState: Bundle?, - ) { - super.onViewCreated(view, savedInstanceState) - - initCloseBtnListener() - } - - private fun initCloseBtnListener() { - binding.btnClose.setOnSingleClickListener { dismiss() } - } -} diff --git a/presentation/src/main/java/kr/genti/presentation/create/CreateViewModel.kt b/presentation/src/main/java/kr/genti/presentation/create/CreateViewModel.kt index bab0a503..0361c65b 100644 --- a/presentation/src/main/java/kr/genti/presentation/create/CreateViewModel.kt +++ b/presentation/src/main/java/kr/genti/presentation/create/CreateViewModel.kt @@ -22,256 +22,250 @@ import kr.genti.domain.enums.PictureRatio import kr.genti.domain.enums.ShotCoverage import kr.genti.domain.repository.CreateRepository import kr.genti.domain.repository.UploadRepository -import kr.genti.domain.repository.UserRepository import javax.inject.Inject import kotlin.random.Random @HiltViewModel class CreateViewModel - @Inject - constructor( - private val createRepository: CreateRepository, - private val uploadRepository: UploadRepository, - private val userRepository: UserRepository, - ) : ViewModel() { - val prompt = MutableLiveData() - var plusImage = emptyImageFileModel() - val isWritten = MutableLiveData(false) +@Inject +constructor( + private val createRepository: CreateRepository, + private val uploadRepository: UploadRepository, +) : ViewModel() { + val prompt = MutableLiveData() + var plusImage = emptyImageFileModel() + val isWritten = MutableLiveData(false) - val selectedRatio = MutableLiveData() - val selectedAngle = MutableLiveData() - val selectedCoverage = MutableLiveData() - val isSelected = MutableLiveData(false) + val selectedRatio = MutableLiveData() + val selectedAngle = MutableLiveData() + val selectedCoverage = MutableLiveData() + val isSelected = MutableLiveData(false) - var imageList = listOf() - var isCompleted = MutableLiveData(false) + var imageList = listOf() + var isCompleted = MutableLiveData(false) - private val _currentPercent = MutableStateFlow(33) - val currentPercent: StateFlow = _currentPercent + private val _currentPercent = MutableStateFlow(33) + val currentPercent: StateFlow = _currentPercent - private var currentPrompt: String = "" + private var currentPrompt: String = "" - private val _totalGeneratingState = MutableStateFlow>(UiState.Empty) - val totalGeneratingState: StateFlow> = _totalGeneratingState + private val _totalGeneratingState = MutableStateFlow>(UiState.Empty) + val totalGeneratingState: StateFlow> = _totalGeneratingState - private var plusImageS3Key = KeyRequestModel(null) - private var imageS3KeyList = listOf() + private var plusImageS3Key = KeyRequestModel(null) + private var imageS3KeyList = listOf() - fun modCurrentPercent(amount: Int) { - _currentPercent.value += amount - } + fun modCurrentPercent(amount: Int) { + _currentPercent.value += amount + } - fun checkWritten() { - isWritten.value = prompt.value?.isNotEmpty() - } + fun checkWritten() { + isWritten.value = prompt.value?.isNotEmpty() + } - fun selectRatio(item: PictureRatio) { - selectedRatio.value = item - checkSelected() - } + fun selectRatio(item: PictureRatio) { + selectedRatio.value = item + checkSelected() + } - fun selectAngle(item: CameraAngle) { - selectedAngle.value = item - checkSelected() - } + fun selectAngle(item: CameraAngle) { + selectedAngle.value = item + checkSelected() + } - fun selectFrame(item: ShotCoverage) { - selectedCoverage.value = item - checkSelected() - } + fun selectFrame(item: ShotCoverage) { + selectedCoverage.value = item + checkSelected() + } - private fun checkSelected() { - isSelected.value = - selectedRatio.value != null && selectedAngle.value != null && selectedCoverage.value != null - } + private fun checkSelected() { + isSelected.value = + selectedRatio.value != null && selectedAngle.value != null && selectedCoverage.value != null + } - fun startSendingImages() { - _totalGeneratingState.value = UiState.Loading - viewModelScope.launch { - runCatching { - listOfNotNull( - if (plusImage.id != (-1).toLong()) async { getSingleS3Url() } else null, - async { getMultiS3Urls() }, - ).awaitAll() - }.onSuccess { - postToGenerateImage() - }.onFailure { - _totalGeneratingState.value = UiState.Failure(it.message.toString()) - } + fun startSendingImages() { + _totalGeneratingState.value = UiState.Loading + viewModelScope.launch { + runCatching { + listOfNotNull( + if (plusImage.id != (-1).toLong()) async { getSingleS3Url() } else null, + async { getMultiS3Urls() }, + ).awaitAll() + }.onSuccess { + postToGenerateImage() + }.onFailure { + _totalGeneratingState.value = UiState.Failure(it.message.toString()) } } + } - private suspend fun getSingleS3Url() { - createRepository.getS3SingleUrl( - S3RequestModel(FileType.USER_UPLOADED_IMAGE, plusImage.name), - ) - .onSuccess { uriModel -> - plusImageS3Key = KeyRequestModel(uriModel.s3Key) - postSingleImage(uriModel) - }.onFailure { - _totalGeneratingState.value = UiState.Failure(it.message.toString()) - } - } - - private suspend fun getMultiS3Urls() { - createRepository.getS3MultiUrl( - listOf( - S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[0].name), - S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[1].name), - S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[2].name), - ), - ).onSuccess { uriList -> - imageS3KeyList = uriList.map { KeyRequestModel(it.s3Key) } - postMultiImage(uriList) + private suspend fun getSingleS3Url() { + createRepository.getS3SingleUrl( + S3RequestModel(FileType.USER_UPLOADED_IMAGE, plusImage.name), + ) + .onSuccess { uriModel -> + plusImageS3Key = KeyRequestModel(uriModel.s3Key) + postSingleImage(uriModel) }.onFailure { _totalGeneratingState.value = UiState.Failure(it.message.toString()) } - } + } - private suspend fun postSingleImage(urlModel: S3PresignedUrlModel) { - uploadRepository.uploadImage(urlModel.url, plusImage.url) - .onFailure { - _totalGeneratingState.value = UiState.Failure(it.message.toString()) - } + private suspend fun getMultiS3Urls() { + createRepository.getS3MultiUrl( + listOf( + S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[0].name), + S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[1].name), + S3RequestModel(FileType.USER_UPLOADED_IMAGE, imageList[2].name), + ), + ).onSuccess { uriList -> + imageS3KeyList = uriList.map { KeyRequestModel(it.s3Key) } + postMultiImage(uriList) + }.onFailure { + _totalGeneratingState.value = UiState.Failure(it.message.toString()) } + } - private suspend fun postMultiImage(urlModelList: List) { - urlModelList.mapIndexed { i, urlModel -> - viewModelScope.async { - uploadRepository.uploadImage(urlModel.url, imageList[i].url) - .onFailure { - _totalGeneratingState.value = UiState.Failure(it.message.toString()) - } - } - }.awaitAll() - } + private suspend fun postSingleImage(urlModel: S3PresignedUrlModel) { + uploadRepository.uploadImage(urlModel.url, plusImage.url) + .onFailure { + _totalGeneratingState.value = UiState.Failure(it.message.toString()) + } + } - private fun postToGenerateImage() { - viewModelScope.launch { - createRepository.postToCreate( - CreateRequestModel( - prompt.value ?: return@launch, - plusImageS3Key, - imageS3KeyList, - selectedAngle.value ?: return@launch, - selectedCoverage.value ?: return@launch, - selectedRatio.value ?: return@launch, - ), - ) - .onSuccess { - _totalGeneratingState.value = UiState.Success(it) - }.onFailure { + private suspend fun postMultiImage(urlModelList: List) { + urlModelList.mapIndexed { i, urlModel -> + viewModelScope.async { + uploadRepository.uploadImage(urlModel.url, imageList[i].url) + .onFailure { _totalGeneratingState.value = UiState.Failure(it.message.toString()) } } - } + }.awaitAll() + } - fun resetGeneratingState() { - _totalGeneratingState.value = UiState.Empty + private fun postToGenerateImage() { + viewModelScope.launch { + createRepository.postToCreate( + CreateRequestModel( + prompt.value ?: return@launch, + plusImageS3Key, + imageS3KeyList, + selectedAngle.value ?: return@launch, + selectedCoverage.value ?: return@launch, + selectedRatio.value ?: return@launch, + ), + ) + .onSuccess { + _totalGeneratingState.value = UiState.Success(it) + }.onFailure { + _totalGeneratingState.value = UiState.Failure(it.message.toString()) + } } + } - fun getIsGuideNeeded() = userRepository.getIsGuideNeeded() - - fun setIsGuideNeeded(isGuideNeeded: Boolean) = userRepository.setIsGuideNeeded(isGuideNeeded) + fun resetGeneratingState() { + _totalGeneratingState.value = UiState.Empty + } - fun getRandomPrompt(): String { - val randomPrompt = promptList[Random.nextInt(promptList.size)] - if (randomPrompt != currentPrompt) currentPrompt = randomPrompt - return currentPrompt - } + fun getRandomPrompt(): String { + val randomPrompt = promptList[Random.nextInt(promptList.size)] + if (randomPrompt != currentPrompt) currentPrompt = randomPrompt + return currentPrompt + } - companion object { - val promptList = - listOf( - "보트를 타고 바다 위를 여행하는 모습을 만들어주세요", - "모델이 되어서 패션쇼에서 런웨이를 서는 모습을 만들어주세요", - "원피스를 입고 꽃집에서 꽃을 들고 있는 모습을 만들어주세요", - "놀이공원에서 일본풍의 교복을 입고 서 있는 모습을 만들어주세요", - "정장을 입고 멋진 호텔에 앉아 있는 모습을 만들어주세요", - "콜로세움을 배경으로 로마 여행을 하는 모습을 만들어주세요", - "오토바이를 타고 광활한 사막 위를 달리는 모습을 만들어주세요", - "탑건 영화처럼 전투기 조종사가 되어 하늘에서 비행기를 조종하는 모습을 만들어주세요", - "산 꼭대기 호수 위에서 기념 사진을 찍는 모습을 만들어주세요", - "겨울 설원과 호수를 배경으로 코트를 입고 있는 모습을 만들어주세요", - "파자마를 입고 거실 소파에 편안하게 앉아 있는 모습을 만들어주세요", - "정장을 입고 스튜디오에서 사진을 찍는 모습을 만들어주세요", - "히말라야 정상에 등반한 모습을 만들어주세요", - "날씨 좋은 날 공원에서 멜빵바지를 입고 풍선을 손에 들고 있는 모습을 만들어주세요", - "한밤 중에 공원에서 운동복을 입고 러닝하는 모습을 만들어주세요", - "밤바다에서 가벼운 옷을 입고 산책하는 모습을 만들어주세요", - "파리의 에펠탑 앞에서 편안하게 앉아 있는 모습을 만들어주세요", - "바다 앞에서 원피스를 입고 걸어가는 모습을 만들어주세요", - "도심 야경을 배경으로 스트릿 스타일의 옷을 입고 있는 모습을 만들어주세요", - "한겨울에 목도리를 하고 있는 모습을 만들어주세요", - "드레스를 입고 파티장에 가 있는 모습을 만들어주세요", - "비행기에서 손님을 맞이하는 승무원차림의 모습을 만들어주세요", - "영화관에서 팝콘을 먹으면서 영화를 보는 모습을 만들어주세요", - "눈오는 날 눈사람을 완성한 모습을 만들어주세요", - "일본풍의 교복을 입고 벛꽃 아래에서 학교가는 모습을 만들어주세요", - "분위기 좋은 카페에 앉아 있는 모습을 만들어주세요", - "구름 위에 올라가서 무지개와 함께 있는 모습을 만들어주세요", - "웨딩드레스를 입고 행진하는 모습을 만들어주세요", - "승마복을 입고 말을 타고 있는 모습을 만들어주세요", - "트렌치 코트를 입고 낙옆이 쌓여 있는 거리를 걷고 있는 모습을 만들어주세요", - "이국적인 해변에서 원피스를 입고 걸어가는 사진을 만들어주세요", - "공항에서 캐리어를 끌고 걸어가는 사진을 만들어주세요", - "뉴욕의 타임스퀘어같은 전광판 아래에 서 있는 모습을 만들어주세요", - "기모노를 입고 교토 거리를 걸어가는 모습을 만들어주세요", - "강연장에서 프리젠테이션하고 있는 모습을 만들어주세요", - "겨울 옷을 입고 북극의 오로라와 함께있는 사진을 만들어주세요", - "변호사가 되어 법정에 서 있는 모습을 만들어주세요", - "런던의 빅밴을 배경으로 서 있는 모습을 만들어주세요", - "초원에서 말을 타고 있는 모습을 만들어주세요", - "이집트 피라미드 앞에서 서 있는 모습을 만들어주세요", - "무대 위에서 기타를 연주하는 모습을 만들어주세요", - "수의사가 되어 동물 병원에서 강아지를 진료하는 모습을 만들어주세요", - "제빵사가 되어 빵을 만들고 있는 모습을 만들어주세요", - "만개한 유채꽃밭에서 화려한 드레스를 입고 있는 모습을 만들어주세요", - "정장을 입고 공원에 앉아서 쉬고 있는 모습을 만들어주세요", - "강아지를 안고 있는 모습으로 만들어주세요", - "캠핑카 앞에 앉아서 캠핑을 즐기는 모습을 만들어주세요", - "정장을 입고 연설하는 모습을 만들어주세요", - "군복을 입고 있는 모습을 만들어주세요", - "경찰이 된 내 모습을 만들어주세요", - "청량한 바닷가에서 반팔과 반바지를 입고 있는 모습을 만들어주세요", - "고급스러운 레스토랑에서 식사하고 있는 모습을 만들어주세요", - "해변가에서 자전거를 타는 모습을 만들어주세요", - "꽃집 사장님이 된 모습을 만들어주세요", - "바닷가를 달리고 있는 모습을 만들어주세요", - "운동장에서 열심히 뛰고 있는 모습을 만들어주세요", - "마법학교에 입학한 마법사가 된 모습을 만들어주세요", - "아프리카 초원에서 사자와 함께 뛰고 있는 모습을 만들어주세요", - "크로스핏하는 모습을 만들어주세요", - "비행기 퍼스트 클래스를 타고 있는 모습을 만들어주세요", - "카페에서 커피 만드는 모습을 만들어주세요", - "잔디밭 위에서 디즈니 공주들이 입는 드레스를 입고 있는 모습을 만들어주세요", - "도서관에서 후드티를 입고 공부하는 모습을 만들어주세요", - "밤하늘에 반짝이는 별들 아래에서 앉아있는 사진을 만들어주세요", - "황혼이 짙어지는 사막에서 걸터앉아 멀리 바라보는 모습을 만들어주세요", - "번화가에서 커피를 들고 있는 사진을 만들어주세요", - "고요한 호수 위에 있는 작은 보트 안에서 비옷을 입고 있는 모습을 만들어주세요", - "황금빛 들녘에서 터틀넥 니트를 입고, 햇볕을 받고 있는 모습을 만들어주세요", - "가을 숲에서 단풍을 바라보는 모습을 만들어주세요", - "꽃이 만발한 정원에서 민소매 원피스를 입고, 꽃을 따고 있는 모습을 만들어주세요", - "도심 골목에서 가죽 재킷을 입고 벽에 기대어 있는 사진을 만들어주세요", - "늦은 가을 날씨에 니트와 스커트를 입고 단풍길을 걷는 사진을 만들어주세요", - "어두운 숲 속에서 검은색 망토를 입고있는 마법사의 모습을 만들어주세요", - "화창한 날씨에 티셔츠와 청바지를 입고 공원에서 피크닉을 즐기는 모습을 만들어주세요", - "빙하 위에서 털달린 점퍼를 입고 당당히 서 있는 모습을 만들어주세요", - "블라우스와 청바지를 입고 강가를 걷는 모습을 만들어주세요", - "해적 선박 위에서 항해하는 모습을 만들어주세요", - "카니발 축제에서 화려한 공연복을 입고 춤추는 모습을 만들어주세요", - "판타지 세계에서 화려한 마법 로브를 입고 마법진을 그리는 모습을 만들어주세요", - "고대 신전에서 황금색 로브를 입고 앉아 있는 모습을 만들어주세요", - "정글 속에서 군복을 입고 숨어있는 모습을 만들어주세요", - "중세시대 성에서 화려한 왕관과 드레스를 입고 공주처럼 앉아 있는 모습을 만들어주세요", - "중국 전통복을 입고 만리장성을 배경으로 사진을 찍고 있는 모습을 만들어주세요", - "이스탄불에서 터키 전통 의상을 입고 역사적인 건물을 구경하는 모습을 만들어주세요.", - "앙코르와트에서 탐험복을 입고 거대한 석조 건축물을 배경으로 사진을 찍는 모습을 만들어주세요", - "한 겨울 자작나무 숲에서 모피 재킷을 입고 산책을 즐기며 자연을 만끽하는 모습을 만들어주세요", - "클럽에서 원피스를 입고 춤추는 모습을 만들어주세요", - "가을의 따뜻한 햇빛이 느껴지는 날씨에, 갈대 밭 속에서 서있는 사진을 만들고 싶어요.", - "저격을 준비하고 있는 스나이퍼가 된 모습을 만들고 싶어요", - ) - } + companion object { + val promptList = + listOf( + "보트를 타고 바다 위를 여행하는 모습을 만들어주세요", + "모델이 되어서 패션쇼에서 런웨이를 서는 모습을 만들어주세요", + "원피스를 입고 꽃집에서 꽃을 들고 있는 모습을 만들어주세요", + "놀이공원에서 일본풍의 교복을 입고 서 있는 모습을 만들어주세요", + "정장을 입고 멋진 호텔에 앉아 있는 모습을 만들어주세요", + "콜로세움을 배경으로 로마 여행을 하는 모습을 만들어주세요", + "오토바이를 타고 광활한 사막 위를 달리는 모습을 만들어주세요", + "탑건 영화처럼 전투기 조종사가 되어 하늘에서 비행기를 조종하는 모습을 만들어주세요", + "산 꼭대기 호수 위에서 기념 사진을 찍는 모습을 만들어주세요", + "겨울 설원과 호수를 배경으로 코트를 입고 있는 모습을 만들어주세요", + "파자마를 입고 거실 소파에 편안하게 앉아 있는 모습을 만들어주세요", + "정장을 입고 스튜디오에서 사진을 찍는 모습을 만들어주세요", + "히말라야 정상에 등반한 모습을 만들어주세요", + "날씨 좋은 날 공원에서 멜빵바지를 입고 풍선을 손에 들고 있는 모습을 만들어주세요", + "한밤 중에 공원에서 운동복을 입고 러닝하는 모습을 만들어주세요", + "밤바다에서 가벼운 옷을 입고 산책하는 모습을 만들어주세요", + "파리의 에펠탑 앞에서 편안하게 앉아 있는 모습을 만들어주세요", + "바다 앞에서 원피스를 입고 걸어가는 모습을 만들어주세요", + "도심 야경을 배경으로 스트릿 스타일의 옷을 입고 있는 모습을 만들어주세요", + "한겨울에 목도리를 하고 있는 모습을 만들어주세요", + "드레스를 입고 파티장에 가 있는 모습을 만들어주세요", + "비행기에서 손님을 맞이하는 승무원차림의 모습을 만들어주세요", + "영화관에서 팝콘을 먹으면서 영화를 보는 모습을 만들어주세요", + "눈오는 날 눈사람을 완성한 모습을 만들어주세요", + "일본풍의 교복을 입고 벛꽃 아래에서 학교가는 모습을 만들어주세요", + "분위기 좋은 카페에 앉아 있는 모습을 만들어주세요", + "구름 위에 올라가서 무지개와 함께 있는 모습을 만들어주세요", + "웨딩드레스를 입고 행진하는 모습을 만들어주세요", + "승마복을 입고 말을 타고 있는 모습을 만들어주세요", + "트렌치 코트를 입고 낙옆이 쌓여 있는 거리를 걷고 있는 모습을 만들어주세요", + "이국적인 해변에서 원피스를 입고 걸어가는 사진을 만들어주세요", + "공항에서 캐리어를 끌고 걸어가는 사진을 만들어주세요", + "뉴욕의 타임스퀘어같은 전광판 아래에 서 있는 모습을 만들어주세요", + "기모노를 입고 교토 거리를 걸어가는 모습을 만들어주세요", + "강연장에서 프리젠테이션하고 있는 모습을 만들어주세요", + "겨울 옷을 입고 북극의 오로라와 함께있는 사진을 만들어주세요", + "변호사가 되어 법정에 서 있는 모습을 만들어주세요", + "런던의 빅밴을 배경으로 서 있는 모습을 만들어주세요", + "초원에서 말을 타고 있는 모습을 만들어주세요", + "이집트 피라미드 앞에서 서 있는 모습을 만들어주세요", + "무대 위에서 기타를 연주하는 모습을 만들어주세요", + "수의사가 되어 동물 병원에서 강아지를 진료하는 모습을 만들어주세요", + "제빵사가 되어 빵을 만들고 있는 모습을 만들어주세요", + "만개한 유채꽃밭에서 화려한 드레스를 입고 있는 모습을 만들어주세요", + "정장을 입고 공원에 앉아서 쉬고 있는 모습을 만들어주세요", + "강아지를 안고 있는 모습으로 만들어주세요", + "캠핑카 앞에 앉아서 캠핑을 즐기는 모습을 만들어주세요", + "정장을 입고 연설하는 모습을 만들어주세요", + "군복을 입고 있는 모습을 만들어주세요", + "경찰이 된 내 모습을 만들어주세요", + "청량한 바닷가에서 반팔과 반바지를 입고 있는 모습을 만들어주세요", + "고급스러운 레스토랑에서 식사하고 있는 모습을 만들어주세요", + "해변가에서 자전거를 타는 모습을 만들어주세요", + "꽃집 사장님이 된 모습을 만들어주세요", + "바닷가를 달리고 있는 모습을 만들어주세요", + "운동장에서 열심히 뛰고 있는 모습을 만들어주세요", + "마법학교에 입학한 마법사가 된 모습을 만들어주세요", + "아프리카 초원에서 사자와 함께 뛰고 있는 모습을 만들어주세요", + "크로스핏하는 모습을 만들어주세요", + "비행기 퍼스트 클래스를 타고 있는 모습을 만들어주세요", + "카페에서 커피 만드는 모습을 만들어주세요", + "잔디밭 위에서 디즈니 공주들이 입는 드레스를 입고 있는 모습을 만들어주세요", + "도서관에서 후드티를 입고 공부하는 모습을 만들어주세요", + "밤하늘에 반짝이는 별들 아래에서 앉아있는 사진을 만들어주세요", + "황혼이 짙어지는 사막에서 걸터앉아 멀리 바라보는 모습을 만들어주세요", + "번화가에서 커피를 들고 있는 사진을 만들어주세요", + "고요한 호수 위에 있는 작은 보트 안에서 비옷을 입고 있는 모습을 만들어주세요", + "황금빛 들녘에서 터틀넥 니트를 입고, 햇볕을 받고 있는 모습을 만들어주세요", + "가을 숲에서 단풍을 바라보는 모습을 만들어주세요", + "꽃이 만발한 정원에서 민소매 원피스를 입고, 꽃을 따고 있는 모습을 만들어주세요", + "도심 골목에서 가죽 재킷을 입고 벽에 기대어 있는 사진을 만들어주세요", + "늦은 가을 날씨에 니트와 스커트를 입고 단풍길을 걷는 사진을 만들어주세요", + "어두운 숲 속에서 검은색 망토를 입고있는 마법사의 모습을 만들어주세요", + "화창한 날씨에 티셔츠와 청바지를 입고 공원에서 피크닉을 즐기는 모습을 만들어주세요", + "빙하 위에서 털달린 점퍼를 입고 당당히 서 있는 모습을 만들어주세요", + "블라우스와 청바지를 입고 강가를 걷는 모습을 만들어주세요", + "해적 선박 위에서 항해하는 모습을 만들어주세요", + "카니발 축제에서 화려한 공연복을 입고 춤추는 모습을 만들어주세요", + "판타지 세계에서 화려한 마법 로브를 입고 마법진을 그리는 모습을 만들어주세요", + "고대 신전에서 황금색 로브를 입고 앉아 있는 모습을 만들어주세요", + "정글 속에서 군복을 입고 숨어있는 모습을 만들어주세요", + "중세시대 성에서 화려한 왕관과 드레스를 입고 공주처럼 앉아 있는 모습을 만들어주세요", + "중국 전통복을 입고 만리장성을 배경으로 사진을 찍고 있는 모습을 만들어주세요", + "이스탄불에서 터키 전통 의상을 입고 역사적인 건물을 구경하는 모습을 만들어주세요.", + "앙코르와트에서 탐험복을 입고 거대한 석조 건축물을 배경으로 사진을 찍는 모습을 만들어주세요", + "한 겨울 자작나무 숲에서 모피 재킷을 입고 산책을 즐기며 자연을 만끽하는 모습을 만들어주세요", + "클럽에서 원피스를 입고 춤추는 모습을 만들어주세요", + "가을의 따뜻한 햇빛이 느껴지는 날씨에, 갈대 밭 속에서 서있는 사진을 만들고 싶어요.", + "저격을 준비하고 있는 스나이퍼가 된 모습을 만들고 싶어요", + ) } +} diff --git a/presentation/src/main/java/kr/genti/presentation/create/DefineAdapter.kt b/presentation/src/main/java/kr/genti/presentation/create/DefineAdapter.kt new file mode 100644 index 00000000..416171e8 --- /dev/null +++ b/presentation/src/main/java/kr/genti/presentation/create/DefineAdapter.kt @@ -0,0 +1,39 @@ +package kr.genti.presentation.create + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import kr.genti.core.util.ItemDiffCallback +import kr.genti.presentation.databinding.ItemDefineExampleBinding + +class DefineAdapter : ListAdapter(diffUtil) { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): DefineViewHolder { + val inflater = LayoutInflater.from(parent.context) + val binding = ItemDefineExampleBinding.inflate(inflater, parent, false) + return DefineViewHolder(binding) + } + + override fun onBindViewHolder( + holder: DefineViewHolder, + position: Int, + ) { + val item = getItem(position) ?: return + holder.onBind(item) + } + + override fun getItemCount(): Int = TOTAL_VIEW_COUNT + + companion object { + const val TOTAL_VIEW_COUNT = 5 + + private val diffUtil = + ItemDiffCallback( + onItemsTheSame = { old, new -> old == new }, + onContentsTheSame = { old, new -> old == new }, + ) + } +} \ No newline at end of file diff --git a/presentation/src/main/java/kr/genti/presentation/create/DefineFragment.kt b/presentation/src/main/java/kr/genti/presentation/create/DefineFragment.kt index 3fe377f1..71b6fe68 100644 --- a/presentation/src/main/java/kr/genti/presentation/create/DefineFragment.kt +++ b/presentation/src/main/java/kr/genti/presentation/create/DefineFragment.kt @@ -1,27 +1,15 @@ package kr.genti.presentation.create -import android.app.Activity -import android.content.Intent -import android.net.Uri import android.os.Bundle import android.view.View -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.PickVisualMediaRequest -import androidx.activity.result.contract.ActivityResultContracts -import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia.Companion.isPhotoPickerAvailable -import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController -import coil.load +import androidx.viewpager2.widget.ViewPager2 import dagger.hilt.android.AndroidEntryPoint import kr.genti.core.base.BaseFragment -import kr.genti.core.extension.getFileName -import kr.genti.core.extension.initOnBackPressedListener import kr.genti.core.extension.setOnSingleClickListener -import kr.genti.core.extension.toast -import kr.genti.domain.entity.response.ImageFileModel -import kr.genti.domain.entity.response.ImageFileModel.Companion.emptyImageFileModel import kr.genti.presentation.R +import kr.genti.presentation.create.CreateViewModel.Companion.promptList import kr.genti.presentation.databinding.FragmentDefineBinding import kr.genti.presentation.util.AmplitudeManager import kr.genti.presentation.util.AmplitudeManager.EVENT_CLICK_BTN @@ -31,8 +19,10 @@ import kr.genti.presentation.util.AmplitudeManager.PROPERTY_PAGE @AndroidEntryPoint class DefineFragment() : BaseFragment(R.layout.fragment_define) { private val viewModel by activityViewModels() - private lateinit var photoPickerResult: ActivityResultLauncher - private lateinit var galleryPickerResult: ActivityResultLauncher + + private var _adapter: DefineAdapter? = null + private val adapter + get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) } override fun onViewCreated( view: View, @@ -42,21 +32,12 @@ class DefineFragment() : BaseFragment(R.layout.fragment_d initView() initCreateBtnListener() - initRefreshExBtnListener() - initAddImageBtnListener() - initDeleteBtnListener() - setGalleryImageWithPhotoPicker() - setGalleryImageWithGalleryPicker() - } - - override fun onResume() { - super.onResume() - setSavedImage() + initViewPager() + setPromptExample() } private fun initView() { binding.vm = viewModel - binding.tvCreateRandomExample.text = viewModel.getRandomPrompt() } private fun initCreateBtnListener() { @@ -71,86 +52,30 @@ class DefineFragment() : BaseFragment(R.layout.fragment_d } } - private fun initRefreshExBtnListener() { - binding.btnRefresh.setOnClickListener { - AmplitudeManager.apply { - trackEvent( - EVENT_CLICK_BTN, - mapOf(PROPERTY_PAGE to "create1"), - mapOf(PROPERTY_BTN to "promptsuggest_refresh"), - ) - plusIntProperties("user_promptsuggest_refresh") - } - binding.tvCreateRandomExample.text = viewModel.getRandomPrompt() - } - } - - private fun initAddImageBtnListener() { + private fun initViewPager() { + _adapter = DefineAdapter() with(binding) { - btnCreatePlus.setOnSingleClickListener { checkAndGetImages() } - layoutPlusImage.setOnSingleClickListener { checkAndGetImages() } - } - } - - private fun initDeleteBtnListener() { - binding.btnDeleteImage.setOnSingleClickListener { - viewModel.plusImage = emptyImageFileModel() - binding.layoutPlusImage.isVisible = false - binding.btnDeleteImage.isVisible = false - } - } - - private fun checkAndGetImages() { - if (isPhotoPickerAvailable(requireContext())) { - photoPickerResult.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) - } else { - galleryPickerResult.launch( - Intent(Intent.ACTION_PICK).apply { type = "image/*" }, - ) - } - } - - private fun setGalleryImageWithPhotoPicker() { - photoPickerResult = - registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> - if (uri != null) setImageWithUri(uri) - } - } - - private fun setGalleryImageWithGalleryPicker() { - galleryPickerResult = - registerForActivityResult( - ActivityResultContracts.StartActivityForResult(), - ) { result -> - when (result.resultCode) { - Activity.RESULT_OK -> result.data?.data?.let { setImageWithUri(it) } - Activity.RESULT_CANCELED -> return@registerForActivityResult - else -> toast(getString(R.string.selfie_toast_picker_error)) + vpCreateRandom.adapter = adapter + vpCreateRandom.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + AmplitudeManager.apply { + trackEvent( + EVENT_CLICK_BTN, + mapOf(PROPERTY_PAGE to "create1"), + mapOf(PROPERTY_BTN to "promptsuggest_refresh"), + ) + plusIntProperties("user_promptsuggest_refresh") + } } - } - } - - private fun setImageWithUri(uri: Uri) { - viewModel.plusImage = - ImageFileModel( - uri.hashCode().toLong(), - uri.getFileName(requireActivity().contentResolver).toString(), - uri.toString(), - ) - with(binding) { - ivAddedImage.load(uri) - layoutPlusImage.isVisible = true - btnDeleteImage.isVisible = true + }) + dotIndicator.setViewPager(binding.vpCreateRandom) } } - private fun setSavedImage() { - if (viewModel.plusImage.id != (-1).toLong()) { - with(binding) { - ivAddedImage.load(viewModel.plusImage.url) - layoutPlusImage.isVisible = true - btnDeleteImage.isVisible = true - } - } + private fun setPromptExample() { + adapter.submitList(promptList.subList(0, 5)) + adapter.notifyDataSetChanged() } + } diff --git a/presentation/src/main/java/kr/genti/presentation/create/DefineViewHolder.kt b/presentation/src/main/java/kr/genti/presentation/create/DefineViewHolder.kt new file mode 100644 index 00000000..3e46bd81 --- /dev/null +++ b/presentation/src/main/java/kr/genti/presentation/create/DefineViewHolder.kt @@ -0,0 +1,15 @@ +package kr.genti.presentation.create + +import androidx.recyclerview.widget.RecyclerView +import kr.genti.core.extension.breakLines +import kr.genti.presentation.databinding.ItemDefineExampleBinding + +class DefineViewHolder( + val binding: ItemDefineExampleBinding, +) : RecyclerView.ViewHolder(binding.root) { + fun onBind(item: String) { + with(binding) { + tvDefineExample.text = item.breakLines() + } + } +} diff --git a/presentation/src/main/java/kr/genti/presentation/create/PoseFragment.kt b/presentation/src/main/java/kr/genti/presentation/create/PoseFragment.kt index 3c68f44a..26edd36e 100644 --- a/presentation/src/main/java/kr/genti/presentation/create/PoseFragment.kt +++ b/presentation/src/main/java/kr/genti/presentation/create/PoseFragment.kt @@ -19,8 +19,6 @@ import kr.genti.presentation.util.AmplitudeManager.PROPERTY_PAGE class PoseFragment() : BaseFragment(R.layout.fragment_pose) { private val viewModel by activityViewModels() - private var createGuideDialog: CreateGuideDialog? = null - override fun onViewCreated( view: View, savedInstanceState: Bundle?, @@ -30,7 +28,6 @@ class PoseFragment() : BaseFragment(R.layout.fragment_pose) initView() initNextBtnListener() initBackPressedListener() - initGuideIfNeeded() } private fun initView() { @@ -50,38 +47,13 @@ class PoseFragment() : BaseFragment(R.layout.fragment_pose) } private fun initBackPressedListener() { - val onBackPressedCallback = + requireActivity().onBackPressedDispatcher.addCallback( + viewLifecycleOwner, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - if (isAdded) { - findNavController().popBackStack() - viewModel.modCurrentPercent(-33) - } else { - requireActivity().onBackPressedDispatcher.onBackPressed() - } + viewModel.modCurrentPercent(-33) + findNavController().popBackStack() } - } - activity?.onBackPressedDispatcher?.addCallback( - requireActivity(), - onBackPressedCallback, - ) - } - - private fun initGuideIfNeeded() { - if (viewModel.getIsGuideNeeded()) { - createGuideDialog = CreateGuideDialog() - createGuideDialog?.show(childFragmentManager, DIALOG_GUIDE) - viewModel.setIsGuideNeeded(false) - } - } - - override fun onDestroyView() { - super.onDestroyView() - - createGuideDialog = null - } - - companion object { - const val DIALOG_GUIDE = "DIALOG_GUIDE" + }) } } diff --git a/presentation/src/main/java/kr/genti/presentation/create/SelfieFragment.kt b/presentation/src/main/java/kr/genti/presentation/create/SelfieFragment.kt index 47f476ab..543358bc 100644 --- a/presentation/src/main/java/kr/genti/presentation/create/SelfieFragment.kt +++ b/presentation/src/main/java/kr/genti/presentation/create/SelfieFragment.kt @@ -34,7 +34,6 @@ import kr.genti.domain.entity.response.ImageFileModel import kr.genti.presentation.R import kr.genti.presentation.databinding.FragmentSelfieBinding import kr.genti.presentation.generate.waiting.WaitingActivity -import kr.genti.presentation.main.MainActivity import kr.genti.presentation.main.feed.FeedFragment import kr.genti.presentation.util.AmplitudeManager import kr.genti.presentation.util.AmplitudeManager.EVENT_CLICK_BTN @@ -45,6 +44,7 @@ import kotlin.math.max @AndroidEntryPoint class SelfieFragment : BaseFragment(R.layout.fragment_selfie) { private val viewModel by activityViewModels() + private lateinit var photoPickerResult: ActivityResultLauncher private lateinit var galleryPickerResult: ActivityResultLauncher private lateinit var waitingResult: ActivityResultLauncher @@ -78,19 +78,14 @@ class SelfieFragment : BaseFragment(R.layout.fragment_sel } private fun initBackPressedListener() { - val onBackPressedCallback = + requireActivity().onBackPressedDispatcher.addCallback( + viewLifecycleOwner, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - if (isAdded) { - findNavController().popBackStack() - viewModel.modCurrentPercent(-34) - } + viewModel.modCurrentPercent(-34) + findNavController().popBackStack() } - } - activity?.onBackPressedDispatcher?.addCallback( - requireActivity(), - onBackPressedCallback, - ) + }) } private fun initAddImageBtnListener() { diff --git a/presentation/src/main/res/drawable/btn_play.xml b/presentation/src/main/res/drawable/btn_play.xml new file mode 100644 index 00000000..e80331c4 --- /dev/null +++ b/presentation/src/main/res/drawable/btn_play.xml @@ -0,0 +1,9 @@ + + + diff --git a/presentation/src/main/res/drawable/ic_indicator_grey5.xml b/presentation/src/main/res/drawable/ic_indicator_white_30.xml similarity index 89% rename from presentation/src/main/res/drawable/ic_indicator_grey5.xml rename to presentation/src/main/res/drawable/ic_indicator_white_30.xml index e9310364..67d16ad7 100644 --- a/presentation/src/main/res/drawable/ic_indicator_grey5.xml +++ b/presentation/src/main/res/drawable/ic_indicator_white_30.xml @@ -5,5 +5,5 @@ android:viewportHeight="10"> + android:fillColor="@color/white_30"/> diff --git a/presentation/src/main/res/drawable/img_green_bg_2_word.xml b/presentation/src/main/res/drawable/img_green_bg_2_word.xml deleted file mode 100644 index 1a095798..00000000 --- a/presentation/src/main/res/drawable/img_green_bg_2_word.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - diff --git a/presentation/src/main/res/drawable/img_green_bg_3_word.xml b/presentation/src/main/res/drawable/img_green_bg_3_word.xml deleted file mode 100644 index 93035f86..00000000 --- a/presentation/src/main/res/drawable/img_green_bg_3_word.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/presentation/src/main/res/drawable/img_guide_bg.png b/presentation/src/main/res/drawable/img_guide_bg.png deleted file mode 100644 index 452306cf..00000000 Binary files a/presentation/src/main/res/drawable/img_guide_bg.png and /dev/null differ diff --git a/presentation/src/main/res/drawable/img_guide_ex.png b/presentation/src/main/res/drawable/img_guide_ex.png deleted file mode 100644 index a893a728..00000000 Binary files a/presentation/src/main/res/drawable/img_guide_ex.png and /dev/null differ diff --git a/presentation/src/main/res/drawable/layerlist_create_progressbar.xml b/presentation/src/main/res/drawable/layerlist_create_progressbar.xml index ea392dc1..b4e6e6aa 100644 --- a/presentation/src/main/res/drawable/layerlist_create_progressbar.xml +++ b/presentation/src/main/res/drawable/layerlist_create_progressbar.xml @@ -1,15 +1,16 @@ - - + - - + diff --git a/presentation/src/main/res/drawable/sel_btn.xml b/presentation/src/main/res/drawable/sel_btn.xml index aed2344e..919e18f2 100644 --- a/presentation/src/main/res/drawable/sel_btn.xml +++ b/presentation/src/main/res/drawable/sel_btn.xml @@ -4,7 +4,7 @@ - + @@ -12,7 +12,10 @@ - + diff --git a/presentation/src/main/res/drawable/shape_black_fill_10_rect.xml b/presentation/src/main/res/drawable/shape_black_fill_10_rect.xml new file mode 100644 index 00000000..f134f84d --- /dev/null +++ b/presentation/src/main/res/drawable/shape_black_fill_10_rect.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/activity_create.xml b/presentation/src/main/res/layout/activity_create.xml index 5db5d378..d2199fad 100644 --- a/presentation/src/main/res/layout/activity_create.xml +++ b/presentation/src/main/res/layout/activity_create.xml @@ -15,15 +15,15 @@ + android:background="@color/black"> - @@ -32,34 +32,43 @@ android:id="@+id/btn_back" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="28dp" - android:layout_marginTop="9dp" + android:layout_marginStart="16dp" + android:layout_marginTop="5dp" android:src="@drawable/ic_back" - android:visibility="gone" + app:layout_constraintBottom_toBottomOf="@id/tv_create_title" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@id/iv_create_logo" - tools:visibility="visible" /> + app:layout_constraintTop_toTopOf="@id/tv_create_title" /> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_create_title" /> + + diff --git a/presentation/src/main/res/layout/dialog_create_guide.xml b/presentation/src/main/res/layout/dialog_create_guide.xml deleted file mode 100644 index 8dde8fa4..00000000 --- a/presentation/src/main/res/layout/dialog_create_guide.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/presentation/src/main/res/layout/fragment_define.xml b/presentation/src/main/res/layout/fragment_define.xml index 58e7dff5..65126633 100644 --- a/presentation/src/main/res/layout/fragment_define.xml +++ b/presentation/src/main/res/layout/fragment_define.xml @@ -15,229 +15,146 @@ + android:background="@color/black"> - + + + + + + + + + + + + + + + + + app:layout_constraintStart_toStartOf="parent"> - - - - - + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_margin="16dp" + android:background="@drawable/shape_black_fill_10_rect" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - - - - + app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - - - - - - - - - - - - - + app:layout_constraintTop_toTopOf="parent" /> - - + diff --git a/presentation/src/main/res/layout/item_define_example.xml b/presentation/src/main/res/layout/item_define_example.xml new file mode 100644 index 00000000..c011f1a6 --- /dev/null +++ b/presentation/src/main/res/layout/item_define_example.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 2d3117ac..d955fd48 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -38,12 +38,12 @@ 다음으로 젠티하러 가기 - 만들고 싶은 사진을 설명해주세요✏️ - 성적이거나 폭력적인 사진은 만들어지지 않아요 - 의상과 배경을 포함해서 설명해 주세요!\n\n*헤어스타일을 변경하는 기능은 준비 중이에요\n*너무 특정한 배경과 의상은 어려울 수 있어요\n(반포 한강 공원, 나이키 티셔츠 등) - 참고할 구도의 사진이 있다면 추가해주세요 (선택) - (선택) - (참고사진은 최대 1장 업로드 할 수 있어요) + 사진 만들기 + %1$d/3 + 어떤 사진을 만들고 싶나요? + AI가 이해하지 못하는 장소나 의상은 생성이 어려울 수 있어요. + 성적이거나 폭력적인 사진은 생성되지 않아요. + 만들고 싶은 사진을 설명해주세요. 이런 사진은 어때요? 프랑스 야경을 즐기는 모습을 그려주세요. 항공점퍼를 입고 테라스에 서 있는 모습이에요. diff --git a/presentation/src/main/res/values/themes.xml b/presentation/src/main/res/values/themes.xml index e376b547..64e3906f 100644 --- a/presentation/src/main/res/values/themes.xml +++ b/presentation/src/main/res/values/themes.xml @@ -10,7 +10,10 @@ @color/black - @color/gray + @color/white_60 + + + @color/black @style/AppBottomSheetDialogTheme