Skip to content

Commit f899c96

Browse files
authored
๐Ÿ”€ #26 from boostcampwm-2022/feat/myGroupList
๋‚ด ๊ทธ๋ฃน ํƒญ ์ž„์‹œ ๊ตฌํ˜„
2 parents 48ad778 + e1cc709 commit f899c96

File tree

16 files changed

+356
-10
lines changed

16 files changed

+356
-10
lines changed

โ€Žbuild.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ buildscript {
2323
splashVersion = "1.0.0"
2424
dataStoreVersion = "1.0.0"
2525
viewPager2Version = "1.0.0"
26+
shimmerVersion = "0.5.0"
2627
desugarVersion = "2.0.0"
2728
calendarVersion = "1.0.4"
2829
}

โ€Ždata/src/main/java/com/whyranoid/data/account/AccountRepositoryImpl.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.whyranoid.domain.model.User
44
import com.whyranoid.domain.repository.AccountRepository
55
import javax.inject.Inject
66

7+
// TODO AccountRepositoryImpl ์žฌ๊ตฌํ˜„ ํ•„์š”!! ํ˜„์žฌ๋Š” Fake ์ƒํƒœ
78
class AccountRepositoryImpl @Inject constructor() : AccountRepository {
89
override suspend fun getUser(): Result<User> {
910
return Result.success(User("byeonghee-uid", "๋ณ‘ํฌ", "github.com/bngsh"))

โ€Ždata/src/main/java/com/whyranoid/data/group/GroupRepositoryImpl.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class GroupRepositoryImpl @Inject constructor(
1919
return userDataSource.getMyGroupList(uid)
2020
}
2121

22+
override fun getMyGroupListFlow(uid: String) = userDataSource.getMyGroupListFlow(uid)
23+
2224
override suspend fun updateGroupInfo(
2325
groupId: String,
2426
groupName: String,

โ€Ždata/src/main/java/com/whyranoid/data/user/UserDataSource.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import com.whyranoid.data.model.toGroupInfo
1212
import com.whyranoid.data.model.toRule
1313
import com.whyranoid.data.model.toUser
1414
import com.whyranoid.domain.model.GroupInfo
15+
import kotlinx.coroutines.channels.awaitClose
16+
import kotlinx.coroutines.flow.Flow
17+
import kotlinx.coroutines.flow.callbackFlow
1518
import kotlinx.coroutines.tasks.await
1619
import javax.inject.Inject
1720

@@ -58,4 +61,52 @@ class UserDataSource @Inject constructor(
5861
if (myGroupInfoList.size == 0) throw NO_JOINED_GROUP_EXCEPTION else myGroupInfoList
5962
}
6063
}
64+
65+
// TODO: ์ฝœ๋ฐฑ์„ suspend๋กœ ๋ณ€๊ฒฝ
66+
// TODO: ์˜ˆ์™ธ์ฒ˜๋ฆฌ
67+
fun getMyGroupListFlow(uid: String): Flow<List<GroupInfo>> = callbackFlow {
68+
db.collection(USERS_COLLECTION)
69+
.document(uid)
70+
.addSnapshotListener { documentSnapshot, _ ->
71+
val myGroupInfoList = mutableListOf<GroupInfo>()
72+
val joinedGroupList =
73+
documentSnapshot?.toObject(UserResponse::class.java)?.joinedGroupList
74+
75+
joinedGroupList?.forEach { groupId ->
76+
77+
db.collection(GROUPS_COLLECTION)
78+
.document(groupId)
79+
.get()
80+
.addOnSuccessListener { documentSnapshot ->
81+
82+
val groupInfoResponse =
83+
documentSnapshot.toObject(GroupInfoResponse::class.java)
84+
85+
groupInfoResponse?.let {
86+
db.collection(USERS_COLLECTION)
87+
.document(it.leaderId)
88+
.get()
89+
.addOnSuccessListener { documentSnapshot ->
90+
val leader =
91+
documentSnapshot.toObject(UserResponse::class.java)
92+
?.toUser()
93+
94+
leader?.let {
95+
val groupInfo = groupInfoResponse.toGroupInfo(
96+
leader = leader,
97+
rules = groupInfoResponse.rules.map {
98+
it.toRule()
99+
}
100+
)
101+
myGroupInfoList.add(groupInfo)
102+
trySend(myGroupInfoList)
103+
}
104+
}
105+
}
106+
}
107+
}
108+
}
109+
110+
awaitClose()
111+
}
61112
}

โ€Ždomain/src/main/java/com/whyranoid/domain/repository/GroupRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ interface GroupRepository {
99

1010
suspend fun getMyGroupList(uid: String): Result<List<GroupInfo>>
1111

12+
fun getMyGroupListFlow(uid: String): Flow<List<GroupInfo>>
13+
1214
// ๊ทธ๋ฃน ์ •๋ณด ์ˆ˜์ •, ํ™๋ณด ๊ธ€ ์ˆ˜์ •
1315
suspend fun updateGroupInfo(
1416
groupId: String,

โ€Ždomain/src/main/java/com/whyranoid/domain/usecase/GetMyGroupListUseCase.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,15 @@ package com.whyranoid.domain.usecase
33
import com.whyranoid.domain.model.GroupInfo
44
import com.whyranoid.domain.repository.AccountRepository
55
import com.whyranoid.domain.repository.GroupRepository
6+
import kotlinx.coroutines.flow.Flow
67
import javax.inject.Inject
78

89
class GetMyGroupListUseCase @Inject constructor(
910
private val groupRepository: GroupRepository,
1011
private val accountRepository: AccountRepository
1112
) {
12-
suspend operator fun invoke(): Result<List<GroupInfo>> {
13-
accountRepository.getUid().onSuccess { uid ->
14-
return groupRepository.getMyGroupList(uid)
15-
}.onFailure {
16-
println("UID ์ด์ƒํ•ด ํฌํฌ")
17-
}
18-
return Result.failure(Exception("UID ์ด์ƒํ•ด ํฌํฌ"))
13+
// TODO accountRepository์—์„œ uid๋ฅผ ๋ฐ›์•„์˜จ ํ›„ ๋™์ž‘ํ•˜๋„๋ก ์ˆ˜์ •
14+
operator fun invoke(): Flow<List<GroupInfo>> {
15+
return groupRepository.getMyGroupListFlow("hsjeon")
1916
}
2017
}

โ€Žpresentation/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ dependencies {
7575
// ViewPager2
7676
implementation "androidx.viewpager2:viewpager2:$viewPager2Version"
7777

78+
// shimmer
79+
implementation "com.facebook.shimmer:shimmer:$shimmerVersion"
80+
7881
// Calendar Library
7982
implementation "com.github.kizitonwose:CalendarView:$calendarVersion"
8083
}

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/CommunityItemFragment.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@ package com.whyranoid.presentation.community
33
import android.os.Build
44
import android.os.Bundle
55
import android.view.View
6+
import androidx.core.view.isVisible
67
import androidx.fragment.app.viewModels
8+
import androidx.lifecycle.lifecycleScope
9+
import com.google.android.material.snackbar.Snackbar
710
import com.whyranoid.presentation.R
811
import com.whyranoid.presentation.base.BaseFragment
912
import com.whyranoid.presentation.databinding.FragmentCommunityItemBinding
13+
import com.whyranoid.presentation.util.repeatWhenUiStarted
1014
import dagger.hilt.android.AndroidEntryPoint
15+
import kotlinx.coroutines.launch
1116

1217
@AndroidEntryPoint
1318
internal class CommunityItemFragment :
1419
BaseFragment<FragmentCommunityItemBinding>(R.layout.fragment_community_item) {
1520

1621
private val viewModel: CommunityViewModel by viewModels()
1722

23+
init {
24+
observe()
25+
}
26+
1827
private val category by lazy {
1928
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
2029
arguments?.getSerializable(COMMUNITY_CATEGORY_KEY, CommunityCategory::class.java)
@@ -27,6 +36,60 @@ internal class CommunityItemFragment :
2736

2837
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
2938
super.onViewCreated(view, savedInstanceState)
39+
40+
// TODO : ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„ ๋‹ค๋ฅธ Shimmer Layout ์ƒ์„ฑ
41+
when (category) {
42+
CommunityCategory.BOARD -> {
43+
// TODO: Adapter ์„ค์ •
44+
}
45+
CommunityCategory.MY_GROUP -> {
46+
setMyGroupAdapter()
47+
}
48+
CommunityCategory.MY_POST -> {
49+
// TODO: Adapter ์„ค์ •
50+
}
51+
}
52+
}
53+
54+
private fun observe() {
55+
repeatWhenUiStarted {
56+
viewModel.eventFlow.collect { event ->
57+
handleEvent(event)
58+
}
59+
}
60+
}
61+
62+
private fun handleEvent(event: Event) {
63+
when (event) {
64+
is Event.CategoryItemClick -> {
65+
Snackbar.make(binding.root, "${event.groupInfo.name} ํด๋ฆญ๋จ", Snackbar.LENGTH_SHORT)
66+
.show()
67+
}
68+
}
69+
}
70+
71+
// TODO ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„ ๋‹ค๋ฅธ ์•„์ดํ…œ ์ฒ˜๋ฆฌ
72+
private fun setMyGroupAdapter() {
73+
val adapter = MyGroupAdapter { groupInfo ->
74+
viewModel.onCategoryItemClicked(groupInfo)
75+
}
76+
binding.rvCommunity.adapter = adapter
77+
78+
viewLifecycleOwner.lifecycleScope.launch {
79+
viewModel.getMyGroupListUseCase().collect { groupList ->
80+
removeShimmer()
81+
adapter.submitList(groupList.sortedBy { it.name })
82+
}
83+
}
84+
}
85+
86+
private fun removeShimmer() {
87+
binding.shimmerCommunity.apply {
88+
if (isShimmerStarted) {
89+
stopShimmer()
90+
isVisible = false
91+
}
92+
}
3093
}
3194

3295
companion object {
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
package com.whyranoid.presentation.community
22

33
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import com.whyranoid.domain.model.GroupInfo
6+
import com.whyranoid.domain.usecase.GetMyGroupListUseCase
47
import dagger.hilt.android.lifecycle.HiltViewModel
8+
import kotlinx.coroutines.flow.MutableSharedFlow
9+
import kotlinx.coroutines.flow.SharedFlow
10+
import kotlinx.coroutines.flow.asSharedFlow
11+
import kotlinx.coroutines.launch
512
import javax.inject.Inject
613

714
@HiltViewModel
8-
class CommunityViewModel @Inject constructor() : ViewModel()
15+
class CommunityViewModel @Inject constructor(
16+
val getMyGroupListUseCase: GetMyGroupListUseCase
17+
) : ViewModel() {
18+
19+
private val _eventFlow = MutableSharedFlow<Event>()
20+
val eventFlow: SharedFlow<Event>
21+
get() = _eventFlow.asSharedFlow()
22+
23+
fun onCategoryItemClicked(groupInfo: GroupInfo) {
24+
event(Event.CategoryItemClick(groupInfo))
25+
}
26+
27+
private fun event(event: Event) {
28+
viewModelScope.launch {
29+
_eventFlow.emit(event)
30+
}
31+
}
32+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.whyranoid.presentation.community
2+
3+
import com.whyranoid.domain.model.GroupInfo
4+
5+
sealed class Event {
6+
data class CategoryItemClick(val groupInfo: GroupInfo) : Event()
7+
}

0 commit comments

Comments
ย (0)