Skip to content

Commit

Permalink
[MERGE] #30 -> develop
Browse files Browse the repository at this point in the history
[FEAT/#30] 리듬뷰 / 리듬 측정 결과 저장 API 구현
  • Loading branch information
Marchbreeze authored Jul 31, 2024
2 parents 4c142ed + cdcbead commit 3421071
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.kkkk.data.dataSource

import com.kkkk.data.dto.BaseResponse
import com.kkkk.data.dto.request.RecordRequestDto
import okhttp3.ResponseBody
import java.io.File

interface RhythmDataSource {
suspend fun postToGetRhythmUrl(
Expand All @@ -12,4 +12,8 @@ interface RhythmDataSource {
suspend fun getRhythmWav(
url: String
): ResponseBody

suspend fun postRhythmRecord(
request: RecordRequestDto
): BaseResponse<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.kkkk.data.dataSourceImpl

import com.kkkk.data.dataSource.RhythmDataSource
import com.kkkk.data.dto.BaseResponse
import com.kkkk.data.dto.request.RecordRequestDto
import com.kkkk.data.service.RhythmService
import okhttp3.ResponseBody
import javax.inject.Inject
Expand All @@ -17,4 +18,7 @@ constructor(

override suspend fun getRhythmWav(url: String): ResponseBody =
rhythmService.getRhythmWav(url)

override suspend fun postRhythmRecord(request: RecordRequestDto): BaseResponse<String> =
rhythmService.postRhythmRecord(request)
}
19 changes: 19 additions & 0 deletions data/src/main/java/com/kkkk/data/dto/request/RecordRequestDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.kkkk.data.dto.request

import com.kkkk.domain.entity.request.RecordRequestModel
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RecordRequestDto(
@SerialName("accuracy")
val accuracy: Double,
@SerialName("duration")
val duration: Int,
@SerialName("steps")
val steps: Int,
) {
companion object {
fun RecordRequestModel.toDto() = RecordRequestDto(accuracy, duration, steps)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.kkkk.data.repositoryImpl

import com.kkkk.data.dataSource.RhythmDataSource
import com.kkkk.data.dto.request.RecordRequestDto.Companion.toDto
import com.kkkk.domain.entity.request.RecordRequestModel
import com.kkkk.domain.repository.RhythmRepository
import javax.inject.Inject

Expand All @@ -19,4 +21,9 @@ constructor(
runCatching {
rhythmDataSource.getRhythmWav(url).bytes()
}

override suspend fun postRhythmRecord(request: RecordRequestModel): Result<String> =
runCatching {
rhythmDataSource.postRhythmRecord(request.toDto()).data
}
}
7 changes: 7 additions & 0 deletions data/src/main/java/com/kkkk/data/service/RhythmService.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.kkkk.data.service

import com.kkkk.data.dto.BaseResponse
import com.kkkk.data.dto.request.RecordRequestDto
import okhttp3.ResponseBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
Expand All @@ -17,4 +19,9 @@ interface RhythmService {
suspend fun getRhythmWav(
@Url url: String
): ResponseBody

@POST("api/v1/records")
suspend fun postRhythmRecord(
@Body request: RecordRequestDto
): BaseResponse<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.kkkk.domain.entity.request

data class RecordRequestModel(
val accuracy: Double,
val duration: Int,
val steps: Int,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.kkkk.domain.repository

import java.io.File
import com.kkkk.domain.entity.request.RecordRequestModel

interface RhythmRepository {
suspend fun postToGetRhythmUrl(
Expand All @@ -10,4 +10,8 @@ interface RhythmRepository {
suspend fun getRhythmWav(
url: String
): Result<ByteArray>

suspend fun postRhythmRecord(
request: RecordRequestModel
): Result<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class RhythmFragment : BaseFragment<FragmentRhythmBinding>(R.layout.fragment_rhy

private val viewModel by activityViewModels<RhythmViewModel>()
private var rhythmBottomSheet: RhythmBottomSheet? = null
private var rhythmSaveDialog: RhythmSaveDialog? = null
private lateinit var mediaPlayer: MediaPlayer

override fun onViewCreated(
Expand All @@ -44,6 +45,7 @@ class RhythmFragment : BaseFragment<FragmentRhythmBinding>(R.layout.fragment_rhy
observeRhythmLevel()
observeRhythmUrlState()
observeDownloadState()
observeRecordSaveState()
}

private fun initChangeLevelBtnListener() {
Expand All @@ -70,6 +72,8 @@ class RhythmFragment : BaseFragment<FragmentRhythmBinding>(R.layout.fragment_rhy
mediaPlayer.pause()
switchPlayingState(false)
}
rhythmSaveDialog = RhythmSaveDialog()
rhythmSaveDialog?.show(parentFragmentManager, DIALOG_RHYTHM_SAVE)
}
}

Expand Down Expand Up @@ -198,16 +202,33 @@ class RhythmFragment : BaseFragment<FragmentRhythmBinding>(R.layout.fragment_rhy
}
}

private fun observeRecordSaveState() {
viewModel.recordSaveState.flowWithLifecycle(lifecycle).distinctUntilChanged()
.onEach { state ->
when (state) {
is UiState.Success -> {
// TODO : 여기에서 기존 걸음 0으로 만드는 로직 필요
toast(stringOf(R.string.rhythm_toast_save_success))
}

is UiState.Failure -> toast(stringOf(R.string.error_msg))
else -> return@onEach
}
}.launchIn(lifecycleScope)
}

override fun onDestroyView() {
super.onDestroyView()
rhythmBottomSheet = null
rhythmSaveDialog = null
if (::mediaPlayer.isInitialized) {
mediaPlayer.release()
}
}

companion object {
private const val BOTTOM_SHEET_CHANGE_LEVEL = "BOTTOM_SHEET_CHANGE_LEVEL"
private const val DIALOG_RHYTHM_SAVE = "DIALOG_RHYTHM_SAVE"

private const val COLOR_PURPLE = "purple"
private const val COLOR_SKY = "sky"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.kkkk.presentation.main.rhythm

import android.os.Bundle
import android.view.View
import android.view.WindowManager
import androidx.fragment.app.activityViewModels
import com.kkkk.core.base.BaseDialog
import com.kkkk.core.extension.setOnSingleClickListener
import kr.genti.presentation.R
import kr.genti.presentation.databinding.DialogRhythmSaveBinding

class RhythmSaveDialog :
BaseDialog<DialogRhythmSaveBinding>(R.layout.dialog_rhythm_save) {
private val viewModel by activityViewModels<RhythmViewModel>()

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)

initPauseBtnListener()
initSaveBtnListener()
}

private fun initPauseBtnListener() {
binding.btnPause.setOnSingleClickListener { dismiss() }
}

private fun initSaveBtnListener() {
binding.btnSave.setOnSingleClickListener {
viewModel.posRhythmRecordToSave()
dismiss()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.kkkk.core.state.UiState
import com.kkkk.domain.entity.request.RecordRequestModel
import com.kkkk.domain.repository.RhythmRepository
import com.kkkk.domain.repository.UserRepository
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -24,6 +25,9 @@ constructor(
var filename: String = "stempo_level_1"
var isSubmitted: Boolean = true

// TODO : 정확도 만져주세용 ㅎㅎ
var accuracy: Double = 1.0

private val _rhythmLevel = MutableStateFlow<Int>(LEVEL_UNDEFINED)
val rhythmLevel: StateFlow<Int> = _rhythmLevel

Expand All @@ -33,6 +37,9 @@ constructor(
private val _downloadWavState = MutableStateFlow<UiState<ByteArray>>(UiState.Empty)
val downloadWavState: StateFlow<UiState<ByteArray>> = _downloadWavState

private val _recordSaveState = MutableStateFlow<UiState<String>>(UiState.Empty)
val recordSaveState: StateFlow<UiState<String>> = _recordSaveState

init {
initRhythmLevelFromDataStore()
}
Expand Down Expand Up @@ -91,6 +98,19 @@ constructor(
}
}

fun posRhythmRecordToSave() {
_recordSaveState.value = UiState.Loading
viewModelScope.launch {
rhythmRepository.postRhythmRecord(
RecordRequestModel(accuracy, 0, 0)
).onSuccess {
_recordSaveState.value = UiState.Success(it)
}.onFailure {
_recordSaveState.value = UiState.Failure(it.message.toString())
}
}
}

companion object {
const val LEVEL_UNDEFINED = -1
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="12dp" />
</shape>
64 changes: 64 additions & 0 deletions presentation/src/main/res/layout/dialog_rhythm_save.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?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">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_white_fill_16_rect"
android:paddingBottom="16dp">

<TextView
android:id="@+id/tv_rhythm_save_title"
style="@style/TextAppearance.Stempo.Head3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:lineSpacingMultiplier="1.3"
android:layout_marginTop="32dp"
android:gravity="center"
android:text="@string/rhythm_stop_tv_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/btn_save"
style="@style/TextAppearance.Stempo.Head4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="6dp"
android:background="@drawable/shape_purple10_fill_12_rect"
android:gravity="center"
android:paddingHorizontal="36dp"
android:paddingVertical="15dp"
android:text="@string/rhythm_stop_btn_save"
android:textColor="@color/purple_50"
app:layout_constraintEnd_toStartOf="@id/btn_pause"
app:layout_constraintStart_toStartOf="@id/tv_rhythm_save_title"
app:layout_constraintTop_toBottomOf="@id/tv_rhythm_save_title" />

<TextView
android:id="@+id/btn_pause"
style="@style/TextAppearance.Stempo.Head4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="32dp"
android:background="@drawable/shape_purple50_fill_12_rect"
android:gravity="center"
android:paddingHorizontal="36dp"
android:paddingVertical="15dp"
android:text="@string/rhythm_stop_btn_pause"
android:textColor="@color/purple_10"
app:layout_constraintEnd_toEndOf="@id/tv_rhythm_save_title"
app:layout_constraintStart_toEndOf="@id/btn_save"
app:layout_constraintTop_toBottomOf="@id/tv_rhythm_save_title" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
5 changes: 5 additions & 0 deletions presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
<string name="rhythm_tv_title">리듬에 맞춰 걸어주세요!</string>
<string name="rhythm_btn_change_level">단계 변경하기</string>
<string name="rhythm_btn_submit_level">완료하기</string>
<string name="rhythm_toast_save_success">기록 저장이 완료되었어요!</string>

<string name="rhythm_stop_tv_title">종료하기를 누르면\n지금까지의 걸음이 기록돼요.\n잠시 멈추시는거라면\n정지하기를 눌러주세요.</string>
<string name="rhythm_stop_btn_save">종료하기</string>
<string name="rhythm_stop_btn_pause">정지하기</string>

<string name="report_tv_title">동안의 성과에요!</string>
<string name="report_tv_achieve_title">달성한 업적</string>
Expand Down

0 comments on commit 3421071

Please sign in to comment.