Skip to content

Commit

Permalink
[feature/remove-databinding] Data Binding 라이브러리와 kapt 플러그인 제거 (#371)
Browse files Browse the repository at this point in the history
* Remove databinding at attendance code dialog

* Livedata의 combine 함수 구현하기

* color resource 값 가져오기

* AttendanceActivity쪽 데이터 바인딩 제거

* remove kotlin-kapt and databinding

* ktlint apply

* remove useless var and change transformation method with livedata

* resolve package conflicts

* remove useless log

* viewModel 상호작용 위치 변경

* apply ktlint

---------

Co-authored-by: hjh1161514 <[email protected]>
  • Loading branch information
l2hyunwoo and hjh1161514 authored Oct 15, 2023
1 parent 7ad8d46 commit 943a34b
Show file tree
Hide file tree
Showing 13 changed files with 621 additions and 571 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ android {
}
}
buildFeatures {
viewBinding = true
compose = true
}
composeOptions {
Expand Down Expand Up @@ -118,6 +117,7 @@ dependencies {
implementation(libs.process.phoenix)

implementation(libs.compose.destination.core)
implementation(libs.androidx.lifecycle.process)
ksp(libs.compose.destination.ksp)

androidTestImplementation(platform(libs.compose.bom))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import android.widget.TextView
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
Expand All @@ -32,26 +33,91 @@ import org.sopt.official.domain.entity.attendance.EventType
import org.sopt.official.domain.entity.attendance.SoptEvent
import org.sopt.official.feature.attendance.adapter.AttendanceAdapter
import org.sopt.official.feature.attendance.model.AttendanceState
import org.sopt.official.util.colorOf
import org.sopt.official.util.dp
import org.sopt.official.util.stringOf

@AndroidEntryPoint
class AttendanceActivity : AppCompatActivity() {
private lateinit var binding: ActivityAttendanceBinding
private val attendanceViewModel by viewModels<AttendanceViewModel>()
private val viewModel by viewModels<AttendanceViewModel>()
private lateinit var attendanceAdapter: AttendanceAdapter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAttendanceBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewModel = attendanceViewModel
binding.lifecycleOwner = this

initView()
initUiInteraction()
initListener()
fetchData()
observeData()
observeProgressState()
}

private fun observeProgressState() {
viewModel.isFirstToSecondLineActive.observe(this) {
binding.lineFirstToSecondActive.isInvisible = !it
}
viewModel.isSecondToThirdLineActive.observe(this) {
binding.lineSecondToThirdActive.isInvisible = !it
}
viewModel.isFirstProgressBarAttendance.observe(this) {
binding.ivAttendanceProgress1Check.setImageResource(
if (it) R.drawable.ic_attendance_check_gray else R.drawable.ic_attendance_close_gray
)
}
viewModel.isFirstProgressBarActive.observe(this) {
binding.ivAttendanceProgress1Check.isInvisible = !it
binding.tvAttendanceProgress1.setTextColor(
if (it) colorOf(R.color.white_100) else colorOf(R.color.gray_100)
)
}
viewModel.isSecondProgressBarAttendance.observe(this) {
binding.ivAttendanceProgress2Check.setImageResource(
if (it) R.drawable.ic_attendance_check_gray else R.drawable.ic_attendance_close_gray
)
}
viewModel.isSecondProgressBarActive.observe(this) {
binding.ivAttendanceProgress2Check.isInvisible = !it
binding.tvAttendanceProgress2.setTextColor(
if (it) colorOf(R.color.white_100) else colorOf(R.color.gray_100)
)
}
viewModel.isThirdProgressBarVisible.observe(this) {
binding.ivAttendanceProgress3Tardy.isInvisible = !it
binding.ivAttendanceProgress3Attendance.isInvisible = it
binding.tvAttendanceProgress3.text = stringOf(
if (it) R.string.attendance_progress_third_tardy else R.string.attendance_progress_third_complete
)
}
viewModel.isThirdProgressBarActive.observe(this) {
binding.ivAttendanceProgress3Empty.isInvisible = it
binding.tvAttendanceProgress3Attendance.text = stringOf(
if (it) R.string.attendance_progress_third_absent else R.string.attendance_progress_before
)
binding.tvAttendanceProgress3Attendance.setTextColor(
if (it) colorOf(R.color.white_100) else colorOf(R.color.gray_100)
)
}
viewModel.isThirdProgressBarBeforeAttendance.observe(this) {
binding.ivAttendanceProgress3Attendance.setImageResource(
if (it) R.drawable.ic_attendacne_check_white else R.drawable.ic_attendance_close_white
)
}
viewModel.isThirdProgressBarActiveAndBeforeAttendance.observe(this) {
binding.tvAttendanceProgress3.isInvisible = !it
binding.tvAttendanceProgress3Attendance.isInvisible = it
}
viewModel.isAttendanceButtonEnabled.observe(this) {
binding.btnAttendance.isEnabled = it
}
viewModel.attendanceButtonText.observe(this) {
binding.btnAttendance.text = it
}
viewModel.isAttendanceButtonVisibility.observe(this) {
binding.btnAttendance.isVisible = it
}
}

private fun initView() {
Expand All @@ -63,14 +129,7 @@ class AttendanceActivity : AppCompatActivity() {
private fun initUiInteraction() {
binding.icRefresh.setOnClickListener {
it.startAnimation(AnimationUtils.loadAnimation(this, R.anim.anim_rotation))
fetchData()
}
}

private fun fetchData() {
attendanceViewModel.run {
fetchSoptEvent()
fetchAttendanceHistory()
viewModel.fetchData()
}
}

Expand Down Expand Up @@ -121,7 +180,7 @@ class AttendanceActivity : AppCompatActivity() {
}

private fun observeSoptEvent() {
attendanceViewModel.soptEvent
viewModel.soptEvent
.flowWithLifecycle(lifecycle)
.onEach {
when (it) {
Expand All @@ -133,7 +192,7 @@ class AttendanceActivity : AppCompatActivity() {
}

private fun observeAttendanceHistory() {
attendanceViewModel.attendanceHistory
viewModel.attendanceHistory
.flowWithLifecycle(lifecycle)
.onEach {
when (it) {
Expand Down Expand Up @@ -192,7 +251,7 @@ class AttendanceActivity : AppCompatActivity() {
setSpan(StyleSpan(Typeface.BOLD), 4, 4 + (soptEvent.eventName.length), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
layoutAttendanceProgress.isVisible = true
attendanceViewModel.setProgressBar(soptEvent)
viewModel.setProgressBar(soptEvent)
when (soptEvent.attendances.size) {
1 -> {
tvAttendanceProgress1.text = if (soptEvent.attendances[0].status == AttendanceStatus.ATTENDANCE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ import androidx.core.widget.addTextChangedListener
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.sopt.official.databinding.DialogAttendanceCodeBinding
import org.sopt.official.feature.attendance.model.DialogState

class AttendanceCodeDialog : DialogFragment() {
private var _binding: DialogAttendanceCodeBinding? = null
private val binding: DialogAttendanceCodeBinding get() = requireNotNull(_binding)
private val attendanceViewModel: AttendanceViewModel by activityViewModels()
private var title: String = ""
private val viewModel: AttendanceViewModel by activityViewModels()
private lateinit var dialogTitle: String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -51,7 +54,6 @@ class AttendanceCodeDialog : DialogFragment() {
savedInstanceState: Bundle?
): View {
_binding = DialogAttendanceCodeBinding.inflate(inflater, container, false)
binding.lifecycleOwner = viewLifecycleOwner
return binding.root
}

Expand All @@ -63,12 +65,16 @@ class AttendanceCodeDialog : DialogFragment() {
}

fun setTitle(title: String): AttendanceCodeDialog {
this.title = title
dialogTitle = title
return this
}

private fun initTitle() {
binding.titleText = "${title.substring(0, 5)}하기"
viewModel.initDialogTitle(dialogTitle)
viewModel.title
.flowWithLifecycle(viewLifecycleOwner.lifecycle)
.onEach { binding.tvAttendanceCodeDialogTitle.text = "${it.substring(0, 5)}하기" }
.launchIn(viewLifecycleOwner.lifecycleScope)
}

private fun initListener() {
Expand Down Expand Up @@ -178,7 +184,7 @@ class AttendanceCodeDialog : DialogFragment() {
dismiss()
}
btnAttendanceCodeDialog.setOnClickListener {
attendanceViewModel.checkAttendanceCode(
viewModel.checkAttendanceCode(
"${etAttendanceCode1.text}${etAttendanceCode2.text}${etAttendanceCode3.text}" +
"${etAttendanceCode4.text}${etAttendanceCode5.text}"
)
Expand All @@ -187,17 +193,17 @@ class AttendanceCodeDialog : DialogFragment() {
}

override fun dismiss() {
attendanceViewModel.initDialogState()
viewModel.initDialogState()
super.dismiss()
}

private fun observeState() {
viewLifecycleOwner.lifecycleScope.launch {
attendanceViewModel.dialogState.collectLatest {
viewModel.dialogState.collectLatest {
when (it) {
is DialogState.Close -> {
dismiss()
attendanceViewModel.run {
viewModel.run {
fetchSoptEvent()
initDialogState()
dialogErrorMessage = ""
Expand All @@ -219,7 +225,7 @@ class AttendanceCodeDialog : DialogFragment() {

// 에러 메시지 나타나도록
tvAttendanceCodeDialogError.visibility = View.VISIBLE
tvAttendanceCodeDialogError.text = attendanceViewModel.dialogErrorMessage
tvAttendanceCodeDialogError.text = viewModel.dialogErrorMessage

// 키보드 내리기
hideKeyboard()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.sopt.official.feature.attendance

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
Expand All @@ -9,6 +8,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.sopt.official.domain.entity.attendance.AttendanceHistory
import org.sopt.official.domain.entity.attendance.AttendanceRound
Expand Down Expand Up @@ -44,13 +44,15 @@ class AttendanceViewModel @Inject constructor(
private val attendanceRepository: AttendanceRepository
) : ViewModel() {
private var eventId: Int = 0
private var _soptEvent = MutableStateFlow<AttendanceState<SoptEvent>>(AttendanceState.Init)
private val _title: MutableStateFlow<String> = MutableStateFlow("")
val title = _title.asStateFlow()
private val _soptEvent = MutableStateFlow<AttendanceState<SoptEvent>>(AttendanceState.Init)
val soptEvent: StateFlow<AttendanceState<SoptEvent>> get() = _soptEvent
private var _attendanceHistory = MutableStateFlow<AttendanceState<AttendanceHistory>>(AttendanceState.Init)
private val _attendanceHistory = MutableStateFlow<AttendanceState<AttendanceHistory>>(AttendanceState.Init)
val attendanceHistory: StateFlow<AttendanceState<AttendanceHistory>> get() = _attendanceHistory
private var _attendanceRound = MutableStateFlow<AttendanceState<AttendanceRound>>(AttendanceState.Init)
private val _attendanceRound = MutableStateFlow<AttendanceState<AttendanceRound>>(AttendanceState.Init)
val attendanceRound: StateFlow<AttendanceState<AttendanceRound>> get() = _attendanceRound
private var _dialogState = MutableStateFlow<DialogState>(DialogState.Show)
private val _dialogState = MutableStateFlow<DialogState>(DialogState.Show)
val dialogState: StateFlow<DialogState> get() = _dialogState

private val progressBarState = MutableLiveData(ProgressBarState())
Expand All @@ -62,8 +64,11 @@ class AttendanceViewModel @Inject constructor(
val isSecondToThirdLineActive: LiveData<Boolean> = progressBarState.map { it.isSecondToThirdLineActive }
val isThirdProgressBarActive: LiveData<Boolean> = progressBarState.map { it.isThirdProgressBarActive }
val isThirdProgressBarAttendance: LiveData<Boolean> = progressBarState.map { it.isThirdProgressBarAttendance }
val isThirdProgressBarTardy: LiveData<Boolean> = progressBarState.map { it.isThirdProgressBarTardy }
private val isThirdProgressBarTardy: LiveData<Boolean> = progressBarState.map { it.isThirdProgressBarTardy }
val isThirdProgressBarBeforeAttendance: LiveData<Boolean> = progressBarState.map { it.isThirdProgressBarBeforeAttendance }
val isThirdProgressBarVisible = progressBarState.map { it.isThirdProgressBarActive && it.isThirdProgressBarTardy }
val isThirdProgressBarActiveAndBeforeAttendance =
progressBarState.map { it.isThirdProgressBarActive && it.isThirdProgressBarBeforeAttendance }

private val attendanceButtonState = MutableLiveData(AttendanceButtonState())
val isAttendanceButtonEnabled: LiveData<Boolean> = attendanceButtonState.map { it.isAttendanceButtonEnabled }
Expand All @@ -74,9 +79,17 @@ class AttendanceViewModel @Inject constructor(
var dialogErrorMessage: String = ""
private var attendancesSize = 0

companion object {
private const val FIRST_ATTENDANCE_TEXT = "1차 출석"
private const val SECOND_ATTENDANCE_TEXT = "2차 출석"
init {
fetchData()
}

fun fetchData() {
fetchSoptEvent()
fetchAttendanceHistory()
}

fun initDialogTitle(title: String) {
_title.value = title
}

fun fetchSoptEvent() {
Expand Down Expand Up @@ -125,9 +138,6 @@ class AttendanceViewModel @Inject constructor(
val firstProgressText = soptEvent.attendances[0].attendedAt
val secondProgressText = soptEvent.attendances[1].attendedAt

Log.d("####hj", firstProgressText)
Log.d("####hj", secondProgressText)

if (firstProgressText != FIRST_ATTENDANCE_TEXT) {
// 1차 출석이 출석
setFirstProgressBar(true)
Expand Down Expand Up @@ -229,7 +239,7 @@ class AttendanceViewModel @Inject constructor(
setProgressBarState { copy(isThirdProgressBarBeforeAttendance = isBeforeAttendance) }
}

fun fetchAttendanceHistory() {
private fun fetchAttendanceHistory() {
viewModelScope.launch {
_attendanceHistory.value = AttendanceState.Loading
attendanceRepository.fetchAttendanceHistory()
Expand All @@ -247,7 +257,6 @@ class AttendanceViewModel @Inject constructor(
.onSuccess {
_attendanceRound.value = AttendanceState.Success(it)
subLectureId = it.id
Timber.tag("zzzz id").i(it.id.toString())
when (it.id) {
-1L -> {
setAttendanceButtonVisibility(false)
Expand All @@ -272,7 +281,6 @@ class AttendanceViewModel @Inject constructor(
}
}
}.onFailure {
Timber.tag("zzzz failure").e(it)
Timber.e(it)
}
}
Expand All @@ -295,21 +303,10 @@ class AttendanceViewModel @Inject constructor(
attendanceRepository.confirmAttendanceCode(subLectureId, code)
.onSuccess {
when (it.subLectureId) {
-2L -> {
showDialog("코드가 일치하지 않아요!")
}

-1L -> {
showDialog("출석 시간 전입니다.")
}

0L -> {
showDialog("출석이 이미 종료되었습니다.")
}

else -> {
_dialogState.value = DialogState.Close
}
-2L -> showDialog("코드가 일치하지 않아요!")
-1L -> showDialog("출석 시간 전입니다.")
0L -> showDialog("출석이 이미 종료되었습니다.")
else -> _dialogState.value = DialogState.Close
}
}.onFailure {
Timber.e(it)
Expand All @@ -325,4 +322,9 @@ class AttendanceViewModel @Inject constructor(
dialogErrorMessage = message
_dialogState.value = DialogState.Failure
}

companion object {
private const val FIRST_ATTENDANCE_TEXT = "1차 출석"
private const val SECOND_ATTENDANCE_TEXT = "2차 출석"
}
}
Loading

0 comments on commit 943a34b

Please sign in to comment.