-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
마이페이지 #74
마이페이지 #74
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage | ||
|
||
interface MyPageActionHandler { | ||
fun navigateToDogDetail() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,43 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage | ||
|
||
import androidx.fragment.app.viewModels | ||
import com.woowacourse.friendogly.R | ||
import com.woowacourse.friendogly.databinding.FragmentMyPageBinding | ||
import com.woowacourse.friendogly.presentation.base.BaseFragment | ||
import com.woowacourse.friendogly.presentation.base.observeEvent | ||
import com.woowacourse.friendogly.presentation.ui.mypage.adapter.DogProfileAdapter | ||
|
||
class MyPageFragment : BaseFragment<FragmentMyPageBinding>(R.layout.fragment_my_page) { | ||
override fun initViewCreated() {} | ||
private val viewModel: MyPageViewModel by viewModels() | ||
|
||
private val adapter: DogProfileAdapter by lazy { DogProfileAdapter(viewModel) } | ||
|
||
override fun initViewCreated() { | ||
initDataBinding() | ||
initAdapter() | ||
initObserve() | ||
} | ||
|
||
private fun initDataBinding() { | ||
binding.vm = viewModel | ||
} | ||
|
||
private fun initAdapter() { | ||
binding.rvDogProfile.adapter = adapter | ||
} | ||
|
||
private fun initObserve() { | ||
viewModel.navigateAction.observeEvent(this) { action -> | ||
when (action) { | ||
is MyPageNavigationAction.NavigateToSetting -> TODO() | ||
is MyPageNavigationAction.NavigateToDogDetail -> TODO() | ||
is MyPageNavigationAction.NavigateToDogRegister -> TODO() | ||
is MyPageNavigationAction.NavigateToProfileEdit -> TODO() | ||
} | ||
} | ||
|
||
viewModel.uiState.observe(viewLifecycleOwner) { uiState -> | ||
adapter.submitList(uiState.dogs) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage | ||
|
||
sealed interface MyPageNavigationAction { | ||
data object NavigateToProfileEdit : MyPageNavigationAction | ||
|
||
data object NavigateToSetting : MyPageNavigationAction | ||
|
||
data object NavigateToDogRegister : MyPageNavigationAction | ||
|
||
data object NavigateToDogDetail : MyPageNavigationAction | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage | ||
|
||
import java.time.LocalDate | ||
|
||
data class MyPageUiState( | ||
val nickname: String = "", | ||
val email: String = "", | ||
val profilePath: String? = null, | ||
val dogs: List<Dog> = emptyList(), | ||
) | ||
|
||
// TODO 더미 데이터 모델 | ||
data class Dog( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ui model인가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
val name: String, | ||
val description: String, | ||
val birthDate: LocalDate, | ||
val sizeType: String, | ||
val gender: String, | ||
val isNeutered: Boolean, | ||
val image: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage | ||
|
||
import androidx.lifecycle.LiveData | ||
import androidx.lifecycle.MutableLiveData | ||
import com.woowacourse.friendogly.presentation.base.BaseViewModel | ||
import com.woowacourse.friendogly.presentation.base.Event | ||
import com.woowacourse.friendogly.presentation.base.emit | ||
import java.time.LocalDate | ||
|
||
class MyPageViewModel : BaseViewModel(), MyPageActionHandler { | ||
private val _uiState: MutableLiveData<MyPageUiState> = MutableLiveData(MyPageUiState()) | ||
val uiState: LiveData<MyPageUiState> get() = _uiState | ||
|
||
private val _navigateAction: MutableLiveData<Event<MyPageNavigationAction>> = | ||
MutableLiveData(null) | ||
val navigateAction: LiveData<Event<MyPageNavigationAction>> get() = _navigateAction | ||
|
||
init { | ||
fetchDummy() | ||
} | ||
|
||
private fun fetchDummy() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fetchDummy에 실패할 경우 or 리스트가 없는 경우에 대한 케이스도 구상되어 있을까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 처리에 대한 이야기를 더 자세히 나눠야할 것 같아 구현하지 않았습니다!! |
||
val state = _uiState.value ?: return | ||
|
||
_uiState.value = | ||
state.copy( | ||
nickname = "손흥민", | ||
email = "[email protected]", | ||
dogs = dogs, | ||
) | ||
} | ||
|
||
fun navigateToDogRegister() { | ||
_navigateAction.emit(MyPageNavigationAction.NavigateToDogRegister) | ||
} | ||
|
||
override fun navigateToDogDetail() { | ||
_navigateAction.emit(MyPageNavigationAction.NavigateToDogDetail) | ||
} | ||
|
||
companion object { | ||
val dog = | ||
Dog( | ||
name = "땡이", | ||
description = "강인해요", | ||
birthDate = LocalDate.now(), | ||
sizeType = "", | ||
gender = "", | ||
isNeutered = true, | ||
image = "https://github.com/user-attachments/assets/9329234e-e47d-4fc5-b4b5-9f2a827b60b1", | ||
) | ||
val dogs = | ||
listOf<Dog>( | ||
dog, | ||
dog.copy( | ||
name = "초코", | ||
image = "https://github.com/user-attachments/assets/a344d355-8b00-4e08-a33f-08db58010b07", | ||
), | ||
dog.copy( | ||
name = "도토리", | ||
image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", | ||
), | ||
dog.copy( | ||
name = "도토리", | ||
image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", | ||
), | ||
dog.copy( | ||
name = "도토리", | ||
image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", | ||
), | ||
dog.copy( | ||
name = "도토리", | ||
image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", | ||
), | ||
dog.copy( | ||
name = "도토리", | ||
image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", | ||
), | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.woowacourse.friendogly.presentation.ui.mypage.adapter | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.DiffUtil | ||
import androidx.recyclerview.widget.ListAdapter | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.woowacourse.friendogly.databinding.ItemDogBinding | ||
import com.woowacourse.friendogly.presentation.ui.mypage.Dog | ||
import com.woowacourse.friendogly.presentation.ui.mypage.MyPageActionHandler | ||
|
||
class DogProfileAdapter( | ||
private val actionHandler: MyPageActionHandler, | ||
) : ListAdapter<Dog, DogProfileAdapter.ViewHolder>(DogItemDiffCallback) { | ||
init { | ||
setHasStableIds(true) | ||
} | ||
|
||
override fun onCreateViewHolder( | ||
parent: ViewGroup, | ||
viewType: Int, | ||
): ViewHolder { | ||
val inflater = LayoutInflater.from(parent.context) | ||
val binding = ItemDogBinding.inflate(inflater, parent, false) | ||
binding.actionHandler = actionHandler | ||
return ViewHolder(binding) | ||
} | ||
|
||
override fun onBindViewHolder( | ||
holder: ViewHolder, | ||
position: Int, | ||
) { | ||
holder.bind(getItem(position)) | ||
} | ||
|
||
class ViewHolder(private val binding: ItemDogBinding) : RecyclerView.ViewHolder(binding.root) { | ||
fun bind(item: Dog) { | ||
binding.dog = item | ||
} | ||
} | ||
|
||
internal object DogItemDiffCallback : DiffUtil.ItemCallback<Dog>() { | ||
override fun areItemsTheSame( | ||
oldItem: Dog, | ||
Comment on lines
+42
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혹시 internal companion object 대신 internal object를 쓰는 이유가 있을까요..? 다들 companion object를 많이 쓰던데 object로 두신 이유가 궁금해요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 멀티모듈이 아닌 시점에서는 수정해야할 것 같습니다!! |
||
newItem: Dog, | ||
): Boolean = oldItem.name == newItem.name | ||
|
||
override fun areContentsTheSame( | ||
oldItem: Dog, | ||
newItem: Dog, | ||
): Boolean = oldItem == newItem | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,27 @@ fun ImageView.bindProfile1000(bitmap: Bitmap?) { | |
.transform(CenterCrop(), RoundedCorners(1000)) | ||
.into(this) | ||
} | ||
|
||
@BindingAdapter("glideProfile1000") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 공용 파일 분리👍 |
||
fun ImageView.bindProfile1000(profilePath: String?) { | ||
if (profilePath == null) { | ||
this.setImageResource(R.drawable.img_dog) | ||
return | ||
} | ||
|
||
Glide.with(context) | ||
.asBitmap() | ||
.load(profilePath) | ||
.transform(CenterCrop(), RoundedCorners(1000)) | ||
.into(this) | ||
} | ||
|
||
@BindingAdapter("urlToImage") | ||
fun ImageView.bindUrlToImage(imageUrl: String?) { | ||
imageUrl?.let { url -> | ||
Glide.with(context) | ||
.load(url) | ||
.centerCrop() | ||
.into(this) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:shape="rectangle"> | ||
|
||
<gradient | ||
android:angle="90" | ||
android:centerColor="#70000000" | ||
android:endColor="#00000000" | ||
android:startColor="#80000000" | ||
android:type="linear" /> | ||
</shape> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<shape xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:shape="rectangle"> | ||
<corners android:radius="16dp" /> | ||
<solid android:color="@color/gray03" /> | ||
</shape> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nickname, email에 default-value 가 있는 다른 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
닉네임과 이메일에 null값이 들어와도 화면에는 보이도록 하기 위해서 위와 같이 구현했는데, 이건 다같이 의논해봐도 좋을 것 같아요!!