Skip to content

Commit

Permalink
[feat] #4 home fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangwook123 committed Apr 13, 2024
1 parent be0f2da commit 5d42716
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
13 changes: 13 additions & 0 deletions feature/home/src/main/java/org/sopt/home/HomeContract.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.sopt.home

import org.sopt.model.Friend

data class HomeState(
val friendList: List<Friend> = emptyList(),
val query: String = "",
)

sealed interface HomeSideEffect{
data class showDeleteDialog(val id: Int): HomeSideEffect
data object showAddFriendBottomSheet: HomeSideEffect
}
86 changes: 86 additions & 0 deletions feature/home/src/main/java/org/sopt/home/HomeFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.sopt.home

import android.os.Bundle
import android.view.View
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ConcatAdapter
import dagger.hilt.android.AndroidEntryPoint
import org.orbitmvi.orbit.viewmodel.observe
import org.sopt.designsystem.dialog.AlertDialogFragment
import org.sopt.home.adapter.HomeAdapter
import org.sopt.home.adapter.HomeHeaderAdapter
import org.sopt.home.add.AddFriendBottomSheetFragment
import org.sopt.home.databinding.FragmentHomeBinding
import org.sopt.model.Friend
import org.sopt.ui.base.BindingFragment

@AndroidEntryPoint
class HomeFragment : BindingFragment<FragmentHomeBinding>({ FragmentHomeBinding.inflate(it) }) {
private lateinit var homeAdapter: HomeAdapter
private lateinit var homeHeaderAdapter: HomeHeaderAdapter
private val viewModel by viewModels<HomeViewModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initAdapter()
initListener()
collectState()
}

private fun initListener() {
binding.etHomeTopSearch.doAfterTextChanged {
viewModel.updateQuery(it.toString())
}
binding.fabHome.setOnClickListener {
viewModel.addFriend()
}
}

private fun collectState() {
viewModel.observe(lifecycleOwner = this, state = ::render, sideEffect = ::handleSideEffect)
}

private fun render(homeState: HomeState) {
homeAdapter.submitList(homeState.friendList)
viewModel.updateQuery(homeState.query)
}

private fun handleSideEffect(sideEffect: HomeSideEffect) {
when (sideEffect) {
HomeSideEffect.showAddFriendBottomSheet -> {
AddFriendBottomSheetFragment.newInstance {
viewModel.insertFriend(it)
}.show(parentFragmentManager, this.tag)
}

is HomeSideEffect.showDeleteDialog -> {
AlertDialogFragment.newInstance(
"삭제?",
"아니요",
"",
{},
{ viewModel.deleteFriend(sideEffect.id) },
).show(parentFragmentManager, this.tag)
}
}
}

private fun initAdapter() {
homeAdapter = HomeAdapter {
viewModel.showDeleteDialog(it.id)
}
homeHeaderAdapter = HomeHeaderAdapter()
homeHeaderAdapter.submitList(
mutableListOf(
Friend(
id = null,
name = "우상욱",
hobby = "안드로이드"
)
)
)
val combineAdapter = ConcatAdapter(homeHeaderAdapter, homeAdapter)
binding.rvHome.adapter = combineAdapter
}

}
74 changes: 74 additions & 0 deletions feature/home/src/main/java/org/sopt/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.sopt.home

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import org.orbitmvi.orbit.Container
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.syntax.simple.intent
import org.orbitmvi.orbit.syntax.simple.postSideEffect
import org.orbitmvi.orbit.syntax.simple.reduce
import org.orbitmvi.orbit.viewmodel.container
import org.sopt.domain.repo.SoptRepository
import org.sopt.domain.usecase.GetSoptUseCase
import org.sopt.model.Friend
import org.sopt.ui.orbit.updateState
import javax.inject.Inject

@OptIn(FlowPreview::class)
@HiltViewModel
class HomeViewModel @Inject constructor(
private val getSoptUseCase: GetSoptUseCase,
private val soptRepository: SoptRepository,
) : ContainerHost<HomeState, HomeSideEffect>, ViewModel() {
override val container: Container<HomeState, HomeSideEffect> = container(HomeState())


init {
observeGetSopt()

viewModelScope.launch {
container.stateFlow.debounce(300)
.filter { it.query.isNotEmpty() || it.query.isBlank() }
.collect {
observeGetSopt()
}
}
}

private fun observeGetSopt() = intent {
viewModelScope.launch {
getSoptUseCase(param = GetSoptUseCase.Param(state.query)).collect {
reduce { state.copy(friendList = it) }
}
}
}

fun addFriend() = intent {
postSideEffect(HomeSideEffect.showAddFriendBottomSheet)
}

fun insertFriend(friend: Friend) = viewModelScope.launch {
soptRepository.addFriend(friend)
}

fun updateQuery(query: String) = updateState {
copy(query = query)
}

fun showDeleteDialog(id: Int?) = intent {
Log.e("이벤트", id.toString())
if (id != null) {
postSideEffect(HomeSideEffect.showDeleteDialog(id))
}
}

fun deleteFriend(id: Int) = viewModelScope.launch {
soptRepository.deleteFriendById(id)
}
}

0 comments on commit 5d42716

Please sign in to comment.