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

[AN-REFACTOR] 상성 화면 리팩토링 #38

Merged
merged 16 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
@@ -1,5 +1,6 @@
package poke.rogue.helper.data.datasource

import poke.rogue.helper.data.model.TypeInfo
import poke.rogue.helper.data.model.TypeMatchedResult
import poke.rogue.helper.local.DummyTypeData

Expand Down Expand Up @@ -35,4 +36,6 @@ class LocalTypeDataSource(private val typeData: DummyTypeData = DummyTypeData) {
listOf(typeData.allTypes.get(defendingTypeId)),
)
}

fun allTypes(): List<TypeInfo> = typeData.allTypes
murjune marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package poke.rogue.helper.data.repository

import poke.rogue.helper.data.datasource.LocalTypeDataSource
import poke.rogue.helper.data.model.MatchedResult
import poke.rogue.helper.data.model.TypeInfo
murjune marked this conversation as resolved.
Show resolved Hide resolved
import poke.rogue.helper.data.model.TypeMatchedResult

class TypeRepository(private val localTypeDataSource: LocalTypeDataSource) {
murjune marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -23,4 +24,8 @@ class TypeRepository(private val localTypeDataSource: LocalTypeDataSource) {
localTypeDataSource.findMatchedTypeResult(myTypeId, it)
}.filter { it.matchedResult != MatchedResult.NORMAL }
}

