Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ add taking time form for step making #358

Merged
merged 6 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class DefaultRecipeStepMakingRepository
private fun RecipeStepMaking.toRecipeStepEntity(): RecipeStepEntity =
RecipeStepEntity(
recipeDescriptionId = recipeId,
cookingTime = "00:00:00",
cookingTime = cookingTime,
stepNumber = sequence,
description = description.ifEmpty { null },
imageUri = imageUri.ifEmpty { null },
Expand All @@ -70,5 +70,6 @@ class DefaultRecipeStepMakingRepository
description = description ?: "",
imageUri = imageUri ?: "",
image = imageTitle ?: "",
cookingTime = cookingTime ?: "00:00:00",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null 처리 굿입니다!

)
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fun RecipeStepEntity.toRecipeStepMaking(): RecipeStepMaking =
image = imageTitle ?: "",
imageUri = imageUri ?: "",
stepId = id,
cookingTime = cookingTime ?: "00:00:00",
)

fun IngredientEntity.toIngredient(): Ingredient =
Expand All @@ -90,7 +91,7 @@ fun Ingredient.toIngredientRequest(): IngredientRequest =

fun RecipeStepMaking.toRecipeStepRequest(): RecipeStepRequest =
RecipeStepRequest(
cookingTime = "00:00:00",
cookingTime = cookingTime,
description = description,
image = image,
sequence = sequence,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ data class RecipeStepMaking(
val image: String,
val sequence: Int,
val imageUri: String,
)
val cookingTime: String,
) {
init {
require(cookingTime.matches(Regex("\\d{2}:\\d{2}:\\d{2}"))) {
"cookingTime must be in the format of HH:MM:SS"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class FollowPagingSource(
return runCatching {
val users = fetchUsers()
val pageData = users.getOrNull() ?: emptyList()
println(pageData.size)
println(params.loadSize)
val nextKey = if (pageData.size < params.loadSize) null else pageNumber + 1
LoadResult.Page(
data = pageData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ class RecipeMakingFragment : Fragment() {
val etHour = binding.itemTimeRequired.etTimeAmountPicker.etHour
val etMinute = binding.itemTimeRequired.etTimeAmountPicker.etMinute
val etSecond = binding.itemTimeRequired.etTimeAmountPicker.etSecond
etHour.filters = arrayOf(MinMaxInputFilter(0, 23))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

시간에 맞는 필터사용 굿 👍

arrayOf(MinMaxInputFilter(0, 59)).also { filters ->
etHour.filters = filters
etMinute.filters = filters
etSecond.filters = filters
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import net.pengcook.android.databinding.FragmentMakingStepBinding
import net.pengcook.android.presentation.core.util.AnalyticsLogging
import net.pengcook.android.presentation.core.util.FileUtils
import net.pengcook.android.presentation.core.util.ImageUtils
import net.pengcook.android.presentation.core.util.MinMaxInputFilter
import java.io.File
import javax.inject.Inject

Expand Down Expand Up @@ -111,6 +112,7 @@ class StepMakingFragment : Fragment() {
) {
super.onViewCreated(view, savedInstanceState)
initBinding()
initTimeFormatInput()
AnalyticsLogging.viewLogEvent("RecipeMaking")
observeViewModel()
}
Expand All @@ -127,6 +129,15 @@ class StepMakingFragment : Fragment() {
binding.appbarEventListener = viewModel
}

private fun initTimeFormatInput() {
val etMinute = binding.etTimeAmount.etTimeAmountPicker.etMinute
val etSecond = binding.etTimeAmount.etTimeAmountPicker.etSecond
arrayOf(MinMaxInputFilter(0, 59)).also { filters ->
etMinute.filters = filters
etSecond.filters = filters
}
}

private fun observeViewModel() {
viewModel.uiEvent.observe(viewLifecycleOwner) { event ->
val newEvent = event.getContentIfNotHandled() ?: return@observe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class StepMakingViewModel
) : ViewModel(),
StepMakingEventHandler,
AppbarDoubleActionEventListener {
private val stepTraversalStatus = MutableList(maximumStep) { false }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 내용은 정확히 로직이 이해가 되지 않네요... 오프라인으로 설명 한번 들으러 가겠습니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

설명 잘 들었습니다! approve 하겠습니다!


private val _stepNumber = MutableLiveData<Int>(1)
val stepNumber: LiveData<Int> get() = _stepNumber

Expand Down Expand Up @@ -56,8 +58,17 @@ class StepMakingViewModel
val uiEvent: LiveData<Event<RecipeStepMakingEvent>>
get() = _uiEvent

private var completionPressed = false

private val _errorVisibility: MutableLiveData<Boolean> = MutableLiveData(false)
val errorVisibility: LiveData<Boolean>
get() = _errorVisibility

private val stepCompletion: MutableMap<Int, Boolean> = mutableMapOf(1 to false)

val minuteContent = MutableLiveData<String>()
val secondContent = MutableLiveData<String>()

init {
val stepNumber = stepNumber.value
if (stepNumber != null) {
Expand All @@ -72,6 +83,7 @@ class StepMakingViewModel
override fun moveToNextPage() {
val imageUploaded = imageUploaded.value
val introduction = introductionContent.value

if (imageUploaded != true) {
_uiEvent.value = Event(RecipeStepMakingEvent.ImageNotUploaded)
return
Expand Down Expand Up @@ -115,6 +127,9 @@ class StepMakingViewModel

override fun customAction() {
viewModelScope.launch {
completionPressed = true
_errorVisibility.value = true

if (imageSelected.value != true) {
_uiEvent.value = Event(RecipeStepMakingEvent.FormNotCompleted)
return@launch
Expand Down Expand Up @@ -184,6 +199,8 @@ class StepMakingViewModel
private fun initStepData(stepNumber: Int) {
viewModelScope.launch {
_isLoading.value = true
_errorVisibility.value = completionPressed && stepTraversalStatus[stepNumber - 1]
stepTraversalStatus[stepNumber - 1] = true
_imageUri.value = null
fetchRecipeStep(stepNumber)
_isLoading.value = false
Expand Down Expand Up @@ -214,6 +231,8 @@ class StepMakingViewModel
_imageUploaded.value = false
introductionContent.value = ""
thumbnailTitle = null
minuteContent.value = ""
secondContent.value = ""
}

private suspend fun postRecipe(recipeCreation: RecipeCreation) {
Expand Down Expand Up @@ -249,7 +268,13 @@ class StepMakingViewModel
sequence = stepNumber,
).onSuccess { recipeStep ->
if (recipeStep == null) return@onSuccess
val minute =
recipeStep.cookingTime.split(SEPARATOR_TIME).getOrNull(1) ?: DEFAULT_TIME_STRING
val second =
recipeStep.cookingTime.split(SEPARATOR_TIME).getOrNull(2) ?: DEFAULT_TIME_STRING
introductionContent.value = recipeStep.description
minuteContent.value = if (minute.toIntOrNull() == 0) DEFAULT_TIME_STRING else minute
secondContent.value = if (second.toIntOrNull() == 0) DEFAULT_TIME_STRING else second
if (recipeStep.imageUri.isNotEmpty()) {
_imageUri.value = Uri.parse(recipeStep.imageUri)
}
Expand All @@ -269,14 +294,23 @@ class StepMakingViewModel
stepNumber: Int,
stepAction: StepAction,
) {
val minute = minuteContent.value
val second = secondContent.value

val recipeStep =
RecipeStepMaking(
recipeId = recipeId,
sequence = stepNumber,
description = introductionContent.value ?: "",
image = thumbnailTitle ?: "",
description = introductionContent.value ?: DEFAULT_TIME_STRING,
image = thumbnailTitle ?: DEFAULT_TIME_STRING,
stepId = 1L,
imageUri = imageUri.value?.toString() ?: "",
imageUri = imageUri.value?.toString() ?: DEFAULT_IMAGE_URI,
cookingTime =
FORMAT_TIME_REQUIRED.format(
DEFAULT_TIME_VALUE,
minute?.toIntOrNull() ?: DEFAULT_TIME_VALUE,
second?.toIntOrNull() ?: DEFAULT_TIME_VALUE,
),
)

recipeStepMakingRepository.saveRecipeStep(recipeId = recipeId, recipeStep = recipeStep)
Expand All @@ -290,6 +324,12 @@ class StepMakingViewModel
}

companion object {
private const val FORMAT_TIME_REQUIRED = "%02d:%02d:%02d"
private const val SEPARATOR_TIME = ":"
private const val DEFAULT_TIME_STRING = ""
private const val DEFAULT_TIME_VALUE = 0
private const val DEFAULT_IMAGE_URI = ""

fun provideFactory(
assistedFactory: StepMakingViewModelFactory,
recipeId: Long,
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/res/layout/fragment_detail_recipe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
android:id="@+id/iv_thumbnail_recipe"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
android:scaleType="centerCrop"
app:imageUrl="@{recipe.thumbnail}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
Expand Down
20 changes: 17 additions & 3 deletions android/app/src/main/res/layout/fragment_making_step.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,22 @@

</androidx.constraintlayout.widget.ConstraintLayout>

<include
android:id="@+id/et_time_amount"
layout="@layout/item_minute_second_picker_with_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/cl_btn_add_image"
app:title="@{@string/making_form_time_required}"
app:minute="@={vm.minuteContent}"
app:second="@={vm.secondContent}"
app:visibleCondition="@{vm.errorVisibility}"/>

<include
android:id="@+id/et_guide_step_recipe"
layout="@layout/item_form_multi_text"
layout="@layout/item_form_multi_text_with_warning"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
Expand All @@ -95,8 +108,9 @@
app:hintContent="@{@string/step_making_hint}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_btn_add_image"
app:title="@{String.valueOf(vm.stepNumber)}" />
app:layout_constraintTop_toBottomOf="@id/et_time_amount"
app:title="@{String.valueOf(vm.stepNumber)}"
app:errorVisibility="@{vm.errorVisibility}"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/res/layout/fragment_sign_up.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
android:layout_marginHorizontal="16dp"
android:layout_marginBottom="12dp"
app:buttonClickListener="@{viewModel}"
app:buttonText="@{(viewModel.imageUploaded == false &amp;&amp; viewModel.imageSelected == true) ? @string/making_uploading_image : @string/making_step}"
app:buttonText="@{(viewModel.imageUploaded == false &amp;&amp; viewModel.imageSelected == true) ? @string/making_uploading_image : @string/signup_button_next}"
app:enabled="@{true}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/sv_sign_up" />
Expand Down
1 change: 0 additions & 1 deletion android/app/src/main/res/layout/item_form_multi_text.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="title"
type="String" />

<variable
name="hintContent"
type="String" />

<variable
name="content"
type="String" />

<variable
name="errorVisibility"
type="Boolean" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<include
android:id="@+id/et_content"
layout="@layout/item_form_multi_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:content="@={content}"
app:hintContent="@{hintContent}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:title="@{title}" />

<TextView
android:id="@+id/tv_alert_message"
style="@style/WarningMessageUnfilledForm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_content"
bind:visibility="@{errorVisibility &amp;&amp; (content == null || content.isEmpty())}" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Loading
Loading