From 5707f7c36f27463727bd4e8f70428480b977592f Mon Sep 17 00:00:00 2001 From: JUNWON LEE Date: Mon, 19 Aug 2024 15:21:00 +0900 Subject: [PATCH] =?UTF-8?q?[0.2.0.alpha/AN=5FFEAT]=20=ED=8F=AC=EC=BC=93?= =?UTF-8?q?=EB=AA=AC=20=EC=83=81=EC=84=B8=EC=97=90=EC=84=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=ED=99=94=EB=A9=B4,=20id(Long=20->=20String)=20(#24?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 포켓몬 상세 탭 타이틀을 string-array 로 한다 * chore: strings 리소스에 dex 를 pokemon_list 와 detail 로 * feat: 포켓몬 상세에서 필요한 데이터 정의 * feat: 포켓몬 상세에서 필요한 데이터 바이옴 추가 * feat: 데이터 레이어 Biome 추가 * feat: 포켓몬 상세 정보에서 바이옴 정보 item UI * feat: 포켓몬 상세 정보에서 바이옴 뷰 홀더 * feat: 포켓몬 상세 정보 프래그먼트 ui xml * feat: 포켓몬 상세 정보에서 바이옴 어댑터 * feat: 포켓몬 상세 뷰모델에 바이옴 상세로 네비게이션하는 이벤트 추가 * feat: 바이옴 상세 액티비티 동반 객체에 intent 추가 * feat(PokemonInformationFragment): 포켓몬 상세 액티비티 뷰모델, 어댑터 연결 * feat(PokemonDetailActivity): 포켓몬 상세에서 바이옴 상세로 네비게이션 * fix(Biome): 바이옴 이미지 url 변경 * feat(PokemonInformationFragmen): 바이옴 라사이클러뷰에 데코레이션 * feat: 바이옴 타이틀과 바이옴 아이템 사이 구분선 추가 * feat(NewPokemon,NewPokemonUiModel): id 를 Long -> String * feat presentation layer 에 NewPokeMonUiModel 적용 * feat(DexRepository): 포켓몬 리스트 리턴을 NewPokemon 으로 * feat(DexDataSource): 포켓몬 리스트 리턴을 NewPokemon 으로 * feat(NewPokemonDetail, NewAbility): response 에서 데이터로 * feat(DexRepository,RemoteDexDataSource.kt) 에서 데이터를 NewPokemonDetail 로 * feat(AbilityDetail): NewPokemon 리스트로 * refactor: 포켓몬 상세 액티비티 뷰모델에서 pokemonId 는 String * feat: PokemonSkill 의 클래스 변경됨 * feat: 포켓몬 특성 id 를 Long -> String 으로 * refactor: Ability 의 id 를 Long -> String - issue: 포켓몬 상세에서 특성 상세로 이동 시 예외 * refactor: 포켓몬 상세에서 특성 상세로 이동하도록 한다 - 이전 커밋(80872b6f) 이슈 해결 * chore: ktlint * refactor: NewPokemon -> Pokemon * refactor: NewSKill -> PokemonSkill * refactor: NewPokemonDetail -> PokemonDetail * chore: 네이밍 NewPokemonSKills -> PokemonDetailSkills * refactor: NewAbility -> PokemonDetailAbility * refactor: id: Long 을 모두 id: String 로 변경 * fix(data/unitTest): id 값을 String 으로 * fix: 특성 상세 프래그먼트에서 bundle 이 null 일 때 처리 * fix: Pokemon 클래스의 더미데이터 복구 * chore: 포켓몬 상세 특성 ui model 네이밍 변경 * feat: 기술머신으로 배우는 PokemonSkill 리스트 추가 * test: data 레이어의 모델의 id String 으로 * chore: ktlint * refactor: getStringArrayOf 를 확장 유틸함수로 --------- Co-authored-by: sh1mj1 <7wlgns@gmail.com> --- .../presentation/ability/AbilityActivity.kt | 9 +- .../presentation/ability/AbilityFragment.kt | 2 +- .../ability/AbilityUiEventHandler.kt | 2 +- .../presentation/ability/AbilityViewModel.kt | 6 +- .../ability/detail/AbilityDetailFragment.kt | 11 +- .../detail/AbilityDetailUiEventHandler.kt | 2 +- .../ability/detail/AbilityDetailViewModel.kt | 10 +- .../ability/model/AbilityDetailUiModel.kt | 2 +- .../ability/model/AbilityUiModel.kt | 54 ++--- .../presentation/biome/BiomeUiEventHandler.kt | 2 +- .../presentation/biome/BiomeViewModel.kt | 6 +- .../biome/detail/BiomeDetailActivity.kt | 9 + .../biome/model/BiomeDetailUiModel.kt | 9 - .../presentation/biome/model/BiomeUiModel.kt | 18 +- .../dex/PokemonListNavigateHandler.kt | 2 +- .../presentation/dex/PokemonListViewModel.kt | 9 +- .../dex/detail/PokemonDetailActivity.kt | 27 ++- .../detail/PokemonDetailNavigateHandler.kt | 4 +- .../dex/detail/PokemonDetailUiState.kt | 17 +- .../dex/detail/PokemonDetailViewModel.kt | 19 +- .../information/PokemonDetailBiomeAdapter.kt | 42 ++++ .../PokemonDetailBiomeViewHolder.kt | 18 ++ .../information/PokemonInformationFragment.kt | 40 +++ .../skill/PokemonDetailSkillFragment.kt | 21 +- .../dex/detail/stat/PokemonStatFragment.kt | 12 +- .../dex/model/AbilityTitleUiModel.kt | 2 +- .../dex/model/PokemonDetailAbilityUiModel.kt | 20 ++ .../dex/model/PokemonSkillUiModel.kt | 4 +- .../presentation/dex/model/PokemonUiModel.kt | 7 +- .../dex/model/SkillCategoryUiModel.kt | 2 +- .../presentation/type/model/TypeUiModel.kt | 2 + .../util/context/ContextExtension.kt | 5 + .../main/res/layout-land/activity_home.xml | 2 +- .../app/src/main/res/layout/activity_home.xml | 2 +- .../res/layout/activity_pokemon_detail.xml | 2 +- .../main/res/layout/activity_pokemon_list.xml | 8 +- .../layout/fragment_pokemon_information.xml | 126 +++++++++- .../item_pokemon_detail_information_biome.xml | 49 ++++ android/app/src/main/res/values/strings.xml | 37 +-- .../ability/AbilityViewModelTest.kt | 8 +- .../detail/AbilityDetailViewModelTest.kt | 9 +- .../dex/PokemonListViewModelTest.kt | 4 +- .../dex/detail/PokemonDetailViewModelTest.kt | 154 +----------- .../datasource/RemoteAbilityDataSource.kt | 5 +- .../data/datasource/RemoteDexDataSource.kt | 7 +- .../poke/rogue/helper/data/model/Ability.kt | 5 +- .../poke/rogue/helper/data/model/Biome.kt | 28 +++ .../poke/rogue/helper/data/model/Evolution.kt | 9 + .../poke/rogue/helper/data/model/Pokemon.kt | 6 +- .../helper/data/model/PokemonCategory.kt | 18 ++ .../rogue/helper/data/model/PokemonDetail.kt | 42 ++-- .../helper/data/model/PokemonDetailAbility.kt | 20 ++ .../helper/data/model/PokemonDetailSkills.kt | 7 + .../rogue/helper/data/model/PokemonSkill.kt | 229 ++++++++++++++++-- .../rogue/helper/data/model/SkillCategory.kt | 8 +- .../data/repository/AbilityRepository.kt | 2 +- .../repository/DefaultAbilityRepository.kt | 2 +- .../data/repository/DefaultDexRepository.kt | 4 +- .../helper/data/repository/DexRepository.kt | 2 +- .../datasource/RemoteDexDataSourceTest.kt | 2 +- .../helper/data/model/PokemonMapperTest.kt | 8 +- .../model/fixture/PokemonResponseFixture.kt | 6 +- .../data/repository/FakeAbilityRepository.kt | 60 ++--- .../data/repository/FakeDexRepository.kt | 49 ++-- 64 files changed, 903 insertions(+), 412 deletions(-) create mode 100644 android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeAdapter.kt create mode 100644 android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeViewHolder.kt create mode 100644 android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonDetailAbilityUiModel.kt create mode 100644 android/app/src/main/res/layout/item_pokemon_detail_information_biome.xml create mode 100644 android/data/src/main/java/poke/rogue/helper/data/model/Biome.kt create mode 100644 android/data/src/main/java/poke/rogue/helper/data/model/Evolution.kt create mode 100644 android/data/src/main/java/poke/rogue/helper/data/model/PokemonCategory.kt create mode 100644 android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailAbility.kt create mode 100644 android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailSkills.kt diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityActivity.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityActivity.kt index 48aa1d83..e56b14b4 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityActivity.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityActivity.kt @@ -14,8 +14,8 @@ class AbilityActivity : BindingActivity(R.layout.activit override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState == null) { - val abilityId = intent.getLongExtra(ABILITY_ID, INVALID_ABILITY) - if (abilityId == INVALID_ABILITY) { + val abilityId = intent.getStringExtra(ABILITY_ID) ?: "" + if (abilityId.isBlank()) { navigateToAbilityList() return } @@ -30,7 +30,7 @@ class AbilityActivity : BindingActivity(R.layout.activit } } - private fun navigateToAbilityDetail(abilityId: Long) { + private fun navigateToAbilityDetail(abilityId: String) { supportFragmentManager.commit { replace( containerViewId = R.id.fragment_container_ability, @@ -41,11 +41,10 @@ class AbilityActivity : BindingActivity(R.layout.activit companion object { private const val ABILITY_ID = "abilityId" - private const val INVALID_ABILITY = -1L fun intent( context: Context, - abilityId: Long = INVALID_ABILITY, + abilityId: String, ): Intent = Intent(context, AbilityActivity::class.java).apply { putExtra(ABILITY_ID, abilityId) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityFragment.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityFragment.kt index bbc844e6..0916d9b5 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityFragment.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityFragment.kt @@ -31,7 +31,7 @@ class AbilityFragment : ErrorHandleFragment(R.layout.fra private val adapter: AbilityAdapter by lazy { AbilityAdapter(viewModel) } - override val toolbar: Toolbar? + override val toolbar: Toolbar get() = binding.toolbarAbility override fun onViewCreated( diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityUiEventHandler.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityUiEventHandler.kt index b8df0273..83a8dec5 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityUiEventHandler.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityUiEventHandler.kt @@ -1,5 +1,5 @@ package poke.rogue.helper.presentation.ability interface AbilityUiEventHandler { - fun navigateToDetail(abilityId: Long) + fun navigateToDetail(abilityId: String) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityViewModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityViewModel.kt index a35e44e0..007899e9 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityViewModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/AbilityViewModel.kt @@ -32,8 +32,8 @@ class AbilityViewModel( ) : ErrorHandleViewModel(logger), AbilityQueryHandler, AbilityUiEventHandler { - private val _navigationToDetailEvent = MutableSharedFlow() - val navigationToDetailEvent: SharedFlow = _navigationToDetailEvent.asSharedFlow() + private val _navigationToDetailEvent = MutableSharedFlow() + val navigationToDetailEvent: SharedFlow = _navigationToDetailEvent.asSharedFlow() private val searchQuery = MutableStateFlow("") @@ -64,7 +64,7 @@ class AbilityViewModel( private suspend fun queriedAbilities(query: String): List = abilityRepository.abilities(query).map { it.toUi() } - override fun navigateToDetail(abilityId: Long) { + override fun navigateToDetail(abilityId: String) { viewModelScope.launch { _navigationToDetailEvent.emit(abilityId) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailFragment.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailFragment.kt index 9c37bdf3..33c66ea2 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailFragment.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailFragment.kt @@ -34,8 +34,8 @@ class AbilityDetailFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val id = arguments?.getLong(ABILITY_ID) ?: INVALID_ABILITY_ID - viewModel.updateAbilityDetail(id) + val abilityId = arguments?.getString(ABILITY_ID) ?: "" + viewModel.updateAbilityDetail(abilityId) } override fun onViewCreated( @@ -106,14 +106,11 @@ class AbilityDetailFragment : companion object { private const val ABILITY_ID = "abilityId" - private const val CONTAINER_ID = "containerId" - private const val INVALID_ABILITY_ID = -1L - private const val INVALID_CONTAINER_ID = -1 private val TAG = AbilityDetailFragment::class.java.simpleName - fun bundleOf(abilityId: Long) = + fun bundleOf(abilityId: String) = Bundle().apply { - putLong(ABILITY_ID, abilityId) + putString(ABILITY_ID, abilityId) } } } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailUiEventHandler.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailUiEventHandler.kt index a290350f..0b787531 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailUiEventHandler.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailUiEventHandler.kt @@ -1,7 +1,7 @@ package poke.rogue.helper.presentation.ability.detail interface AbilityDetailUiEventHandler { - fun navigateToPokemonDetail(pokemonId: Long) + fun navigateToPokemonDetail(pokemonId: String) fun navigateToHome() } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModel.kt index 1213d0f6..85f004d8 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModel.kt @@ -28,8 +28,8 @@ class AbilityDetailViewModel( MutableStateFlow>(AbilityDetailUiState.Loading) val abilityDetail = _abilityDetail.asStateFlow() - private val _navigationToPokemonDetailEvent = MutableSharedFlow() - val navigationToPokemonDetailEvent: SharedFlow = + private val _navigationToPokemonDetailEvent = MutableSharedFlow() + val navigationToPokemonDetailEvent: SharedFlow = _navigationToPokemonDetailEvent.asSharedFlow() private val _navigateToHomeEvent = MutableSharedFlow() @@ -42,7 +42,7 @@ class AbilityDetailViewModel( abilityDetail.map { it is AbilityDetailUiState.Success && it.data.pokemons.isEmpty() } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), false) - override fun navigateToPokemonDetail(pokemonId: Long) { + override fun navigateToPokemonDetail(pokemonId: String) { viewModelScope.launch { _navigationToPokemonDetailEvent.emit(pokemonId) } @@ -54,8 +54,8 @@ class AbilityDetailViewModel( } } - fun updateAbilityDetail(abilityId: Long) { - if (abilityId == -1L) { + fun updateAbilityDetail(abilityId: String) { + if (abilityId.isBlank()) { _errorEvent.tryEmit(Unit) return } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityDetailUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityDetailUiModel.kt index 1772eb05..dffc7a54 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityDetailUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityDetailUiModel.kt @@ -26,5 +26,5 @@ fun AbilityDetail.toUi(): AbilityDetailUiModel = AbilityDetailUiModel( title = this.title, description = this.description, - pokemons = this.pokemons.map { it.toUi() }, + pokemons = pokemons.toUi(), ) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityUiModel.kt index 86acd466..2a1ec3d6 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/ability/model/AbilityUiModel.kt @@ -3,7 +3,7 @@ package poke.rogue.helper.presentation.ability.model import poke.rogue.helper.data.model.Ability data class AbilityUiModel( - val id: Long, + val id: String, val title: String, val description: String, val shortening: Boolean = true, @@ -14,36 +14,36 @@ data class AbilityUiModel( val DUMMY = AbilityUiModel( - id = -1, + id = "-1", title = DUMMY_ABILITY_NAME, description = DUMMY_ABILITY_DESCRIPTION, ) val dummys: List = listOf( - AbilityUiModel(1, "악취", "악취를 풍겨서 공격했을 때 상대가 풀죽을 때가 있다."), - AbilityUiModel(2, "잔비", "등장했을 때 날씨를 비로 만든다."), - AbilityUiModel(3, "가속", "매 턴 스피드가 올라간다."), - AbilityUiModel(4, "전투무장", "단단한 껍질에 보호받아 상대의 공격이 급소에 맞지 않는다."), - AbilityUiModel(5, "옹골참", "상대 기술을 받아도 일격으로 쓰러지지 않는다. 일격필살 기술도 효과 없다."), - AbilityUiModel(6, "유연", "주변을 습하게 함으로써 자폭 등 폭발하는 기술을 아무도 못 쓰게 한다."), - AbilityUiModel(7, "모래숨기", "모래바람일 때 회피율이 올라간다."), - AbilityUiModel(8, "정전기", "정전기를 몸에 둘러 접촉한 상대를 마비시킬 때가 있다."), - AbilityUiModel(9, "축전 (P)", "전기타입의 기술을 받으면 데미지를 받지 않고 회복한다."), - AbilityUiModel(10, "저수 (P)", "물타입의 기술을 받으면 데미지를 받지 않고 회복한다."), - AbilityUiModel(11, "둔감", "둔감해서 헤롱헤롱이나 도발 상태가 되지 않는다."), - AbilityUiModel(12, "날씨부정", "모든 날씨의 영향이 없어진다."), - AbilityUiModel(13, "복안", "복안을 가지고 있어 기술의 명중률이 올라간다."), - AbilityUiModel(14, "불면", "잠들지 못하는 체질이라 잠듦 상태가 되지 않는다."), - AbilityUiModel(15, "변색", "상대에게 받은 기술의 타입으로 자신의 타입이 변화한다."), - AbilityUiModel(16, "면역", "체내에 면역을 가지고 있어 독 상태가 되지 않는다."), - AbilityUiModel(17, "타오르는불꽃", "불꽃타입의 기술을 받으면 불꽃을 받아서 자신이 사용하는 불꽃타입의 기술이 강해진다."), - AbilityUiModel(18, "인분 (P)", "인분에 보호받아 기술의 추가 효과를 받지 않게 된다."), - AbilityUiModel(19, "마이페이스", "마이페이스라서 혼란 상태가 되지 않는다."), - AbilityUiModel(20, "홉반", "흡반으로 지면에 달라붙어 포켓몬을 교체시키는 기술이나 도구의 효과를 발휘하지 못하게 한다."), - AbilityUiModel(21, "위협", "등장했을 때 위협해서 상대를 위축시켜 상대의 공격을 떨어뜨린다."), - AbilityUiModel(22, "그림자밝기", "상대의 그림자를 밟아 도망치거나 교체할 수 없게 한다."), - AbilityUiModel(23, "까칠한피부", "공격을 받았을 때 자신에게 접촉한 상대를 까칠까칠한 피부로 상처를 입힌다."), - AbilityUiModel(24, "불가사의부적", "효과가 굉장한 기술만 맞는 불가사의한 힘."), + AbilityUiModel("1", "악취", "악취를 풍겨서 공격했을 때 상대가 풀죽을 때가 있다."), + AbilityUiModel("2", "잔비", "등장했을 때 날씨를 비로 만든다."), + AbilityUiModel("3", "가속", "매 턴 스피드가 올라간다."), + AbilityUiModel("4", "전투무장", "단단한 껍질에 보호받아 상대의 공격이 급소에 맞지 않는다."), + AbilityUiModel("5", "옹골참", "상대 기술을 받아도 일격으로 쓰러지지 않는다. 일격필살 기술도 효과 없다."), + AbilityUiModel("6", "유연", "주변을 습하게 함으로써 자폭 등 폭발하는 기술을 아무도 못 쓰게 한다."), + AbilityUiModel("7", "모래숨기", "모래바람일 때 회피율이 올라간다."), + AbilityUiModel("8", "정전기", "정전기를 몸에 둘러 접촉한 상대를 마비시킬 때가 있다."), + AbilityUiModel("9", "축전 (P)", "전기타입의 기술을 받으면 데미지를 받지 않고 회복한다."), + AbilityUiModel("10", "저수 (P)", "물타입의 기술을 받으면 데미지를 받지 않고 회복한다."), + AbilityUiModel("11", "둔감", "둔감해서 헤롱헤롱이나 도발 상태가 되지 않는다."), + AbilityUiModel("12", "날씨부정", "모든 날씨의 영향이 없어진다."), + AbilityUiModel("13", "복안", "복안을 가지고 있어 기술의 명중률이 올라간다."), + AbilityUiModel("14", "불면", "잠들지 못하는 체질이라 잠듦 상태가 되지 않는다."), + AbilityUiModel("15", "변색", "상대에게 받은 기술의 타입으로 자신의 타입이 변화한다."), + AbilityUiModel("16", "면역", "체내에 면역을 가지고 있어 독 상태가 되지 않는다."), + AbilityUiModel("17", "타오르는불꽃", "불꽃타입의 기술을 받으면 불꽃을 받아서 자신이 사용하는 불꽃타입의 기술이 강해진다."), + AbilityUiModel("18", "인분 (P)", "인분에 보호받아 기술의 추가 효과를 받지 않게 된다."), + AbilityUiModel("19", "마이페이스", "마이페이스라서 혼란 상태가 되지 않는다."), + AbilityUiModel("20", "홉반", "흡반으로 지면에 달라붙어 포켓몬을 교체시키는 기술이나 도구의 효과를 발휘하지 못하게 한다."), + AbilityUiModel("21", "위협", "등장했을 때 위협해서 상대를 위축시켜 상대의 공격을 떨어뜨린다."), + AbilityUiModel("22", "그림자밝기", "상대의 그림자를 밟아 도망치거나 교체할 수 없게 한다."), + AbilityUiModel("23", "까칠한피부", "공격을 받았을 때 자신에게 접촉한 상대를 까칠까칠한 피부로 상처를 입힌다."), + AbilityUiModel("24", "불가사의부적", "효과가 굉장한 기술만 맞는 불가사의한 힘."), ) } } @@ -57,7 +57,7 @@ fun Ability.toUi(): AbilityUiModel = fun AbilityDetailUiModel.toUi(): AbilityUiModel = AbilityUiModel( - id = 0, + id = "0", title = title, description = description, shortening = false, diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeUiEventHandler.kt b/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeUiEventHandler.kt index 901f3a08..40cf57b9 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeUiEventHandler.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeUiEventHandler.kt @@ -1,5 +1,5 @@ package poke.rogue.helper.presentation.biome interface BiomeUiEventHandler { - fun navigateToDetail(biomeId: Long) + fun navigateToDetail(biomeId: String) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeViewModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeViewModel.kt index f08ba9f2..9e65d4a3 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeViewModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/biome/BiomeViewModel.kt @@ -12,10 +12,10 @@ import poke.rogue.helper.presentation.base.error.ErrorHandleViewModel class BiomeViewModel(logger: AnalyticsLogger = analyticsLogger()) : ErrorHandleViewModel(logger), BiomeUiEventHandler { - private val _navigationToDetailEvent = MutableSharedFlow() - val navigationToDetailEvent: SharedFlow = _navigationToDetailEvent.asSharedFlow() + private val _navigationToDetailEvent = MutableSharedFlow() + val navigationToDetailEvent: SharedFlow = _navigationToDetailEvent.asSharedFlow() - override fun navigateToDetail(biomeId: Long) { + override fun navigateToDetail(biomeId: String) { viewModelScope.launch { _navigationToDetailEvent.emit(biomeId) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/biome/detail/BiomeDetailActivity.kt b/android/app/src/main/java/poke/rogue/helper/presentation/biome/detail/BiomeDetailActivity.kt index 7b1869e5..c7d1b819 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/biome/detail/BiomeDetailActivity.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/biome/detail/BiomeDetailActivity.kt @@ -1,5 +1,7 @@ package poke.rogue.helper.presentation.biome.detail +import android.content.Context +import android.content.Intent import android.os.Bundle import androidx.appcompat.widget.Toolbar import com.google.android.material.tabs.TabLayoutMediator @@ -39,5 +41,12 @@ class BiomeDetailActivity : companion object { const val BIOME_ID = "biomeId" + + fun intent( + context: Context, + biomeId: String, + ): Intent = + Intent(context, BiomeDetailActivity::class.java) + .putExtra(BIOME_ID, biomeId) } } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeDetailUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeDetailUiModel.kt index ca4d4bef..be603c86 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeDetailUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeDetailUiModel.kt @@ -30,7 +30,6 @@ class BiomeDetailUiModel( pokemons = (1..9).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "일반 $it", imageUrl = dummyUrl(it.toLong()), @@ -45,7 +44,6 @@ class BiomeDetailUiModel( pokemons = (10..21).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "희귀 $it", imageUrl = dummyUrl(it.toLong()), @@ -60,7 +58,6 @@ class BiomeDetailUiModel( pokemons = (22..24).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "전설 $it", imageUrl = dummyUrl(it.toLong()), @@ -78,7 +75,6 @@ class BiomeDetailUiModel( pokemons = (990..1005).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "일반 보스 $it", imageUrl = dummyUrl(it.toLong()), @@ -93,7 +89,6 @@ class BiomeDetailUiModel( pokemons = (1006..1011).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "희귀 보스 $it", imageUrl = dummyUrl(it.toLong()), @@ -108,7 +103,6 @@ class BiomeDetailUiModel( pokemons = (1012..1015).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "전설 보스 $it", imageUrl = dummyUrl(it.toLong()), @@ -126,7 +120,6 @@ class BiomeDetailUiModel( pokemons = (871..874).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "심지몬 $it", imageUrl = dummyUrl(it.toLong()), @@ -141,7 +134,6 @@ class BiomeDetailUiModel( pokemons = (901..905).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "꼬상몬 $it", imageUrl = dummyUrl(it.toLong()), @@ -156,7 +148,6 @@ class BiomeDetailUiModel( pokemons = (100..105).map { PokemonUiModel( - id = it.toLong(), dexNumber = it.toLong(), name = "비토몬 $it", imageUrl = dummyUrl(it.toLong()), diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeUiModel.kt index b63f64da..43b44fd1 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/biome/model/BiomeUiModel.kt @@ -3,7 +3,7 @@ package poke.rogue.helper.presentation.biome.model import poke.rogue.helper.presentation.type.model.TypeUiModel data class BiomeUiModel( - val id: Long, + val id: String, val name: String, val imageUrl: String, val types: List, @@ -12,49 +12,49 @@ data class BiomeUiModel( val DUMMYS: List = listOf( BiomeUiModel( - 1, + "1", "풀숲", "https://wiki.pokerogue.net/_media/ko:biomes:ko_grassy_fields_bg.png?w=200&tok=745c5b", types = listOf(TypeUiModel.GRASS, TypeUiModel.POISON), ), BiomeUiModel( - 2, + "2", "높은 풀숲", "https://wiki.pokerogue.net/_media/ko:biomes:ko_tall_grass_bg.png?w=200&tok=b3497c", types = listOf(TypeUiModel.BUG), ), BiomeUiModel( - 3, + "3", "동굴", "https://wiki.pokerogue.net/_media/ko:biomes:ko_cave_bg.png?w=200&tok=905d8b", types = listOf(TypeUiModel.GRASS), ), BiomeUiModel( - 4, + "4", "악지", "https://wiki.pokerogue.net/_media/ko:biomes:ko_badlands_bg.png?w=200&tok=37d070", types = listOf(TypeUiModel.DARK, TypeUiModel.FIGHTING), ), BiomeUiModel( - 5, + "5", "공장", "https://wiki.pokerogue.net/_media/en:biomes:en_factory_bg.png?w=200&tok=5c1cb5", types = listOf(TypeUiModel.DARK, TypeUiModel.FIGHTING), ), BiomeUiModel( - 6, + "6", "공사장", "https://wiki.pokerogue.net/_media/en:biomes:en_construction_site_bg.png?w=200&tok=8cf671", types = listOf(TypeUiModel.NORMAL, TypeUiModel.GROUND), ), BiomeUiModel( - 7, + "7", "눈덮힌 숲", "https://wiki.pokerogue.net/_media/en:biomes:en_snowy_forest_bg.png?w=200&tok=2fe712", types = listOf(TypeUiModel.ICE, TypeUiModel.STEEL), ), BiomeUiModel( - 8, + "8", "얼음동굴", "https://wiki.pokerogue.net/_media/en:biomes:en_ice_cave_bg.png?w=200&tok=aa8cf1", types = listOf(TypeUiModel.ICE, TypeUiModel.WATER), diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListNavigateHandler.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListNavigateHandler.kt index 81b7c020..f8097632 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListNavigateHandler.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListNavigateHandler.kt @@ -1,5 +1,5 @@ package poke.rogue.helper.presentation.dex interface PokemonListNavigateHandler { - fun navigateToPokemonDetail(pokemonId: Long) + fun navigateToPokemonDetail(pokemonId: String) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListViewModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListViewModel.kt index d5c3f3e6..1232467e 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListViewModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/PokemonListViewModel.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.plus import poke.rogue.helper.analytics.AnalyticsLogger import poke.rogue.helper.analytics.analyticsLogger import poke.rogue.helper.data.exception.PokeException -import poke.rogue.helper.data.model.Pokemon import poke.rogue.helper.data.repository.DexRepository import poke.rogue.helper.presentation.base.BaseViewModelFactory import poke.rogue.helper.presentation.base.error.ErrorHandleViewModel @@ -62,15 +61,15 @@ class PokemonListViewModel( true, ) - private val _navigateToDetailEvent = MutableSharedFlow() + private val _navigateToDetailEvent = MutableSharedFlow() val navigateToDetailEvent = _navigateToDetailEvent.asSharedFlow() private suspend fun queriedPokemons(query: String): List { return try { if (query.isBlank()) { - pokemonListRepository.pokemons().map(Pokemon::toUi) + pokemonListRepository.pokemons().toUi() } else { - pokemonListRepository.filteredPokemons(query).map(Pokemon::toUi) + pokemonListRepository.filteredPokemons(query).toUi() } } catch (e: PokeException) { handlePokemonError(e) @@ -80,7 +79,7 @@ class PokemonListViewModel( } } - override fun navigateToPokemonDetail(pokemonId: Long) { + override fun navigateToPokemonDetail(pokemonId: String) { viewModelScope.launch { _navigateToDetailEvent.emit(pokemonId) } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailActivity.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailActivity.kt index df082257..2847cf5f 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailActivity.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailActivity.kt @@ -12,9 +12,11 @@ import poke.rogue.helper.data.repository.DefaultDexRepository import poke.rogue.helper.databinding.ActivityPokemonDetailBinding import poke.rogue.helper.presentation.ability.AbilityActivity import poke.rogue.helper.presentation.base.toolbar.ToolbarActivity +import poke.rogue.helper.presentation.biome.detail.BiomeDetailActivity import poke.rogue.helper.presentation.dex.PokemonTypesAdapter import poke.rogue.helper.presentation.home.HomeActivity import poke.rogue.helper.presentation.type.view.TypeChip +import poke.rogue.helper.presentation.util.context.stringArrayOf import poke.rogue.helper.presentation.util.context.stringOf import poke.rogue.helper.presentation.util.repeatOnStarted import poke.rogue.helper.presentation.util.view.dp @@ -33,7 +35,7 @@ class PokemonDetailActivity : ToolbarActivity(R.la override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - viewModel.updatePokemonDetail(intent.getLongExtra(POKEMON_ID, 2606)) + viewModel.updatePokemonDetail(intent.getStringExtra(POKEMON_ID).toString()) binding.eventHandler = viewModel binding.lifecycleOwner = this @@ -54,13 +56,9 @@ class PokemonDetailActivity : ToolbarActivity(R.la adapter = pokemonDetailPagerAdapter } + val tabTitles = stringArrayOf(R.array.pokemon_detail_tab_titles) TabLayoutMediator(binding.tabLayoutPokemonDetail, binding.pagerPokemonDetail) { tab, position -> - when (position) { - 0 -> tab.text = stringOf(R.string.pokemon_detail_pokemon_stats_title) - 1 -> tab.text = stringOf(R.string.pokemon_detail_pokemon_evolution_title) - 2 -> tab.text = stringOf(R.string.pokemon_detail_pokemon_skills_title) - 3 -> tab.text = stringOf(R.string.pokemon_detail_pokemon_information_title) - } + tab.text = tabTitles[position] }.attach() } @@ -68,6 +66,7 @@ class PokemonDetailActivity : ToolbarActivity(R.la observePokemonDetailUi() observeNavigateToHomeEvent() observeNavigateToAbilityDetailEvent() + observeNavigateToBiomeDetailEvent() } private fun observePokemonDetailUi() { @@ -95,12 +94,20 @@ class PokemonDetailActivity : ToolbarActivity(R.la private fun observeNavigateToAbilityDetailEvent() { repeatOnStarted { - viewModel.navigationToDetailEvent.collect { abilityId -> + viewModel.navigationToAbilityDetailEvent.collect { abilityId -> startActivity(AbilityActivity.intent(this, abilityId)) } } } + private fun observeNavigateToBiomeDetailEvent() { + repeatOnStarted { + viewModel.navigationToDetailEvent.collect { biomeId -> + startActivity(BiomeDetailActivity.intent(this, biomeId)) + } + } + } + private fun bindPokemonDetail(pokemonDetail: PokemonDetailUiState.Success) { with(binding) { ivPokemonDetailPokemon.loadImageWithProgress( @@ -110,7 +117,7 @@ class PokemonDetailActivity : ToolbarActivity(R.la tvPokemonDetailPokemonName.text = stringOf( - R.string.dex_poke_name_format, + R.string.pokemon_list_poke_name_format, pokemonDetail.pokemon.name, pokemonDetail.pokemon.dexNumber, ) @@ -137,7 +144,7 @@ class PokemonDetailActivity : ToolbarActivity(R.la fun intent( context: Context, - pokemonId: Long, + pokemonId: String, ): Intent = Intent(context, PokemonDetailActivity::class.java).apply { putExtra(POKEMON_ID, pokemonId) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailNavigateHandler.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailNavigateHandler.kt index cb7f4672..dba58456 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailNavigateHandler.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailNavigateHandler.kt @@ -1,7 +1,9 @@ package poke.rogue.helper.presentation.dex.detail interface PokemonDetailNavigateHandler { - fun navigateToAbilityDetail(abilityId: Long) + fun navigateToAbilityDetail(abilityId: String) + + fun navigateToBiomeDetail(biomeId: String) fun navigateToHome() } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailUiState.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailUiState.kt index 69b65883..fb2e3bc3 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailUiState.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailUiState.kt @@ -1,10 +1,9 @@ package poke.rogue.helper.presentation.dex.detail -import poke.rogue.helper.data.model.Ability import poke.rogue.helper.data.model.PokemonDetail +import poke.rogue.helper.data.model.PokemonDetailSkills import poke.rogue.helper.data.model.Stat -import poke.rogue.helper.presentation.dex.model.AbilityTitleUiModel -import poke.rogue.helper.presentation.dex.model.PokemonSkillUiModel +import poke.rogue.helper.presentation.dex.model.PokemonDetailAbilityUiModel import poke.rogue.helper.presentation.dex.model.PokemonUiModel import poke.rogue.helper.presentation.dex.model.StatUiModel import poke.rogue.helper.presentation.dex.model.toPokemonDetailUi @@ -14,8 +13,8 @@ sealed interface PokemonDetailUiState { data class Success( val pokemon: PokemonUiModel, val stats: List, - val abilities: List, - val skills: List, + val abilities: List, + val skills: PokemonDetailSkills, val height: Float, val weight: Float, ) : PokemonDetailUiState @@ -27,8 +26,8 @@ fun PokemonDetail.toUi(): PokemonDetailUiState.Success = PokemonDetailUiState.Success( pokemon = pokemon.toUi(), stats = stats.map(Stat::toUi), - abilities = abilities.map(Ability::toPokemonDetailUi), - skills = skills.toUi(), - height = height, - weight = weight, + abilities = abilities.toPokemonDetailUi(), + skills = skills, + height = height.toFloat(), + weight = weight.toFloat(), ) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModel.kt index c497e97f..406d1142 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModel.kt @@ -32,22 +32,31 @@ class PokemonDetailViewModel( uiState.map { it is PokemonDetailUiState.IsLoading } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), true) - private val _navigationToDetailEvent = MutableSharedFlow() - val navigationToDetailEvent: SharedFlow = _navigationToDetailEvent.asSharedFlow() + private val _navigationToAbilityDetailEvent = MutableSharedFlow() + val navigationToAbilityDetailEvent: SharedFlow = _navigationToAbilityDetailEvent.asSharedFlow() + + private val _navigationToBiomeDetailEvent = MutableSharedFlow() + val navigationToDetailEvent: SharedFlow = _navigationToBiomeDetailEvent.asSharedFlow() private val _navigateToHomeEvent = MutableSharedFlow() val navigateToHomeEvent = _navigateToHomeEvent.asSharedFlow() - fun updatePokemonDetail(pokemonId: Long?) { + fun updatePokemonDetail(pokemonId: String) { requireNotNull(pokemonId) { "Pokemon ID must not be null" } viewModelScope.launch(errorHandler) { _uiState.value = dexRepository.pokemonDetail(pokemonId).toUi() } } - override fun navigateToAbilityDetail(abilityId: Long) { + override fun navigateToAbilityDetail(abilityId: String) { + viewModelScope.launch { + _navigationToAbilityDetailEvent.emit(abilityId) + } + } + + override fun navigateToBiomeDetail(biomeId: String) { viewModelScope.launch { - _navigationToDetailEvent.emit(abilityId) + _navigationToBiomeDetailEvent.emit(biomeId) } } diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeAdapter.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeAdapter.kt new file mode 100644 index 00000000..199aede0 --- /dev/null +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeAdapter.kt @@ -0,0 +1,42 @@ +package poke.rogue.helper.presentation.dex.detail.information + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import poke.rogue.helper.data.model.Biome +import poke.rogue.helper.databinding.ItemPokemonDetailInformationBiomeBinding +import poke.rogue.helper.presentation.dex.detail.PokemonDetailNavigateHandler +import poke.rogue.helper.presentation.util.view.ItemDiffCallback + +class PokemonDetailBiomeAdapter( + private val onClickBiomeItem: PokemonDetailNavigateHandler, +) : ListAdapter(biomeComparator) { + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): PokemonDetailBiomeViewHolder = + PokemonDetailBiomeViewHolder( + binding = + ItemPokemonDetailInformationBiomeBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false, + ), + onClickBiomeItem = onClickBiomeItem, + ) + + override fun onBindViewHolder( + holder: PokemonDetailBiomeViewHolder, + position: Int, + ) { + holder.bind(getItem(position)) + } + + companion object { + val biomeComparator = + ItemDiffCallback( + onItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id }, + onContentsTheSame = { oldItem, newItem -> oldItem == newItem }, + ) + } +} diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeViewHolder.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeViewHolder.kt new file mode 100644 index 00000000..fa2ff115 --- /dev/null +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonDetailBiomeViewHolder.kt @@ -0,0 +1,18 @@ +package poke.rogue.helper.presentation.dex.detail.information + +import androidx.recyclerview.widget.RecyclerView +import poke.rogue.helper.data.model.Biome +import poke.rogue.helper.databinding.ItemPokemonDetailInformationBiomeBinding +import poke.rogue.helper.presentation.dex.detail.PokemonDetailNavigateHandler + +class PokemonDetailBiomeViewHolder( + private val binding: ItemPokemonDetailInformationBiomeBinding, + private val onClickBiomeItem: PokemonDetailNavigateHandler, +) : RecyclerView.ViewHolder(binding.root) { + fun bind(biome: Biome) { + binding.apply { + this.biome = biome + uiEventHandler = onClickBiomeItem + } + } +} diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonInformationFragment.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonInformationFragment.kt index 904b13c5..077094a5 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonInformationFragment.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/information/PokemonInformationFragment.kt @@ -1,11 +1,51 @@ package poke.rogue.helper.presentation.dex.detail.information +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels import poke.rogue.helper.R +import poke.rogue.helper.data.model.Biome import poke.rogue.helper.databinding.FragmentPokemonInformationBinding import poke.rogue.helper.presentation.base.BindingFragment +import poke.rogue.helper.presentation.dex.detail.PokemonDetailUiState +import poke.rogue.helper.presentation.dex.detail.PokemonDetailViewModel +import poke.rogue.helper.presentation.util.repeatOnStarted +import poke.rogue.helper.presentation.util.view.GridSpacingItemDecoration +import poke.rogue.helper.presentation.util.view.dp class PokemonInformationFragment : BindingFragment(R.layout.fragment_pokemon_information) { + private val activityViewModel: PokemonDetailViewModel by activityViewModels() + private val biomesAdapter: PokemonDetailBiomeAdapter by lazy { PokemonDetailBiomeAdapter(activityViewModel) } + + override fun onViewCreated( + view: View, + savedInstanceState: Bundle?, + ) { + super.onViewCreated(view, savedInstanceState) + + initAdapter() + initObserver() + } + + private fun initAdapter() { + binding.rvPokemonDetailInformation.apply { + adapter = biomesAdapter + addItemDecoration(GridSpacingItemDecoration(2, 9.dp, false)) + } + } + + private fun initObserver() { + repeatOnStarted { + activityViewModel.uiState.collect { + when (it) { + is PokemonDetailUiState.IsLoading -> {} + is PokemonDetailUiState.Success -> biomesAdapter.submitList(Biome.DUMMYS) + } + } + } + } + override fun onResume() { super.onResume() binding.root.requestLayout() diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/skill/PokemonDetailSkillFragment.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/skill/PokemonDetailSkillFragment.kt index 77621853..d1062c23 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/skill/PokemonDetailSkillFragment.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/skill/PokemonDetailSkillFragment.kt @@ -6,10 +6,14 @@ import androidx.fragment.app.activityViewModels import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.divider.MaterialDividerItemDecoration.VERTICAL import poke.rogue.helper.R +import poke.rogue.helper.data.model.PokemonSkill import poke.rogue.helper.databinding.FragmentPokemonSkillsBinding import poke.rogue.helper.presentation.base.BindingFragment import poke.rogue.helper.presentation.dex.detail.PokemonDetailUiState import poke.rogue.helper.presentation.dex.detail.PokemonDetailViewModel +import poke.rogue.helper.presentation.dex.model.PokemonSkillUiModel +import poke.rogue.helper.presentation.dex.model.toUi +import poke.rogue.helper.presentation.type.model.toUi import poke.rogue.helper.presentation.util.repeatOnStarted import poke.rogue.helper.presentation.util.view.LinearSpacingItemDecoration import poke.rogue.helper.presentation.util.view.dp @@ -57,9 +61,24 @@ class PokemonDetailSkillFragment : BindingFragment activityViewModel.uiState.collect { state -> when (state) { is PokemonDetailUiState.IsLoading -> {} - is PokemonDetailUiState.Success -> skillsAdapter.submitList(state.skills) + // TODO: skill 을 현재는 한 종류의 스킬 목록만 사용하고 있음..... 이후에는 여러개의 스킬을 받아야함 + is PokemonDetailUiState.Success -> skillsAdapter.submitList(state.skills.selfLearn.toUi()) } } } } } + +// TODO: skill 을 현재는 한 종류의 스킬 목록만 사용하고 있음..... 이후에는 여러개의 스킬을 받아야함 +fun PokemonSkill.toUi(): PokemonSkillUiModel = + PokemonSkillUiModel( + id = id, + name = name, + level = level, + power = if (power == PokemonSkill.NO_POWER_VALUE) PokemonSkillUiModel.NO_POWER else power.toString(), + type = type.toUi(), + accuracy = accuracy, + category = category.toUi(), + ) + +fun List.toUi(): List = map(PokemonSkill::toUi) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/stat/PokemonStatFragment.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/stat/PokemonStatFragment.kt index 6f3f7d3e..dc447073 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/stat/PokemonStatFragment.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/detail/stat/PokemonStatFragment.kt @@ -14,6 +14,8 @@ import poke.rogue.helper.databinding.FragmentPokemonStatBinding import poke.rogue.helper.presentation.base.BindingFragment import poke.rogue.helper.presentation.dex.detail.PokemonDetailUiState import poke.rogue.helper.presentation.dex.detail.PokemonDetailViewModel +import poke.rogue.helper.presentation.dex.model.AbilityTitleUiModel +import poke.rogue.helper.presentation.dex.model.PokemonDetailAbilityUiModel import poke.rogue.helper.presentation.util.context.colorOf import poke.rogue.helper.presentation.util.repeatOnStarted import poke.rogue.helper.presentation.util.view.LinearSpacingItemDecoration @@ -67,7 +69,7 @@ class PokemonStatFragment : BindingFragment(R.layout private fun bindDatas(uiState: PokemonDetailUiState.Success) { binding.apply { pokemonStatAdapter.submitList(uiState.stats) - abilityAdapter.submitList(uiState.abilities) + abilityAdapter.submitList(uiState.abilities.toUi()) } } @@ -99,3 +101,11 @@ class PokemonStatFragment : BindingFragment(R.layout } } } + +private fun PokemonDetailAbilityUiModel.toUi(): AbilityTitleUiModel = + AbilityTitleUiModel( + id = id, + name = name, + ) + +private fun List.toUi(): List = map(PokemonDetailAbilityUiModel::toUi) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/AbilityTitleUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/AbilityTitleUiModel.kt index 1355f44d..5b5609bd 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/AbilityTitleUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/AbilityTitleUiModel.kt @@ -3,7 +3,7 @@ package poke.rogue.helper.presentation.dex.model import poke.rogue.helper.data.model.Ability data class AbilityTitleUiModel( - val id: Long, + val id: String, val name: String, ) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonDetailAbilityUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonDetailAbilityUiModel.kt new file mode 100644 index 00000000..372be2c5 --- /dev/null +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonDetailAbilityUiModel.kt @@ -0,0 +1,20 @@ +package poke.rogue.helper.presentation.dex.model + +import poke.rogue.helper.data.model.PokemonDetailAbility + +data class PokemonDetailAbilityUiModel( + val id: String, + val name: String, + val passive: Boolean, + val hidden: Boolean, +) + +fun PokemonDetailAbility.toPokemonDetailUi(): PokemonDetailAbilityUiModel = + PokemonDetailAbilityUiModel( + id = id, + name = name, + passive = passive, + hidden = hidden, + ) + +fun List.toPokemonDetailUi(): List = map(PokemonDetailAbility::toPokemonDetailUi) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonSkillUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonSkillUiModel.kt index 983ae980..d16874f6 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonSkillUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonSkillUiModel.kt @@ -5,7 +5,7 @@ import poke.rogue.helper.presentation.type.model.TypeUiModel import poke.rogue.helper.presentation.type.model.toUi data class PokemonSkillUiModel( - val id: Long, + val id: String, val name: String, val level: Int, val power: String, @@ -20,7 +20,7 @@ data class PokemonSkillUiModel( fun PokemonSkill.toUi(): PokemonSkillUiModel = PokemonSkillUiModel( - id = id, + id = id.toString(), name = name, level = level, power = if (power == PokemonSkill.NO_POWER_VALUE) PokemonSkillUiModel.NO_POWER else power.toString(), diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonUiModel.kt index 65bc5b47..a2b03e75 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/PokemonUiModel.kt @@ -1,12 +1,11 @@ package poke.rogue.helper.presentation.dex.model import poke.rogue.helper.data.model.Pokemon -import poke.rogue.helper.data.model.Type import poke.rogue.helper.presentation.type.model.TypeUiModel import poke.rogue.helper.presentation.type.model.toUi data class PokemonUiModel( - val id: Long, + val id: String = "", val dexNumber: Long, val name: String, val imageUrl: String, @@ -19,5 +18,7 @@ fun Pokemon.toUi(): PokemonUiModel = dexNumber = dexNumber, name = name, imageUrl = imageUrl, - types = types.map(Type::toUi), + types = types.toUi(), ) + +fun List.toUi(): List = map(Pokemon::toUi) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/SkillCategoryUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/SkillCategoryUiModel.kt index 0872de1b..50d653bb 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/SkillCategoryUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/dex/model/SkillCategoryUiModel.kt @@ -5,7 +5,7 @@ import poke.rogue.helper.R import poke.rogue.helper.data.model.SkillCategory data class SkillCategoryUiModel( - val id: Long, + val id: String, val name: String, @DrawableRes val iconResId: Int, ) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/type/model/TypeUiModel.kt b/android/app/src/main/java/poke/rogue/helper/presentation/type/model/TypeUiModel.kt index 419a92c7..aa0c4b47 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/type/model/TypeUiModel.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/type/model/TypeUiModel.kt @@ -40,3 +40,5 @@ enum class TypeUiModel( } fun Type.toUi(): TypeUiModel = TypeUiModel.valueOf(this.name) + +fun List.toUi(): List = map(Type::toUi) diff --git a/android/app/src/main/java/poke/rogue/helper/presentation/util/context/ContextExtension.kt b/android/app/src/main/java/poke/rogue/helper/presentation/util/context/ContextExtension.kt index 42956857..f27b107e 100644 --- a/android/app/src/main/java/poke/rogue/helper/presentation/util/context/ContextExtension.kt +++ b/android/app/src/main/java/poke/rogue/helper/presentation/util/context/ContextExtension.kt @@ -12,6 +12,7 @@ import android.view.View import android.view.WindowInsets import android.view.WindowManager import android.widget.Toast +import androidx.annotation.ArrayRes import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes @@ -61,6 +62,10 @@ fun Context.stringOf( vararg formatArgs: Any?, ) = getString(resId, *formatArgs) +fun Context.stringArrayOf( + @ArrayRes resId: Int, +) = resources.getStringArray(resId) + fun Context.colorOf( @ColorRes resId: Int, ) = ContextCompat.getColor(this, resId) diff --git a/android/app/src/main/res/layout-land/activity_home.xml b/android/app/src/main/res/layout-land/activity_home.xml index 171fffa3..aa7603b6 100644 --- a/android/app/src/main/res/layout-land/activity_home.xml +++ b/android/app/src/main/res/layout-land/activity_home.xml @@ -125,7 +125,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="12dp" - android:text="@string/home_menu_dex" + android:text="@string/home_menu_pokemon_detail" android:textAlignment="center" android:textAppearance="@style/TextAppearance.Poke.TitleBold" /> diff --git a/android/app/src/main/res/layout/activity_home.xml b/android/app/src/main/res/layout/activity_home.xml index ca23a9bc..ed721913 100644 --- a/android/app/src/main/res/layout/activity_home.xml +++ b/android/app/src/main/res/layout/activity_home.xml @@ -177,7 +177,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="25dp" - android:text="@string/home_menu_dex" + android:text="@string/home_menu_pokemon_detail" android:textAlignment="center" android:textAppearance="@style/TextAppearance.Poke.TitleBold" app:layout_constraintBottom_toBottomOf="parent" diff --git a/android/app/src/main/res/layout/activity_pokemon_detail.xml b/android/app/src/main/res/layout/activity_pokemon_detail.xml index 58ec429d..81de9caf 100644 --- a/android/app/src/main/res/layout/activity_pokemon_detail.xml +++ b/android/app/src/main/res/layout/activity_pokemon_detail.xml @@ -32,7 +32,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:title="@string/dex_title_name"> + app:title="@string/pokemon_list_title_name"> + app:title="@string/pokemon_list_title_name"> + app:queryHint="@string/pokemon_list_list_search_pokemon_hint" /> @@ -74,7 +74,7 @@ style="@style/TextAppearance.Poke.TitleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/dex_list_loading_guide" + android:text="@string/pokemon_list_loading_guide" android:textSize="28sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -106,7 +106,7 @@ style="@style/TextAppearance.Poke.TitleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/dex_list_empty_guide" + android:text="@string/pokemon_list_empty_guide" android:textSize="28sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/android/app/src/main/res/layout/fragment_pokemon_information.xml b/android/app/src/main/res/layout/fragment_pokemon_information.xml index ceddc87f..29dd2176 100644 --- a/android/app/src/main/res/layout/fragment_pokemon_information.xml +++ b/android/app/src/main/res/layout/fragment_pokemon_information.xml @@ -1,17 +1,123 @@ - + - + android:layout_height="wrap_content"> - - + android:layout_height="wrap_content" + android:layout_marginHorizontal="10dp" + android:layout_marginTop="10dp" + android:background="@drawable/shape_pokemon_corner_radius" + android:padding="10dp" + app:layout_constraintBottom_toTopOf="@id/tv_pokemon_detail_information_biome_title" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + + + + + + + + + + + + /> + + + + + + + + + - + \ No newline at end of file diff --git a/android/app/src/main/res/layout/item_pokemon_detail_information_biome.xml b/android/app/src/main/res/layout/item_pokemon_detail_information_biome.xml new file mode 100644 index 00000000..93592868 --- /dev/null +++ b/android/app/src/main/res/layout/item_pokemon_detail_information_biome.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index c16cb314..8283e1bf 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -13,6 +13,7 @@ 약한 무효한 대등한 + 포켓로그 바로가기 피드백 보내기 @@ -20,30 +21,33 @@ https://namu.wiki/w/Pok%C3%A9Rogue https://docs.google.com/forms/d/e/1FAIpQLScd-Kp5zCzrcWKO6eXR7Ujgm0TscGrwuCPNCX1na0enhtVZaw/viewform 상성 보기 - 포켓몬 도감 + 포켓몬 도감 특성 도감 꿀팁 배틀 구도 바이옴 도감 아이템 도감 - - 포켓몬 도감 - %03d/%03d - %s #%d - 포켓몬 이름으로 검색하세요. - 잘못된 containerId값(-1) 입니다. - Loading… - 해당하는 포켓몬이 없어요 + + 포켓몬 도감 + %03d/%03d + %s #%d + 포켓몬 이름으로 검색하세요. + 잘못된 containerId값(-1) 입니다. + Loading… + 해당하는 포켓몬이 없어요 - + 기본 스탯 - 능력치 - 기술 정보 - 진화 정보 - 정보 - + + 능력치 + 진화 정보 + 기술 정보 + 정보 + + + 레벨 기술명 위력 @@ -51,6 +55,9 @@ 타입 분류 + + 체중 + 특성 도감 diff --git a/android/app/src/test/java/poke/rogue/helper/presentation/ability/AbilityViewModelTest.kt b/android/app/src/test/java/poke/rogue/helper/presentation/ability/AbilityViewModelTest.kt index 792c2c2f..37de965a 100644 --- a/android/app/src/test/java/poke/rogue/helper/presentation/ability/AbilityViewModelTest.kt +++ b/android/app/src/test/java/poke/rogue/helper/presentation/ability/AbilityViewModelTest.kt @@ -52,17 +52,17 @@ class AbilityViewModelTest { abilities shouldBe listOf( AbilityUiModel( - id = 14, + id = "14", title = "불면", description = "잠들지 못하는 체질이라 잠듦 상태가 되지 않는다.", ), AbilityUiModel( - id = 17, + id = "17", title = "타오르는불꽃", description = "불꽃타입의 기술을 받으면 불꽃을 받아서 자신이 사용하는 불꽃타입의 기술이 강해진다.", ), AbilityUiModel( - id = 24, + id = "24", title = "불가사의부적", description = "효과가 굉장한 기술만 맞는 불가사의한 힘.", ), @@ -73,7 +73,7 @@ class AbilityViewModelTest { fun `특성 id값으로 특성 상세 화면으로 이동한다`() = runTest { // given - val abilityId = 15L + val abilityId = "15L" // when launch { diff --git a/android/app/src/test/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModelTest.kt b/android/app/src/test/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModelTest.kt index b0c2252a..5a7308f8 100644 --- a/android/app/src/test/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModelTest.kt +++ b/android/app/src/test/java/poke/rogue/helper/presentation/ability/detail/AbilityDetailViewModelTest.kt @@ -31,11 +31,14 @@ class AbilityDetailViewModelTest { fun `특성 id값으로 특성 상세 정보를 불러온다`() = runTest { // given - val abilityId = 1L + val abilityId = "1L" // when viewModel.updateAbilityDetail(abilityId) - val abilityDetail = viewModel.abilityDetail.first() + val abilityDetail = + viewModel.abilityDetail.first { + it is AbilityDetailUiState.Success + } val detail = (abilityDetail as AbilityDetailUiState.Success).data.toUi() // then @@ -48,7 +51,7 @@ class AbilityDetailViewModelTest { runTest { // given Dispatchers.setMain(StandardTestDispatcher()) - val pokemonId = 1L + val pokemonId = "1L" // when viewModel.navigateToPokemonDetail(pokemonId) diff --git a/android/app/src/test/java/poke/rogue/helper/presentation/dex/PokemonListViewModelTest.kt b/android/app/src/test/java/poke/rogue/helper/presentation/dex/PokemonListViewModelTest.kt index e81bc94c..997780fe 100644 --- a/android/app/src/test/java/poke/rogue/helper/presentation/dex/PokemonListViewModelTest.kt +++ b/android/app/src/test/java/poke/rogue/helper/presentation/dex/PokemonListViewModelTest.kt @@ -59,14 +59,14 @@ class PokemonListViewModelTest { queriedPokemons shouldBe listOf( PokemonUiModel( - id = 5, + id = "5", dexNumber = 5, name = "리자드", imageUrl = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/5.png", types = listOf(TypeUiModel.FIRE), ), PokemonUiModel( - id = 6, + id = "6", dexNumber = 6, name = "리자몽", imageUrl = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/6.png", diff --git a/android/app/src/test/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModelTest.kt b/android/app/src/test/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModelTest.kt index 5b5f23f2..b620bf0e 100644 --- a/android/app/src/test/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModelTest.kt +++ b/android/app/src/test/java/poke/rogue/helper/presentation/dex/detail/PokemonDetailViewModelTest.kt @@ -7,11 +7,11 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import poke.rogue.helper.R +import poke.rogue.helper.data.model.PokemonDetailSkills +import poke.rogue.helper.data.model.PokemonSkill import poke.rogue.helper.data.repository.DexRepository -import poke.rogue.helper.presentation.dex.model.AbilityTitleUiModel -import poke.rogue.helper.presentation.dex.model.PokemonSkillUiModel +import poke.rogue.helper.presentation.dex.model.PokemonDetailAbilityUiModel import poke.rogue.helper.presentation.dex.model.PokemonUiModel -import poke.rogue.helper.presentation.dex.model.SkillCategoryUiModel import poke.rogue.helper.presentation.dex.model.StatUiModel import poke.rogue.helper.presentation.type.model.TypeUiModel import poke.rogue.helper.testing.CoroutinesTestExtension @@ -48,7 +48,7 @@ class PokemonDetailViewModelTest { viewModel = PokemonDetailViewModel(repository) // when - viewModel.updatePokemonDetail(pokemonId = 1) + viewModel.updatePokemonDetail(pokemonId = "1") // then val pokemonDetailUiState = viewModel.uiState @@ -56,7 +56,7 @@ class PokemonDetailViewModelTest { PokemonDetailUiState.Success( pokemon = PokemonUiModel( - id = 1, + id = "1", dexNumber = 1, name = "이상해씨", imageUrl = @@ -80,146 +80,14 @@ class PokemonDetailViewModelTest { ), abilities = listOf( - AbilityTitleUiModel(450, "심록"), - AbilityTitleUiModel(419, "엽록소"), + PokemonDetailAbilityUiModel("450", "심록", false, false), + PokemonDetailAbilityUiModel("419", "엽록소", false, false), ), skills = - listOf( - PokemonSkillUiModel( - id = 1, - name = "몸통박치기", - level = 1, - power = "40", - type = TypeUiModel.NORMAL, - accuracy = 100, - category = SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 2, - name = "울음소리", - level = 1, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.NORMAL, - accuracy = 100, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 3, - name = "덩굴채찍", - level = 1, - power = "45", - type = TypeUiModel.GRASS, - accuracy = 100, - category = SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 4, - name = "성장", - level = 6, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.NORMAL, - accuracy = 100, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 5, - name = "씨뿌리기", - level = 9, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.GRASS, - accuracy = 90, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 6, - name = "앞날가르기", - level = 12, - power = "55", - type = TypeUiModel.GRASS, - accuracy = 95, - SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 7, - name = "독가루", - level = 15, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.POISON, - accuracy = 75, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 8, - name = "수면가루", - level = 15, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.GRASS, - accuracy = 75, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 9, - name = "씨폭탄", - level = 18, - power = "80", - type = TypeUiModel.GRASS, - accuracy = 100, - category = SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 10, - name = "돌진", - level = 21, - power = "90", - type = TypeUiModel.NORMAL, - accuracy = 85, - category = SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 11, - name = "달콤한향기", - level = 24, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.NORMAL, - accuracy = 100, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 12, - name = "광합성", - level = 27, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.GRASS, - accuracy = 100, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 13, - name = "고민씨", - level = 30, - power = PokemonSkillUiModel.NO_POWER, - type = TypeUiModel.GRASS, - accuracy = 100, - category = SkillCategoryUiModel(3, "변화", R.drawable.ic_change_status_skill), - ), - PokemonSkillUiModel( - id = 14, - name = "파워휩", - level = 33, - power = "120", - type = TypeUiModel.GRASS, - accuracy = 85, - category = SkillCategoryUiModel(1, "물리", R.drawable.ic_physical_attack_skill), - ), - PokemonSkillUiModel( - id = 15, - name = "솔라빔", - level = 36, - power = "120", - type = TypeUiModel.GRASS, - accuracy = 100, - category = SkillCategoryUiModel(2, "특수", R.drawable.ic_special_attack_skill), - ), + PokemonDetailSkills( + selfLearn = PokemonSkill.FAKE_SELF_LEARN_SKILLS, + eggLearn = PokemonSkill.FAKE_EGG_LEARN_SKILLS, + tmLearn = PokemonSkill.FAKE_SELF_LEARN_SKILLS, ), height = 0.7f, weight = 6.9f, diff --git a/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteAbilityDataSource.kt b/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteAbilityDataSource.kt index c0ef8242..6dcb613a 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteAbilityDataSource.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteAbilityDataSource.kt @@ -22,8 +22,9 @@ class RemoteAbilityDataSource( .getOrThrow() .map { it.toData() } - suspend fun abilityDetail(id: Long): AbilityDetail = - abilityService.ability(id) + // TODO: 서비스에서 실제로 string 값을 보내준다면 id.toLong 에서 toLong 을 제거합시다 + suspend fun abilityDetail(id: String): AbilityDetail = + abilityService.ability(id.toLong()) .onFailure { logger.logError(throwable, "abilityService - ability($id) 에서 발생") } diff --git a/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteDexDataSource.kt b/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteDexDataSource.kt index 8025444a..0479c0d9 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteDexDataSource.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/datasource/RemoteDexDataSource.kt @@ -22,13 +22,14 @@ class RemoteDexDataSource( .getOrThrow() .toData() - suspend fun pokemon(id: Long): PokemonDetail = - pokeDexService.pokemon(id) + // TODO: Long 제거? + suspend fun pokemon(id: String): PokemonDetail = + pokeDexService.pokemon(id.toLong()) .onFailure { logger.logError(throwable, "pokeDexService - pokemon($id) 에서 발생") } .getOrThrow() - .toData(id) + .toData(id.toLong()) companion object { private var instance: RemoteDexDataSource? = null diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/Ability.kt b/android/data/src/main/java/poke/rogue/helper/data/model/Ability.kt index 0320becd..6bb7ed7b 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/model/Ability.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/model/Ability.kt @@ -3,14 +3,15 @@ package poke.rogue.helper.data.model import poke.rogue.helper.remote.dto.response.ability.AbilityResponse data class Ability( - val id: Long = 0, + val id: String = "0", val title: String, val description: String, ) +// TODO: 서버에서 String 으로 주면 id.toString 제거해도 된다 fun AbilityResponse.toData(): Ability = Ability( - id = id, + id = id.toString(), title = title, description = description, ) diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/Biome.kt b/android/data/src/main/java/poke/rogue/helper/data/model/Biome.kt new file mode 100644 index 00000000..5fdab72e --- /dev/null +++ b/android/data/src/main/java/poke/rogue/helper/data/model/Biome.kt @@ -0,0 +1,28 @@ +package poke.rogue.helper.data.model + +data class Biome( + val id: String, + val name: String, + val imageUrl: String, +) { + companion object { + val DUMMYS: List = + listOf( + Biome( + "1", + "평야", + "https://pokeroguedex.com/biomes/plains.png", + ), + Biome( + "2", + "높은 풀숲", + "https://pokeroguedex.com/biomes/tall-grass.png", + ), + Biome( + "3", + "동굴", + "https://pokeroguedex.com/biomes/cave.png", + ), + ) + } +} diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/Evolution.kt b/android/data/src/main/java/poke/rogue/helper/data/model/Evolution.kt new file mode 100644 index 00000000..a9f5b808 --- /dev/null +++ b/android/data/src/main/java/poke/rogue/helper/data/model/Evolution.kt @@ -0,0 +1,9 @@ +package poke.rogue.helper.data.model + +data class Evolution( + val pokemonId: String, + val pokemonName: String, + val level: Int, + val item: String?, + val condition: String?, +) diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/Pokemon.kt b/android/data/src/main/java/poke/rogue/helper/data/model/Pokemon.kt index f79fdef4..5b8e6403 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/model/Pokemon.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/model/Pokemon.kt @@ -4,7 +4,7 @@ import poke.rogue.helper.remote.dto.response.pokemon.PokemonResponse import poke.rogue.helper.remote.dto.response.type.PokemonTypeResponse data class Pokemon( - val id: Long, + val id: String, val dexNumber: Long, val name: String, val imageUrl: String, @@ -26,7 +26,7 @@ data class Pokemon( val DUMMY = Pokemon( - id = 1, + id = "1", dexNumber = 1, name = DUMMY_POKEMON_NAME, imageUrl = DUMMY_IMAGE_URL, @@ -37,7 +37,7 @@ data class Pokemon( fun PokemonResponse.toData(): Pokemon = Pokemon( - id = id, + id = id.toString(), dexNumber = pokedexNumber, name = name, imageUrl = image, diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonCategory.kt b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonCategory.kt new file mode 100644 index 00000000..c872d88f --- /dev/null +++ b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonCategory.kt @@ -0,0 +1,18 @@ +package poke.rogue.helper.data.model + +data class PokemonCategory( + val legendary: Boolean, + val subLegendary: Boolean, + val mythical: Boolean, + val canChangeForm: Boolean, +) { + companion object { + val EMPTY = + PokemonCategory( + legendary = false, + subLegendary = false, + mythical = false, + canChangeForm = false, + ) + } +} diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetail.kt b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetail.kt index 3ca964ea..640fabff 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetail.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetail.kt @@ -6,22 +6,28 @@ import poke.rogue.helper.remote.dto.response.type.PokemonTypeResponse data class PokemonDetail( val pokemon: Pokemon, + val abilities: List, val stats: List, - val abilities: List, - val skills: List = PokemonSkill.FAKE_SKILLS, - val height: Float, - val weight: Float, + val pokemonCategory: PokemonCategory, + val evolutions: List, + val skills: PokemonDetailSkills, + val biomes: List, + val height: Double, + val weight: Double, ) +// TODO: 서버에서 String 으로 주면 id: Long -> id.String() 으로 변경 fun PokemonDetailResponse.toData(id: Long): PokemonDetail = PokemonDetail( - Pokemon( - id = id, - dexNumber = dexNumber, - name = name, - imageUrl = imageUrl, - types = types.map(PokemonTypeResponse::toData), - ), + pokemon = + Pokemon( + id = id.toString(), + dexNumber = dexNumber, + name = name, + imageUrl = imageUrl, + types = types.map(PokemonTypeResponse::toData), + ), + abilities = abilities.map(AbilityResponse::toNewData), stats = listOf( Stat("hp", hp), @@ -32,7 +38,15 @@ fun PokemonDetailResponse.toData(id: Long): PokemonDetail = Stat("speed", speed), Stat("total", totalStats), ), - abilities = abilities.map(AbilityResponse::toData), - height = height, - weight = weight, + pokemonCategory = PokemonCategory.EMPTY, + evolutions = emptyList(), + skills = + PokemonDetailSkills( + selfLearn = PokemonSkill.FAKE_SELF_LEARN_SKILLS, + tmLearn = PokemonSkill.FAKE_SELF_LEARN_SKILLS, + eggLearn = PokemonSkill.FAKE_EGG_LEARN_SKILLS, + ), + biomes = Biome.DUMMYS, + height = height.toDouble(), + weight = weight.toDouble(), ) diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailAbility.kt b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailAbility.kt new file mode 100644 index 00000000..6d47a346 --- /dev/null +++ b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailAbility.kt @@ -0,0 +1,20 @@ +package poke.rogue.helper.data.model + +import poke.rogue.helper.remote.dto.response.ability.AbilityResponse + +data class PokemonDetailAbility( + val id: String, + val name: String, + val description: String, + val passive: Boolean, + val hidden: Boolean, +) + +fun AbilityResponse.toNewData(): PokemonDetailAbility = + PokemonDetailAbility( + id = id.toString(), + name = title, + description = description, + passive = false, + hidden = false, + ) diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailSkills.kt b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailSkills.kt new file mode 100644 index 00000000..1af97c5b --- /dev/null +++ b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonDetailSkills.kt @@ -0,0 +1,7 @@ +package poke.rogue.helper.data.model + +data class PokemonDetailSkills( + val selfLearn: List, + val eggLearn: List, + val tmLearn: List, +) diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonSkill.kt b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonSkill.kt index 746eacca..5bd6e8f7 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/model/PokemonSkill.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/model/PokemonSkill.kt @@ -1,7 +1,7 @@ package poke.rogue.helper.data.model data class PokemonSkill( - val id: Long, + val id: String, val name: String, val level: Int, val power: Int, @@ -12,10 +12,189 @@ data class PokemonSkill( companion object { const val NO_POWER_VALUE = -1 - val FAKE_SKILLS = + val FAKE_EGG_LEARN_SKILLS = listOf( PokemonSkill( - id = 1, + id = "101", + name = "기가드레인", + level = 1, + power = 75, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.specialAttackSkill, + ), + PokemonSkill( + id = "102", + name = "오물폭탄", + level = 1, + power = 90, + type = Type.POISON, + accuracy = 100, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "103", + name = "대지의힘", + level = 1, + power = 90, + type = Type.GROUND, + accuracy = 100, + category = SkillCategory.specialAttackSkill, + ), + PokemonSkill( + id = "104", + name = "쑥쑥봄버", + level = 1, + power = 100, + type = Type.GRASS, + accuracy = 90, + category = SkillCategory.physicalAttackSkill, + ), + ) + + val FAKE_SELF_LEARN_SKILLS = + listOf( + PokemonSkill( + id = "1", + name = "몸통박치기", + level = 1, + power = 40, + type = Type.NORMAL, + accuracy = 100, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "2", + name = "울음소리", + level = 1, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.NORMAL, + accuracy = 100, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "3", + name = "덩굴채찍", + level = 1, + power = 45, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "4", + name = "성장", + level = 6, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.NORMAL, + accuracy = 100, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "5", + name = "씨뿌리기", + level = 9, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.GRASS, + accuracy = 90, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "6", + name = "앞날가르기", + level = 12, + power = 55, + type = Type.GRASS, + accuracy = 95, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "7", + name = "독가루", + level = 15, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.POISON, + accuracy = 75, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "8", + name = "수면가루", + level = 15, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.GRASS, + accuracy = 75, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "9", + name = "씨폭탄", + level = 18, + power = 80, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "10", + name = "돌진", + level = 21, + power = 90, + type = Type.NORMAL, + accuracy = 85, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "11", + name = "달콤한향기", + level = 24, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.NORMAL, + accuracy = 100, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "12", + name = "광합성", + level = 27, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "13", + name = "고민씨", + level = 30, + power = PokemonSkill.NO_POWER_VALUE, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.changeStatusSkill, + ), + PokemonSkill( + id = "14", + name = "파워휩", + level = 33, + power = 120, + type = Type.GRASS, + accuracy = 85, + category = SkillCategory.physicalAttackSkill, + ), + PokemonSkill( + id = "15", + name = "솔라빔", + level = 36, + power = 120, + type = Type.GRASS, + accuracy = 100, + category = SkillCategory.specialAttackSkill, + ), + ) + + val FAKE_TM_LEARN_SKILLS = + listOf( + PokemonSkill( + id = "1", name = "몸통박치기", level = 1, power = 40, @@ -24,16 +203,16 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 2, + id = "2", name = "울음소리", level = 1, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.NORMAL, accuracy = 100, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 3, + id = "3", name = "덩굴채찍", level = 1, power = 45, @@ -42,25 +221,25 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 4, + id = "4", name = "성장", level = 6, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.NORMAL, accuracy = 100, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 5, + id = "5", name = "씨뿌리기", level = 9, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.GRASS, accuracy = 90, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 6, + id = "6", name = "앞날가르기", level = 12, power = 55, @@ -69,25 +248,25 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 7, + id = "7", name = "독가루", level = 15, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.POISON, accuracy = 75, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 8, + id = "8", name = "수면가루", level = 15, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.GRASS, accuracy = 75, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 9, + id = "9", name = "씨폭탄", level = 18, power = 80, @@ -96,7 +275,7 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 10, + id = "10", name = "돌진", level = 21, power = 90, @@ -105,34 +284,34 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 11, + id = "11", name = "달콤한향기", level = 24, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.NORMAL, accuracy = 100, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 12, + id = "12", name = "광합성", level = 27, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.GRASS, accuracy = 100, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 13, + id = "13", name = "고민씨", level = 30, - power = NO_POWER_VALUE, + power = PokemonSkill.NO_POWER_VALUE, type = Type.GRASS, accuracy = 100, category = SkillCategory.changeStatusSkill, ), PokemonSkill( - id = 14, + id = "14", name = "파워휩", level = 33, power = 120, @@ -141,7 +320,7 @@ data class PokemonSkill( category = SkillCategory.physicalAttackSkill, ), PokemonSkill( - id = 15, + id = "15", name = "솔라빔", level = 36, power = 120, diff --git a/android/data/src/main/java/poke/rogue/helper/data/model/SkillCategory.kt b/android/data/src/main/java/poke/rogue/helper/data/model/SkillCategory.kt index 50132947..3ea36bc0 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/model/SkillCategory.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/model/SkillCategory.kt @@ -1,25 +1,25 @@ package poke.rogue.helper.data.model data class SkillCategory( - val id: Long, + val id: String, val name: String, ) { companion object { val physicalAttackSkill = SkillCategory( - id = 1, + id = "1", name = "물리", ) val specialAttackSkill = SkillCategory( - id = 2, + id = "2", name = "특수", ) val changeStatusSkill = SkillCategory( - id = 3, + id = "3", name = "변화", ) } diff --git a/android/data/src/main/java/poke/rogue/helper/data/repository/AbilityRepository.kt b/android/data/src/main/java/poke/rogue/helper/data/repository/AbilityRepository.kt index 086d89aa..74d7070a 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/repository/AbilityRepository.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/repository/AbilityRepository.kt @@ -8,5 +8,5 @@ interface AbilityRepository { suspend fun abilities(query: String): List - suspend fun abilityDetail(id: Long): AbilityDetail + suspend fun abilityDetail(id: String): AbilityDetail } diff --git a/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultAbilityRepository.kt b/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultAbilityRepository.kt index 30d08809..043e5a2c 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultAbilityRepository.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultAbilityRepository.kt @@ -23,7 +23,7 @@ class DefaultAbilityRepository(private val remoteAbilityDataSource: RemoteAbilit return abilities().filter { it.title.has(query) } } - override suspend fun abilityDetail(id: Long): AbilityDetail = remoteAbilityDataSource.abilityDetail(id) + override suspend fun abilityDetail(id: String): AbilityDetail = remoteAbilityDataSource.abilityDetail(id) companion object { private var instance: AbilityRepository? = null diff --git a/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultDexRepository.kt b/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultDexRepository.kt index d9afa726..2a0ec71e 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultDexRepository.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/repository/DefaultDexRepository.kt @@ -11,7 +11,7 @@ class DefaultDexRepository( private val dexDataSource: RemoteDexDataSource, ) : DexRepository { private var cachedPokemons: List = emptyList() - private var cachedPokemonDetails: MutableMap = mutableMapOf() + private var cachedPokemonDetails: MutableMap = mutableMapOf() override suspend fun pokemons(): List { if (cachedPokemons.isEmpty()) { @@ -32,7 +32,7 @@ class DefaultDexRepository( }.toFilteredPokemons(sort, filters) } - override suspend fun pokemonDetail(id: Long): PokemonDetail { + override suspend fun pokemonDetail(id: String): PokemonDetail { val cached = cachedPokemonDetails[id] if (cached != null) { return cached diff --git a/android/data/src/main/java/poke/rogue/helper/data/repository/DexRepository.kt b/android/data/src/main/java/poke/rogue/helper/data/repository/DexRepository.kt index feb829f8..9f4f33ee 100644 --- a/android/data/src/main/java/poke/rogue/helper/data/repository/DexRepository.kt +++ b/android/data/src/main/java/poke/rogue/helper/data/repository/DexRepository.kt @@ -14,5 +14,5 @@ interface DexRepository { filters: List = emptyList(), ): List - suspend fun pokemonDetail(id: Long): PokemonDetail + suspend fun pokemonDetail(id: String): PokemonDetail } diff --git a/android/data/src/test/java/poke/rogue/helper/data/datasource/RemoteDexDataSourceTest.kt b/android/data/src/test/java/poke/rogue/helper/data/datasource/RemoteDexDataSourceTest.kt index 4912c711..4aa08ddc 100644 --- a/android/data/src/test/java/poke/rogue/helper/data/datasource/RemoteDexDataSourceTest.kt +++ b/android/data/src/test/java/poke/rogue/helper/data/datasource/RemoteDexDataSourceTest.kt @@ -27,7 +27,7 @@ class RemoteDexDataSourceTest { val actualPokemonDatas = dataSource.pokemons() // then - val expectedPokemonDatas = pokemons(1, 2, 3, 4, 5) + val expectedPokemonDatas = pokemons("1", "2", "3", "4", "5") actualPokemonDatas shouldBe expectedPokemonDatas } } diff --git a/android/data/src/test/java/poke/rogue/helper/data/model/PokemonMapperTest.kt b/android/data/src/test/java/poke/rogue/helper/data/model/PokemonMapperTest.kt index e54b969d..6795764b 100644 --- a/android/data/src/test/java/poke/rogue/helper/data/model/PokemonMapperTest.kt +++ b/android/data/src/test/java/poke/rogue/helper/data/model/PokemonMapperTest.kt @@ -26,7 +26,7 @@ class PokemonMapperTest { // when val expectedPokemonData = Pokemon( - id = 1, + id = "1", dexNumber = 1, name = "name", imageUrl = "image", @@ -46,21 +46,21 @@ class PokemonMapperTest { val expectedPokemonDatas = listOf( Pokemon( - id = 1, + id = "1", dexNumber = 10, name = "pokemon1", imageUrl = "logo1", types = listOf(Type.GRASS, Type.POISON), ), Pokemon( - id = 2, + id = "2", dexNumber = 20, name = "pokemon2", imageUrl = "logo2", types = listOf(Type.GRASS, Type.POISON), ), Pokemon( - id = 3, + id = "3", dexNumber = 30, name = "pokemon3", imageUrl = "logo3", diff --git a/android/data/src/test/java/poke/rogue/helper/data/model/fixture/PokemonResponseFixture.kt b/android/data/src/test/java/poke/rogue/helper/data/model/fixture/PokemonResponseFixture.kt index 49d1330a..da27961e 100644 --- a/android/data/src/test/java/poke/rogue/helper/data/model/fixture/PokemonResponseFixture.kt +++ b/android/data/src/test/java/poke/rogue/helper/data/model/fixture/PokemonResponseFixture.kt @@ -46,10 +46,10 @@ fun pokemonResponses(vararg ids: Long): List = ids.map(::pokemo * @param types 포켓몬의 타입 목록. default: 풀, 독 * @return [Pokemon] */ -fun pokemon(id: Long) = +fun pokemon(id: String) = Pokemon( id = id, - dexNumber = id * 10, + dexNumber = id.toLong() * 10, name = "pokemon$id", imageUrl = "logo$id", types = listOf(Type.GRASS, Type.POISON), @@ -60,4 +60,4 @@ fun pokemon(id: Long) = * @param ids 포켓몬의 id 목록 (vararg) * @return [List]<[Pokemon]> */ -fun pokemons(vararg ids: Long) = ids.map(::pokemon) +fun pokemons(vararg ids: String) = ids.map(::pokemon) diff --git a/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeAbilityRepository.kt b/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeAbilityRepository.kt index 8beb28ef..baa0ce6c 100644 --- a/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeAbilityRepository.kt +++ b/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeAbilityRepository.kt @@ -15,7 +15,7 @@ class FakeAbilityRepository : AbilityRepository { ability.title.has(query) } - override suspend fun abilityDetail(id: Long): AbilityDetail = + override suspend fun abilityDetail(id: String): AbilityDetail = ABILITY_DETAILS[id] ?: throw IllegalArgumentException("Invalid Ability Id") companion object { @@ -29,42 +29,42 @@ class FakeAbilityRepository : AbilityRepository { val ABILITES: List = listOf( - Ability(1, "악취", "악취를 풍겨서 공격했을 때 상대가 풀죽을 때가 있다."), - Ability(2, "잔비", "등장했을 때 날씨를 비로 만든다."), - Ability(3, "가속", "매 턴 스피드가 올라간다."), - Ability(4, "전투무장", "단단한 껍질에 보호받아 상대의 공격이 급소에 맞지 않는다."), - Ability(5, "옹골참", "상대 기술을 받아도 일격으로 쓰러지지 않는다. 일격필살 기술도 효과 없다."), - Ability(6, "유연", "주변을 습하게 함으로써 자폭 등 폭발하는 기술을 아무도 못 쓰게 한다."), - Ability(7, "모래숨기", "모래바람일 때 회피율이 올라간다."), - Ability(8, "정전기", "정전기를 몸에 둘러 접촉한 상대를 마비시킬 때가 있다."), - Ability(9, "축전 (P)", "전기타입의 기술을 받으면 데미지를 받지 않고 회복한다."), - Ability(10, "저수 (P)", "물타입의 기술을 받으면 데미지를 받지 않고 회복한다."), - Ability(11, "둔감", "둔감해서 헤롱헤롱이나 도발 상태가 되지 않는다."), - Ability(12, "날씨부정", "모든 날씨의 영향이 없어진다."), - Ability(13, "복안", "복안을 가지고 있어 기술의 명중률이 올라간다."), - Ability(14, "불면", "잠들지 못하는 체질이라 잠듦 상태가 되지 않는다."), - Ability(15, "변색", "상대에게 받은 기술의 타입으로 자신의 타입이 변화한다."), - Ability(16, "면역", "체내에 면역을 가지고 있어 독 상태가 되지 않는다."), - Ability(17, "타오르는불꽃", "불꽃타입의 기술을 받으면 불꽃을 받아서 자신이 사용하는 불꽃타입의 기술이 강해진다."), - Ability(18, "인분 (P)", "인분에 보호받아 기술의 추가 효과를 받지 않게 된다."), - Ability(19, "마이페이스", "마이페이스라서 혼란 상태가 되지 않는다."), - Ability(20, "홉반", "흡반으로 지면에 달라붙어 포켓몬을 교체시키는 기술이나 도구의 효과를 발휘하지 못하게 한다."), - Ability(21, "위협", "등장했을 때 위협해서 상대를 위축시켜 상대의 공격을 떨어뜨린다."), - Ability(22, "그림자밝기", "상대의 그림자를 밟아 도망치거나 교체할 수 없게 한다."), - Ability(23, "까칠한피부", "공격을 받았을 때 자신에게 접촉한 상대를 까칠까칠한 피부로 상처를 입힌다."), - Ability(24, "불가사의부적", "효과가 굉장한 기술만 맞는 불가사의한 힘."), + Ability("1", "악취", "악취를 풍겨서 공격했을 때 상대가 풀죽을 때가 있다."), + Ability("2", "잔비", "등장했을 때 날씨를 비로 만든다."), + Ability("3", "가속", "매 턴 스피드가 올라간다."), + Ability("4", "전투무장", "단단한 껍질에 보호받아 상대의 공격이 급소에 맞지 않는다."), + Ability("5", "옹골참", "상대 기술을 받아도 일격으로 쓰러지지 않는다. 일격필살 기술도 효과 없다."), + Ability("6", "유연", "주변을 습하게 함으로써 자폭 등 폭발하는 기술을 아무도 못 쓰게 한다."), + Ability("7", "모래숨기", "모래바람일 때 회피율이 올라간다."), + Ability("8", "정전기", "정전기를 몸에 둘러 접촉한 상대를 마비시킬 때가 있다."), + Ability("9", "축전 (P)", "전기타입의 기술을 받으면 데미지를 받지 않고 회복한다."), + Ability("10", "저수 (P)", "물타입의 기술을 받으면 데미지를 받지 않고 회복한다."), + Ability("11", "둔감", "둔감해서 헤롱헤롱이나 도발 상태가 되지 않는다."), + Ability("12", "날씨부정", "모든 날씨의 영향이 없어진다."), + Ability("13", "복안", "복안을 가지고 있어 기술의 명중률이 올라간다."), + Ability("14", "불면", "잠들지 못하는 체질이라 잠듦 상태가 되지 않는다."), + Ability("15", "변색", "상대에게 받은 기술의 타입으로 자신의 타입이 변화한다."), + Ability("16", "면역", "체내에 면역을 가지고 있어 독 상태가 되지 않는다."), + Ability("17", "타오르는불꽃", "불꽃타입의 기술을 받으면 불꽃을 받아서 자신이 사용하는 불꽃타입의 기술이 강해진다."), + Ability("18", "인분 (P)", "인분에 보호받아 기술의 추가 효과를 받지 않게 된다."), + Ability("19", "마이페이스", "마이페이스라서 혼란 상태가 되지 않는다."), + Ability("20", "홉반", "흡반으로 지면에 달라붙어 포켓몬을 교체시키는 기술이나 도구의 효과를 발휘하지 못하게 한다."), + Ability("21", "위협", "등장했을 때 위협해서 상대를 위축시켜 상대의 공격을 떨어뜨린다."), + Ability("22", "그림자밝기", "상대의 그림자를 밟아 도망치거나 교체할 수 없게 한다."), + Ability("23", "까칠한피부", "공격을 받았을 때 자신에게 접촉한 상대를 까칠까칠한 피부로 상처를 입힌다."), + Ability("24", "불가사의부적", "효과가 굉장한 기술만 맞는 불가사의한 힘."), ) - private val ABILITY_DETAILS: Map = + private val ABILITY_DETAILS: Map = mapOf( - 1L to + "1L" to AbilityDetail( title = "악취", description = "악취를 풍겨서 공격했을 때 상대가 풀죽을 때가 있다.", pokemons = listOf( Pokemon( - id = 1, + id = "1", dexNumber = 1, name = "이상해씨", imageUrl = pokemonImageUrl(pokemonId = 1), @@ -72,14 +72,14 @@ class FakeAbilityRepository : AbilityRepository { ), ), ), - 2L to + "2L" to AbilityDetail( title = "잔비", description = "등장했을 때 날씨를 비로 만든다.", pokemons = listOf( Pokemon( - id = 2, + id = "2", dexNumber = 2, name = "이상해풀", imageUrl = pokemonImageUrl(pokemonId = 2), diff --git a/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeDexRepository.kt b/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeDexRepository.kt index 035821e8..072bc9dc 100644 --- a/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeDexRepository.kt +++ b/android/testing/src/main/java/poke/rogue/helper/testing/data/repository/FakeDexRepository.kt @@ -1,8 +1,11 @@ package poke.rogue.helper.testing.data.repository -import poke.rogue.helper.data.model.Ability +import poke.rogue.helper.data.model.Biome import poke.rogue.helper.data.model.Pokemon +import poke.rogue.helper.data.model.PokemonCategory import poke.rogue.helper.data.model.PokemonDetail +import poke.rogue.helper.data.model.PokemonDetailAbility +import poke.rogue.helper.data.model.PokemonDetailSkills import poke.rogue.helper.data.model.PokemonFilter import poke.rogue.helper.data.model.PokemonGeneration import poke.rogue.helper.data.model.PokemonSkill @@ -27,7 +30,7 @@ class FakeDexRepository : DexRepository { }.toFilteredPokemons(sort, filters) } - override suspend fun pokemonDetail(id: Long): PokemonDetail = DUMMY_POKEMON_DETAIL + override suspend fun pokemonDetail(id: String): PokemonDetail = DUMMY_POKEMON_DETAIL private fun List.toFilteredPokemons( sort: PokemonSort, @@ -57,7 +60,7 @@ class FakeDexRepository : DexRepository { val POKEMONS: List = listOf( Pokemon( - id = 1, + id = "1", dexNumber = 1, name = "이상해씨", imageUrl = pokemonImageUrl(pokemonId = 1), @@ -72,7 +75,7 @@ class FakeDexRepository : DexRepository { speed = 45, ), Pokemon( - id = 2, + id = "2", dexNumber = 2, name = "이상해풀", imageUrl = pokemonImageUrl(pokemonId = 2), @@ -87,7 +90,7 @@ class FakeDexRepository : DexRepository { speed = 60, ), Pokemon( - id = 3, + id = "3", dexNumber = 3, name = "이상해꽃", imageUrl = pokemonImageUrl(pokemonId = 3), @@ -102,7 +105,7 @@ class FakeDexRepository : DexRepository { speed = 525, ), Pokemon( - id = 4, + id = "4", dexNumber = 4, name = "파이리", imageUrl = pokemonImageUrl(pokemonId = 4), @@ -117,7 +120,7 @@ class FakeDexRepository : DexRepository { speed = 65, ), Pokemon( - id = 5, + id = "5", dexNumber = 5, name = "리자드", imageUrl = pokemonImageUrl(pokemonId = 5), @@ -132,7 +135,7 @@ class FakeDexRepository : DexRepository { speed = 80, ), Pokemon( - id = 6, + id = "6", dexNumber = 6, name = "리자몽", imageUrl = pokemonImageUrl(pokemonId = 6), @@ -147,7 +150,7 @@ class FakeDexRepository : DexRepository { speed = 100, ), Pokemon( - id = 7, + id = "7", dexNumber = 7, name = "꼬부기", imageUrl = pokemonImageUrl(pokemonId = 7), @@ -162,7 +165,7 @@ class FakeDexRepository : DexRepository { speed = 43, ), Pokemon( - id = 8, + id = "8", dexNumber = 8, name = "어니부기", imageUrl = pokemonImageUrl(pokemonId = 8), @@ -177,7 +180,7 @@ class FakeDexRepository : DexRepository { speed = 58, ), Pokemon( - id = 9, + id = "9", dexNumber = 9, name = "거북왕", imageUrl = pokemonImageUrl(pokemonId = 9), @@ -192,7 +195,7 @@ class FakeDexRepository : DexRepository { speed = 78, ), Pokemon( - id = 373, + id = "373", dexNumber = 373, name = "보만다", imageUrl = pokemonImageUrl(pokemonId = 373), @@ -211,6 +214,11 @@ class FakeDexRepository : DexRepository { val DUMMY_POKEMON_DETAIL = PokemonDetail( pokemon = Pokemon.DUMMY, + abilities = + listOf( + PokemonDetailAbility("450", "심록", description = "HP가 줄었을 때 풀타입 기술의 위력이 올라간다.", false, false), + PokemonDetailAbility("419", "엽록소", description = "날씨가 맑을 때 스피드가 올라간다.", false, false), + ), stats = listOf( Stat("hp", 45), @@ -221,14 +229,17 @@ class FakeDexRepository : DexRepository { Stat("speed", 45), Stat("total", 318), ), - abilities = - listOf( - Ability(450, "심록", description = "HP가 줄었을 때 풀타입 기술의 위력이 올라간다."), - Ability(419, "엽록소", description = "날씨가 맑을 때 스피드가 올라간다."), + pokemonCategory = PokemonCategory.EMPTY, + evolutions = emptyList(), + skills = + PokemonDetailSkills( + selfLearn = PokemonSkill.FAKE_SELF_LEARN_SKILLS, + tmLearn = PokemonSkill.FAKE_TM_LEARN_SKILLS, + eggLearn = PokemonSkill.FAKE_EGG_LEARN_SKILLS, ), - skills = PokemonSkill.FAKE_SKILLS, - height = 0.7f, - weight = 6.9f, + biomes = Biome.DUMMYS, + height = 0.7, + weight = 6.9, ) } }