fun allTypes(): List<TypeInfo> {
return localTypeDataSource.allTypes()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import poke.rogue.helper.R
import poke.rogue.helper.databinding.ActivityTypeBinding
import poke.rogue.helper.presentation.base.BindingActivity
import poke.rogue.helper.presentation.type.model.SelectorType
import poke.rogue.helper.presentation.type.model.TypeSelectionUiState
import poke.rogue.helper.presentation.type.typeselection.TypeSelectionBottomSheetFragment
import poke.rogue.helper.presentation.util.context.colorOf
import poke.rogue.helper.presentation.type.result.TypeResultAdapter
import poke.rogue.helper.presentation.type.selection.TypeSelectionBottomSheetFragment
import poke.rogue.helper.presentation.util.context.drawableOf
import poke.rogue.helper.presentation.util.context.stringOf
import poke.rogue.helper.presentation.util.repeatOnStarted
import poke.rogue.helper.presentation.util.view.setVisible

class TypeActivity : BindingActivity<ActivityTypeBinding>(R.layout.activity_type) {
private val viewModel: TypeViewModel by viewModels {
Expand Down Expand Up @@ -46,8 +48,7 @@ class TypeActivity : BindingActivity<ActivityTypeBinding>(R.layout.activity_type
}

private fun navigateToPokeRogue() {
val intent =
Intent(Intent.ACTION_VIEW, Uri.parse(stringOf(R.string.home_pokerogue_url)))
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(stringOf(R.string.home_pokerogue_url)))
startActivity(intent)
}

Expand All @@ -56,86 +57,61 @@ class TypeActivity : BindingActivity<ActivityTypeBinding>(R.layout.activity_type
setSupportActionBar(toolbarHome.toolbar)
toolbarHome.toolbar.overflowIcon = drawableOf(R.drawable.ic_menu)
supportActionBar?.setDisplayShowTitleEnabled(false)

typeHandler = viewModel
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initViews()
initAdapter()
initListener()
initObserver()
binding.typeHandler = viewModel
}

private fun initAdapter() {
binding.rvTypeResult.adapter = typeResultAdapter
}

private fun initListener() {
binding.vwTypeMyTypeContainer.setOnClickListener {
displayBottomSheet(SelectorType.MINE)
}

binding.vwTypeOpponentTypeContainer1.setOnClickListener {
displayBottomSheet(SelectorType.OPPONENT1)
}

binding.vwTypeOpponentTypeContainer2.setOnClickListener {
displayBottomSheet(SelectorType.OPPONENT2)
}
binding.btnRefresh.setOnClickListener {
viewModel.refresh()
}
}

private fun initObserver() {
viewModel.myType.observe(this) { uiState ->
when (uiState) {
is TypeSelectionUiState.Selected -> {
val data = uiState.selectedType
binding.vwTypeMyTypeContent.visibility = View.VISIBLE
binding.vwTypeMyTypeContent.setContentColor(this.colorOf(data.typeColor))
binding.ivTypeMyTypeContent.setImageResource(uiState.selectedType.typeIconResId)
}

is TypeSelectionUiState.Idle -> {
binding.vwTypeMyTypeContent.visibility = View.GONE
repeatOnStarted {
Copy link
Contributor

Choose a reason for hiding this comment

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

repeatOnStarted 단위로 함수로 뺄 수도 있을 것 같아요.

viewModel.typeEvent.collect {
if (it is TypeEvent.ShowSelection) {
displayBottomSheet(it.selectorType)
Copy link
Contributor

Choose a reason for hiding this comment

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

해당 함수의 네이밍을 showTypeSelection 로 바꾸는건 어떨까요?

display, show.. 비슷한 네이밍인데 통일성을 맞춰주셨으면 좋겠어요 🙃

}
}
}

viewModel.opponentType1.observe(this) { uiState ->
when (uiState) {
is TypeSelectionUiState.Selected -> {
val data = uiState.selectedType
binding.vwTypeOpponentTypeContent1.visibility = View.VISIBLE
binding.vwTypeOpponentTypeContent1.setContentColor(this.colorOf(data.typeColor))
binding.ivTypeOpponentTypeContent1.setImageResource(uiState.selectedType.typeIconResId)
}

is TypeSelectionUiState.Idle -> {
binding.vwTypeOpponentTypeContent1.visibility = View.GONE
lifecycleScope.launch {
Copy link
Contributor

Choose a reason for hiding this comment

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

flow 사용하는 것으로 바꾸셨군요!! 👍👍👍👍👍
아까 이야기한 것처럼 LifecycleExtension 사용하는 것으로 바꾸는 것 리마인드 코멘트 달아놓겠습니다~

Copy link
Contributor

Choose a reason for hiding this comment

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

동의합니다 ㅎ ㅎ
repeatOnStarted 로 바꿔주세용

이유는 따로 공부해보는게 좋을 것 같습니다!

https://kotlinworld.com/228

viewModel.myType.collect { uiState ->
binding.parallelogramTypeMyTypeContent.setVisible(uiState is TypeSelectionUiState.Selected)
if (uiState is TypeSelectionUiState.Selected) {
binding.myType = uiState.selectedType
}
}
}

viewModel.opponentType2.observe(this) { uiState ->
when (uiState) {
is TypeSelectionUiState.Selected -> {
val data = uiState.selectedType
binding.vwTypeOpponentTypeContent2.visibility = View.VISIBLE
binding.vwTypeOpponentTypeContent2.setContentColor(this.colorOf(data.typeColor))
binding.ivTypeOpponentTypeContent2.setImageResource(uiState.selectedType.typeIconResId)
lifecycleScope.launch {
viewModel.opponentType1.collect { uiState ->
binding.parallelogramTypeOpponentTypeContent1.setVisible(uiState is TypeSelectionUiState.Selected)
if (uiState is TypeSelectionUiState.Selected) {
binding.opponent1Type = uiState.selectedType
}
}
}

is TypeSelectionUiState.Idle -> {
binding.vwTypeOpponentTypeContent2.visibility = View.GONE
lifecycleScope.launch {
viewModel.opponentType2.collect { uiState ->
binding.parallelogramTypeOpponentTypeContent2.setVisible(uiState is TypeSelectionUiState.Selected)
if (uiState is TypeSelectionUiState.Selected) {
binding.opponent2Type = uiState.selectedType
}
}
}

viewModel.type.observe(this) { matchedResult ->
typeResultAdapter.submitList(matchedResult)
lifecycleScope.launch {
viewModel.type.collect { matchedResult ->
typeResultAdapter.submitList(matchedResult)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package poke.rogue.helper.presentation.type

import poke.rogue.helper.presentation.type.model.SelectorType

sealed interface TypeEvent {
data class ShowSelection(val selectorType: SelectorType) : TypeEvent

data object HideSelection : TypeEvent
}
Copy link
Contributor

Choose a reason for hiding this comment

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

이벤트를 객체로 모아두신 점 👍👍

Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import poke.rogue.helper.presentation.type.model.SelectorType
import poke.rogue.helper.presentation.type.model.TypeUiModel

interface TypeHandler {
fun selectType(
fun showSelection(selectorType: SelectorType)
Copy link
Contributor

Choose a reason for hiding this comment

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

오프에서 얘기했던것처럼 startSelection 은 어떨까요?


fun applySelection(
Copy link
Contributor

Choose a reason for hiding this comment

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

저는 개인적으로 이 함수는 selectType 이 더 좋아보이네요.
뷰모델 코드를 볼 때 헷갈렸어요.
applyselection 둘 다 너무 일반적인 네이밍 같아서요.

Copy link
Contributor

Choose a reason for hiding this comment

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

동의합니다 :D

selectorType: SelectorType,
selectedType: TypeUiModel,
)

fun deleteMyType()

fun deleteOpponent1Type()
fun removeSelection(selectorType: SelectorType)
Copy link
Contributor

Choose a reason for hiding this comment

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

컨벤션 좋습니다 👍
인터페이스의 이름의 경우에는 Listener,Handler에 따라 추후 변경될 수도 있겠네요 !


fun deleteOpponent2Type()
fun removeAllSelections()
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package poke.rogue.helper.presentation.type.model
package poke.rogue.helper.presentation.type

Copy link
Contributor

Choose a reason for hiding this comment

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

원래 UiStatemodel 패키지에 들어있는 게 아닌가요?
이 부분은 제가 헷갈리네요

Copy link
Contributor

Choose a reason for hiding this comment

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

이것은 컨벤션으로 정해두면 좋을 듯 합니다!!

NowInAndroid 에서는 UiState 가 그리 크지 않으면 ViewModel 파일에 두는 것을 볼 수 있습니다.

https://github.com/android/nowinandroid/blob/main/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/InterestsViewModel.kt

조금 길면 따로 파일로 분리하는 것 같습니다.

https://github.com/android/nowinandroid/blob/main/feature/search/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/search/SearchResultUiState.kt


저는 개인적으로 ViewModel 아래에 두는 것을 선호해요
ViewModel 로직 작성하기 편하기 때문이에요 ㅎ ㅎ

import poke.rogue.helper.presentation.type.model.TypeUiModel

sealed interface TypeSelectionUiState {
data class Selected(val selectedType: TypeUiModel) : TypeSelectionUiState
Expand Down
Loading
Loading