Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/src/main/java/com/egobook/app/ui/shop/CustomItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ data class CustomItem(
val type: ItemType,
val price: Price,
val itemStatus: ItemStatus,
val image: ItemImage? = null
val image: ItemImage? = null,
val outfitImage: ItemImage? = null
)

sealed class ItemImage {
data class Url(val path: String): ItemImage()
}
}
29 changes: 18 additions & 11 deletions app/src/main/java/com/egobook/app/ui/shop/ItemAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@ import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.egobook.app.R

class ItemAdapter :
ListAdapter<CustomItem, ItemAdapter.ItemViewHolder>(ItemDiffCallback) {
class ItemAdapter(
private val onItemClick: (CustomItem) -> Unit
) : ListAdapter<CustomItemState, ItemAdapter.ItemViewHolder>(ItemDiffCallback) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ItemViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.view_holder_store_item, parent, false)

return ItemViewHolder(view)
}

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.binding(getItem(position))
holder.root.setOnClickListener {
onItemClick(getItem(position).item)
}
}

class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
Expand All @@ -38,8 +41,8 @@ class ItemAdapter :
val itemImage: ImageView = view.findViewById(R.id.iv_item)
val root: View = view.rootView

fun binding(item: CustomItem) {

fun binding(itemState: CustomItemState) {
val item = itemState.item
item.image?.let { image ->
when(image) {
is ItemImage.Url -> itemImage.load(image.path)
Expand All @@ -56,25 +59,29 @@ class ItemAdapter :
itemStatus.text = "구독전용"
itemInfoLayout.setPadding(24,6,24,6)
itemPriceIcon.visibility = GONE
root.background = null
}
ItemStatus.PURCHASABLE -> {
itemStatus.text = item.price.toString()
itemInfoLayout.updatePadding(left=12, right=16)
itemPriceIcon.visibility = VISIBLE
root.background = null
}
}

if (itemState.isSelected) {
root.setBackgroundResource(R.drawable.store_item_selection_border)
} else {
root.background = null
}
}
}

