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

[스터디 관리하기 뷰 시작 후] 스터디 관리하기 뷰 기능 구현 #140

Merged
merged 35 commits into from
Aug 2, 2023

Conversation

RightHennessy
Copy link
Collaborator

😋 작업한 내용

  • ViewPager 연결
  • 스터디의 선택 투두 RecyclerView 구현
  • 스터디의 멤버 RecyclerView 구현
  • 이전 회차, 다음 회차 버튼에 대한 로직 구현

🙏 PR Point

뷰페이저 어댑터의 리스트에 데이터를 넣는 과정이 회차별 정보를 각각 따로 서버 통신을 해야해서
이에 관한 로직은 서버 연결할 때 완성될 것 같습니다 ~

👍 관련 이슈

@RightHennessy RightHennessy changed the title An/feature/120 studymanagement inflate [스터디 관리하기 뷰 시작 후] 스터디 관리하기 뷰 기능 구현 Jul 30, 2023
@github-actions
Copy link

github-actions bot commented Jul 30, 2023

Test Results

13 tests   13 ✔️  3s ⏱️
  7 suites    0 💤
  7 files      0

Results for commit c9a9439.

♻️ This comment has been updated with latest results.

Copy link
Member

@inseonyun inseonyun left a comment

Choose a reason for hiding this comment

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

어떤 로직은 도메인에 있고 어떤 로직은 UI에 있고 관심사 분리가 조금 덜 된 거 같네용
매직 넘버가 너무 많아요!!!!
피드백 남겨드린거 참고해서 반영 부탁드립니다

Comment on lines +51 to +53
val studyId = intent.getLongExtra(KEY_STUDY_ID, KEY_ERROR)
val roundId = intent.getLongExtra(KEY_ROUND_ID, KEY_ERROR)
studyManagementViewModel.getStudyRounds(studyId, roundId)
Copy link
Member

Choose a reason for hiding this comment

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

KEY_ERROR 가 되었을 때는 어떤 플로우를 타게 되나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아직 이부분에 대한 코드가 없습니다..
서버 연결을 하면서 오류처리를 어떻게 할지 결정할 것 같습니다.


private fun setPageChangeButtonEnabled() {
binding.ivStudyManagementPreviousButton.isEnabled =
studyManagementViewModel.currentRound.value != 1
Copy link
Member

Choose a reason for hiding this comment

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

매직 넘버

Comment on lines 103 to 113
binding.ivStudyManagementPreviousButton.setOnClickListener {
val page = (binding.vpStudyManagement.currentItem - 1).coerceAtLeast(0)
binding.vpStudyManagement.setCurrentItem(page, true)
studyManagementViewModel.fetchRoundDetail(page)
}
binding.ivStudyManagementNextButton.setOnClickListener {
val page =
(binding.vpStudyManagement.currentItem + 1).coerceAtMost(studyManagementAdapter.itemCount - 1)
binding.vpStudyManagement.setCurrentItem(page, true)
studyManagementViewModel.fetchRoundDetail(page)
}
Copy link
Member

Choose a reason for hiding this comment

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

페이지 계산 로직이 뷰에 있어야하는게 맞을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

PageIndex에서 관리하도록 분리함슴

Copy link
Collaborator

Choose a reason for hiding this comment

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

22

Comment on lines 72 to 73
val studyDetails = studyRounds.value ?: throw IllegalStateException()
val currentStudy = studyRounds.value?.get(currentItemId) ?: throw IllegalStateException()
Copy link
Member

Choose a reason for hiding this comment

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

업데이트하지 못하면 터진다..?
무시무시한 앱이군요...
의도한 흐름인가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

무시무시하죠?

when (isNecessary) {
true -> {
updateNecessaryTodoCheck(studyDetails, todoId, isDone)
study = studyDetails.find { it.necessaryTodo.todoId == todoId }!!
Copy link
Member

Choose a reason for hiding this comment

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

!!
해결할 방법이 없을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

산군코드라 생략하겠습니다.

궁금한점이 가짜 study를 생성해서 넣어주는게 더 좋다고 생각하나요?

Copy link
Member

Choose a reason for hiding this comment

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

아뇨 그냥 그 뷰 안 띄우고, 토스트로 안내 해주는 것이 전 더 좋다고 봅니다

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

스터디 하면서 먼말인지 알아들었습니다

override fun onBindViewHolder(holder: StudyOptionalTodoViewHolder, position: Int) {
when (getItemViewType(position)) {
1 -> (holder as StudyManagementOptionalTodoAddViewHolder).bind(getItem(position))
else -> (holder as StudyManagementOptionalTodoViewHolder).bind(getItem(position))
Copy link
Member

Choose a reason for hiding this comment

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

분기처리 else에서 뷰홀더 연결보다는 1 -> StudyManagementOptionalAdd...ViewHolder 처럼
2 -> StudyManagementOptionalViewHolder 이렇게 처리하고 else에서는 예외를 발생하는 것이 명시적이고 좋을 거 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OptionalTodoViewType에서 예외처리 했습니다.

Comment on lines 13 to 14
override fun bind(optionalTodoUiModel: OptionalTodoUiModel) {
}
Copy link
Member

Choose a reason for hiding this comment

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

추후에 쓰일 함수인가여?

아니라면 상위 클래스에 bind 함수를 굳이 둬서 하위 클래스에서 이러한 불필요한 함수 구현부를 계속 두게 돼서 불편할 거 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

제거하였습니다

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

image

val profileImageUrl: String,
val isDone: Boolean,
) {
fun progressPercentage(): Int = if (isDone) 100 else 0
Copy link
Member

Choose a reason for hiding this comment

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

ui model에 있어야할 로직인가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

커스텀 뷰의 경우 프로그레스 바의 기본 색이 필수투두를 완료한 색상으로 지정되어 있습니다.
또한 프로그레스가 0이라면 필수투두를 미완료한 색상으로 지정되어있습니다.
다시 말해 티어를 지정해주지 않으면 필수투두를 완료 했냐 안했냐를 표현해줄 수 있습니다.
때문에 isDone으로 투두를 완료했으면 progress가 100 미완료라면 0으로 표현해주는 겁니다.
뷰의 관심사지만 액티비티 또는 xml에 위치해 있는거도 자연스럽지 않다 생각해서 그외에 가장 어울리는 파일에 작성한 것입니다.
액티비티에 따로 로직을 나누고 적용시킨다면 databinding expression을 사용하는 의미가 약간 퇴색되는거 같습니다.
저는 일단 그렇게 생각하는데 혹시 다른 의견이 있으신가요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

뷰 로직이라고 생각된다면, uiModel에 있어도 될 것 같습니다!
근데 왜 Activity에서 뷰로직을 작성하면, dataBinding의 의미가 퇴색된다고 생각했나요?

  1. 뷰 로직이다. 해당 퍼센테이지의 수치가 필수투두 완료 =10000으로 바뀐다면, 뷰모델까지 바뀌는가?
  • UiModel, BindingAdapter, Activity에 위치해도 될 것 같다.
  1. 해당 UiModel이 뷰에 의존하고 있는가? 뷰라고 생각하는가?
  • 해당 UiModel을 혹시 뷰모델에서 생성하고 있는가? 그럼 뷰모델은 뷰를 참조하고 있는가?

@@ -36,7 +44,7 @@
android:textAppearance="@style/text_r12"
android:textColor="@color/white"
app:drawableStartCompat="@drawable/ic_edit_12"
app:isVisible="@{isMaster}"
app:isVisible="@{role.Companion.isMaster(studyManagement.role)}"
Copy link
Member

Choose a reason for hiding this comment

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

오,,신기

Copy link
Collaborator

Choose a reason for hiding this comment

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

뷰에 도메인 임포트.. 어떻게 생각하시나요?


<variable
name="onClickMember"
type="com.created.team201.presentation.studyManagement.StudyMemberClickListener" />
Copy link
Member

Choose a reason for hiding this comment

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

그냥 갑자기 든 생각인데, xml에서 이렇게 개발자가 만든 listener라는 함수만을 받도록 만드는 것과
kotlin.jvm.functions... 을 받는 것과 어떤게 더 나을까욤
저는 이왕 추상화하는 거 후자가 더 나을 거 같단 생각이 드네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

저는 생각했을 때, 이미 onClickMember 자체는 추상화된거잖아요?
근데 그 특정 추상화 중에 어떤 것을 선택하는지 정도는 오히려 명시해주는 것이
어떤 기능을 사용하고 있는지 읽기 쉽다고 생각이 들었습니다.
특히나 xml은 코드를 왔다갔다 해야하는 번거로움이 있기 때문에 더 그렇게 느껴지네용

Copy link
Member

Choose a reason for hiding this comment

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

흐음음음

@inseonyun
Copy link
Member

  • menu 파일에 studyManagement 메뉴 파일 언제 추가 된건지 모르겠는데 네이밍 확인 부탁드립니당 study_list라고 되어있길래

Copy link
Collaborator

@s9hn s9hn left a comment

Choose a reason for hiding this comment

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

졸린데 남기다보니 16개나 되네요... 고생하셨습니다!! 늦어서 미안해용!

Comment on lines 103 to 113
binding.ivStudyManagementPreviousButton.setOnClickListener {
val page = (binding.vpStudyManagement.currentItem - 1).coerceAtLeast(0)
binding.vpStudyManagement.setCurrentItem(page, true)
studyManagementViewModel.fetchRoundDetail(page)
}
binding.ivStudyManagementNextButton.setOnClickListener {
val page =
(binding.vpStudyManagement.currentItem + 1).coerceAtMost(studyManagementAdapter.itemCount - 1)
binding.vpStudyManagement.setCurrentItem(page, true)
studyManagementViewModel.fetchRoundDetail(page)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

22

R.string.study_management_app_bar_title_is_study_participant,
R.string.study_management_end_button_is_study_participant,
)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

enum class StudyManagementState(@StringRes val title: Int, @StringRes val buttonText: Int) {
 
MASTER(R.string.study_management_app_bar_title_is_study_master,
R.string.study_management_end_button_is_study_master,),
MEMBER(R.string.study_management_app_bar_title_is_study_participant,
R.string.study_management_end_button_is_study_participant,)
;
}

sealed Class와 오브젝트를 사용한 이유가 궁금합니다(진짜모름)

optionalTodos = studyDetailUiModel.optionalTodos.map {
it.takeUnless { it.todo.todoId == id }
?: it.copy(it.todo.copy(isDone = isDone))
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

뭐죠 이 혼란의 코드는!?!?!?!!?!?!? ㅎ내꺼군

Comment on lines 23 to 27
if (item.isDone) {
binding.root.context.getString(R.string.item_study_management_todo_done)
} else {
binding.root.context.getString(R.string.item_study_management_todo_undone)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

dataBinding과 viewBinding을 혼용하신 연유가 무엇인지 여쭈어 봐도 되겠습니까를 질문해도 괜찮겠습니까?


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StudyOptionalTodoViewHolder {
return when (viewType) {
1 -> StudyManagementOptionalTodoAddViewHolder.from(parent, studyManagementClickListener)
Copy link
Collaborator

Choose a reason for hiding this comment

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

블랙 맘바

val profileImageUrl: String,
val isDone: Boolean,
) {
fun progressPercentage(): Int = if (isDone) 100 else 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

뷰 로직이라고 생각된다면, uiModel에 있어도 될 것 같습니다!
근데 왜 Activity에서 뷰로직을 작성하면, dataBinding의 의미가 퇴색된다고 생각했나요?

  1. 뷰 로직이다. 해당 퍼센테이지의 수치가 필수투두 완료 =10000으로 바뀐다면, 뷰모델까지 바뀌는가?
  • UiModel, BindingAdapter, Activity에 위치해도 될 것 같다.
  1. 해당 UiModel이 뷰에 의존하고 있는가? 뷰라고 생각하는가?
  • 해당 UiModel을 혹시 뷰모델에서 생성하고 있는가? 그럼 뷰모델은 뷰를 참조하고 있는가?

@@ -36,7 +44,7 @@
android:textAppearance="@style/text_r12"
android:textColor="@color/white"
app:drawableStartCompat="@drawable/ic_edit_12"
app:isVisible="@{isMaster}"
app:isVisible="@{role.Companion.isMaster(studyManagement.role)}"
Copy link
Collaborator

Choose a reason for hiding this comment

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

뷰에 도메인 임포트.. 어떻게 생각하시나요?

<TextView
android:id="@+id/tv_item_study_management_optional_todo_add_button"
android:layout_width="60dp"
android:layout_height="40dp"
Copy link
Collaborator

Choose a reason for hiding this comment

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

고정dp 최선인가요!?

// 서버 통신으로 round 정보 가져옴
}

fun updateCurrentPage(pageIndex: Int) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Round라는 도메인의 책임으로 보긴 힘들까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

round와 page의 개념이 모두 있는데, 이 부분은 Page의 개념이어서 기존에 만들어두었던 PageIndex 도메인을 사용하도록 코드를 변경하였습니다.

@RightHennessy RightHennessy requested a review from s9hn August 1, 2023 08:23
Copy link
Collaborator

@s9hn s9hn left a comment

Choose a reason for hiding this comment

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

LGTM~

@RightHennessy RightHennessy merged commit f695277 into develop Aug 2, 2023
@RightHennessy RightHennessy deleted the AN/feature/120-studymanagement-inflate branch August 2, 2023 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android💚 안드 feat 기능 추가 ßändäl🌗 반달 ringring🤙 링링
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[스터디 관리하기 뷰 시작 후] 서버 연결을 제외한 기능 구현
4 participants