companion object {
private val ItemDiffCallback = object : DiffUtil.ItemCallback<CustomItem>() {
override fun areItemsTheSame(oldItem: CustomItem, newItem: CustomItem): Boolean {
return oldItem.id == newItem.id // 고유 ID 비교
private val ItemDiffCallback = object : DiffUtil.ItemCallback<CustomItemState>() {
override fun areItemsTheSame(oldItem: CustomItemState, newItem: CustomItemState): Boolean {
return oldItem.item.id == newItem.item.id // 고유 ID 비교
}

override fun areContentsTheSame(oldItem: CustomItem, newItem: CustomItem): Boolean {
override fun areContentsTheSame(oldItem: CustomItemState, newItem: CustomItemState): Boolean {
return oldItem == newItem // 전체 객체 내용 비교
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.egobook.app.ui.shop

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.BundleCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand All @@ -31,13 +32,15 @@ class StoreCollectionFragment(): Fragment() {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewModel: StoreViewModel by viewModels()
val viewModel: StoreViewModel by activityViewModels()
val targetBundle = checkNotNull(arguments) { "구현 오류: 올바른 탭을 표시하기 위해 번들은 필수입니다"}
val tabItem = checkNotNull(BundleCompat.getParcelable(targetBundle, ItemTab.BUNDLE_KEY, ItemTab::class.java)) {
"구현 오류: 올바른 탭을 표시하기 위해 tabItem을 번들을 통해 넘겨야 합니다."
}

val itemAdapter = ItemAdapter()
val itemAdapter = ItemAdapter { customItem ->
viewModel.equipItem(customItem)
}

binding.rvItems.apply {
adapter = itemAdapter
Expand All @@ -46,8 +49,8 @@ class StoreCollectionFragment(): Fragment() {

viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.items.collect { newItems ->
itemAdapter.submitList(newItems)
viewModel.itemStates.collect { newItems ->
itemAdapter.submitList(newItems[tabItem.type])
}
}
}
Expand Down
77 changes: 75 additions & 2 deletions app/src/main/java/com/egobook/app/ui/shop/StoreFragment.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
package com.egobook.app.ui.shop

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.widget.ViewPager2
import coil.load
import com.egobook.app.BlurLevel
import com.egobook.app.R
import com.egobook.app.applyScreenBlur
import com.egobook.app.databinding.FragmentStoreBinding
import com.egobook.app.ui.home.ui.AdDialog
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch

@AndroidEntryPoint
class StoreFragment: Fragment() {
private var _binding: FragmentStoreBinding? = null
private val binding get() = checkNotNull(_binding) { "Fragment가 제거되었습니다." }
private lateinit var viewPager: ViewPager2

private var lastSelected = -1

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -36,16 +46,39 @@ class StoreFragment: Fragment() {
v.setPadding(0, 0, 0, systemBars.bottom)
insets
}

val viewModel: StoreViewModel by activityViewModels()
viewPager = binding.vp2StoreCollectionContainer
viewPager.adapter = StoreCollectionAdapter(this)
val tabLayout = binding.tlTabs
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = ItemTab.of(position).text
}.attach()

viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (position == lastSelected) return
lastSelected = position
viewModel.loadEquippedItems()
Log.d("jang", "페이지 변경 감지됨: $position")
}
})

binding.ivBack.setOnClickListener {
findNavController().navigate(R.id.action_storeFragment_to_homeFragment)
applyScreenBlur(BlurLevel.BASE)
val dialog = StoreLeavingDialog()
dialog.isCancelable = false
dialog.show(parentFragmentManager, "StoreLeavingDialog")
}



viewLifecycleOwner.lifecycleScope.launch {
viewModel.equippedItems.collect { equippedList ->
equippedList.forEach { equippedItem ->
updateEquipItemUi(equippedItem)
}
}
}

}
Expand All @@ -54,6 +87,46 @@ class StoreFragment: Fragment() {
super.onDestroyView()
_binding = null
}

private fun updateEquipItemUi(item: CustomItem) {
binding.ivStoreTurtle.visibility = View.INVISIBLE
when (item.type) {
ItemType.BACK -> {
if (item.outfitImage is ItemImage.Url) {
binding.ivStoreTurtleBack.load(item.outfitImage.path)
}
}
ItemType.SKIN -> {
if (item.outfitImage is ItemImage.Url) {
binding.ivStoreTurtleSkin.load(item.outfitImage.path)
}
}
ItemType.DECO_1 -> {
if (item.outfitImage is ItemImage.Url) {
if(item.outfitImage.path.contains("Default")) {
binding.ivStoreTurtleDeco1.load(null)
return
}
binding.ivStoreTurtleDeco1.load(item.outfitImage.path)
}
}
ItemType.DECO_2 -> {
if (item.outfitImage is ItemImage.Url) {
if(item.outfitImage.path.contains("Default")) {
binding.ivStoreTurtleDeco2.load(null)
return
}
binding.ivStoreTurtleDeco2.load(item.outfitImage.path)
}
}
ItemType.BACKGROUND -> {
if (item.outfitImage is ItemImage.Url) {
binding.ivStoreBackground.load(item.outfitImage.path)
}
}
}
}

}


Expand Down
53 changes: 53 additions & 0 deletions app/src/main/java/com/egobook/app/ui/shop/StoreLeavingDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.egobook.app.ui.shop

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.egobook.app.R
import com.egobook.app.databinding.DialogLeavingStoreBinding
import com.egobook.app.removeScreenBlur

class StoreLeavingDialog: DialogFragment() {
private var _binding: DialogLeavingStoreBinding? = null
private val binding get() = checkNotNull(_binding) { "Fragment가 제거되었습니다." }

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
_binding = DialogLeavingStoreBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val viewModel: StoreViewModel by activityViewModels()
binding.btnRemain.setOnClickListener {
removeScreenBlur()
dismiss()
}


binding.btnLeave.setOnClickListener {
removeScreenBlur()
dismiss()
viewModel.resetEquipItems()
findNavController().navigate(R.id.action_storeFragment_to_homeFragment)
}
}


override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Loading