Skip to content

Commit bdf7b19

Browse files
authored
🔀 #30 from boostcampwm-2022/feat/createGroup
그룹 생성하기 페이지 구현 + 컴포즈로 커스텀 Dialog 구현
2 parents 3514959 + c1be73c commit bdf7b19

File tree

19 files changed

+719
-3
lines changed

19 files changed

+719
-3
lines changed

data/src/main/java/com/whyranoid/data/group/GroupDataSource.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import com.whyranoid.data.constant.FieldId.GROUP_MEMBERS_ID
99
import com.whyranoid.data.constant.FieldId.GROUP_NAME
1010
import com.whyranoid.data.constant.FieldId.JOINED_GROUP_LIST
1111
import com.whyranoid.data.constant.FieldId.RULES
12+
import com.whyranoid.data.model.GroupInfoResponse
1213
import com.whyranoid.domain.model.Rule
14+
import kotlinx.coroutines.suspendCancellableCoroutine
15+
import java.util.UUID
1316
import javax.inject.Inject
1417
import kotlin.coroutines.resume
1518
import kotlin.coroutines.suspendCoroutine
@@ -18,6 +21,7 @@ class GroupDataSource @Inject constructor(
1821
private val db: FirebaseFirestore
1922
) {
2023

24+
// TODO: suspendcancellablecoroutine로 변경
2125
suspend fun updateGroupInfo(
2226
groupId: String,
2327
groupName: String,
@@ -45,6 +49,7 @@ class GroupDataSource @Inject constructor(
4549
}
4650
}
4751

52+
// TODO: suspendcancellablecoroutine로 변경
4853
suspend fun joinGroup(uid: String, groupId: String): Boolean {
4954
return suspendCoroutine<Boolean> { continuation ->
5055
db.collection(GROUPS_COLLECTION)
@@ -60,6 +65,7 @@ class GroupDataSource @Inject constructor(
6065
}
6166
}
6267

68+
// TODO: suspendcancellablecoroutine로 변경
6369
suspend fun exitGroup(uid: String, groupId: String): Boolean {
6470
return suspendCoroutine { continuation ->
6571
db.collection(GROUPS_COLLECTION)
@@ -87,4 +93,32 @@ class GroupDataSource @Inject constructor(
8793
}
8894
}
8995
}
96+
97+
// TODO Rule 추가
98+
suspend fun createGroup(
99+
groupName: String,
100+
introduce: String,
101+
rules: List<String>,
102+
uid: String
103+
): Boolean {
104+
return suspendCancellableCoroutine { cancellableContinuation ->
105+
val newGroupId = UUID.randomUUID().toString()
106+
db.collection(GROUPS_COLLECTION)
107+
.document(newGroupId)
108+
.set(
109+
GroupInfoResponse(
110+
groupId = newGroupId,
111+
groupName = groupName,
112+
introduce = introduce,
113+
leaderId = uid,
114+
membersId = listOf(uid),
115+
rules = rules
116+
)
117+
).addOnSuccessListener {
118+
cancellableContinuation.resume(true)
119+
}.addOnFailureListener {
120+
cancellableContinuation.resume(false)
121+
}
122+
}
123+
}
90124
}

data/src/main/java/com/whyranoid/data/group/GroupRepositoryImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@ class GroupRepositoryImpl @Inject constructor(
4545
override suspend fun notifyRunningStart(uid: String, groupIdList: List<String>) {
4646
groupNotificationDataSource.notifyRunningStart(uid, groupIdList)
4747
}
48+
49+
override suspend fun createGroup(groupName: String, introduce: String, rules: List<String>, uid: String): Boolean {
50+
return groupDataSource.createGroup(groupName, introduce, rules, uid)
51+
}
4852
}

domain/src/main/java/com/whyranoid/domain/repository/GroupRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@ interface GroupRepository {
2929
fun getGroupNotifications(groupId: String): Flow<List<GroupNotification>>
3030

3131
suspend fun notifyRunningStart(uid: String, groupIdList: List<String>)
32+
33+
// 그룹 생성하기
34+
suspend fun createGroup(groupName: String, introduce: String, rules: List<String>, uid: String): Boolean
3235
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.whyranoid.domain.usecase
2+
3+
import com.whyranoid.domain.repository.GroupRepository
4+
import javax.inject.Inject
5+
6+
class CreateGroupUseCase @Inject constructor(
7+
private val groupRepository: GroupRepository
8+
) {
9+
// TODO AccountRepository에서 uid를 가져와야함.
10+
suspend operator fun invoke(groupName: String, introduce: String, rules: List<String>): Boolean {
11+
return groupRepository.createGroup(groupName, introduce, rules = rules, uid = "hsjeon")
12+
}
13+
}

presentation/build.gradle

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ plugins {
33
id "org.jetbrains.kotlin.android"
44
id "kotlin-kapt"
55
id "dagger.hilt.android.plugin"
6+
id "androidx.navigation.safeargs.kotlin"
67
}
78

89
android {
@@ -33,6 +34,10 @@ android {
3334
}
3435
buildFeatures {
3536
dataBinding true
37+
compose true
38+
}
39+
composeOptions {
40+
kotlinCompilerExtensionVersion = "1.3.2"
3641
}
3742
}
3843

@@ -77,7 +82,16 @@ dependencies {
7782

7883
// shimmer
7984
implementation "com.facebook.shimmer:shimmer:$shimmerVersion"
80-
85+
8186
// Calendar Library
8287
implementation "com.github.kizitonwose:CalendarView:$calendarVersion"
88+
89+
// composeBom
90+
def composeBom = platform("androidx.compose:compose-bom:2022.10.00")
91+
implementation composeBom
92+
androidTestImplementation composeBom
93+
94+
// or Material Design 2
95+
implementation 'androidx.compose.material:material'
96+
8397
}

presentation/src/main/java/com/whyranoid/presentation/community/CommunityFragment.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package com.whyranoid.presentation.community
22

33
import android.os.Bundle
44
import android.view.View
5+
import androidx.navigation.fragment.findNavController
56
import androidx.viewpager2.adapter.FragmentStateAdapter
7+
import com.google.android.material.tabs.TabLayout
8+
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
69
import com.google.android.material.tabs.TabLayoutMediator
710
import com.whyranoid.presentation.R
811
import com.whyranoid.presentation.base.BaseFragment
@@ -20,8 +23,47 @@ internal class CommunityFragment :
2023

2124
private fun setTabLayout(adapter: FragmentStateAdapter) {
2225
binding.viewPager.adapter = adapter
26+
setOnMenuClickListener()
27+
binding.tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
28+
// TODO 게시글, 내가 쓴 글 추가 필요
29+
override fun onTabSelected(tab: TabLayout.Tab?) {
30+
when (tab?.position) {
31+
CommunityCategory.MY_GROUP.ordinal -> {
32+
binding.topAppBar.inflateMenu(R.menu.my_group_menu)
33+
}
34+
}
35+
}
36+
37+
// TODO 게시글, 내가 쓴 글 추가 필요
38+
override fun onTabUnselected(tab: TabLayout.Tab?) {
39+
when (tab?.position) {
40+
CommunityCategory.MY_GROUP.ordinal -> {
41+
binding.topAppBar.menu.clear()
42+
}
43+
}
44+
}
45+
46+
override fun onTabReselected(tab: TabLayout.Tab?) {
47+
}
48+
})
2349
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
2450
tab.text = getString(CommunityCategory.values()[position].stringId)
2551
}.attach()
2652
}
53+
54+
private fun setOnMenuClickListener() {
55+
binding.topAppBar.setOnMenuItemClickListener { menuItem ->
56+
when (menuItem.itemId) {
57+
R.id.go_to_create_group -> {
58+
val action =
59+
CommunityFragmentDirections.actionCommunityFragmentToCreateGroupFragment()
60+
findNavController().navigate(action)
61+
true
62+
}
63+
else -> {
64+
false
65+
}
66+
}
67+
}
68+
}
2769
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package com.whyranoid.presentation.community.group
2+
3+
import android.os.Bundle
4+
import android.view.View
5+
import androidx.compose.material.MaterialTheme
6+
import androidx.compose.runtime.collectAsState
7+
import androidx.compose.runtime.getValue
8+
import androidx.compose.ui.platform.ViewCompositionStrategy
9+
import androidx.fragment.app.viewModels
10+
import androidx.navigation.fragment.findNavController
11+
import com.google.android.material.snackbar.Snackbar
12+
import com.whyranoid.presentation.R
13+
import com.whyranoid.presentation.base.BaseFragment
14+
import com.whyranoid.presentation.compose.RulePicker
15+
import com.whyranoid.presentation.databinding.FragmentCreateGroupBinding
16+
import com.whyranoid.presentation.util.repeatWhenUiStarted
17+
import dagger.hilt.android.AndroidEntryPoint
18+
19+
@AndroidEntryPoint
20+
internal class CreateGroupFragment :
21+
BaseFragment<FragmentCreateGroupBinding>(R.layout.fragment_create_group) {
22+
23+
private val viewModel: CreateGroupViewModel by viewModels()
24+
25+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
26+
super.onViewCreated(view, savedInstanceState)
27+
28+
binding.viewModel = viewModel
29+
30+
setupMenu()
31+
32+
repeatWhenUiStarted {
33+
viewModel.eventFlow.collect { event ->
34+
handleEvent(event)
35+
}
36+
}
37+
38+
repeatWhenUiStarted {
39+
viewModel.rules.collect {
40+
println("테스트 $it")
41+
}
42+
}
43+
}
44+
45+
private fun handleEvent(event: Event) {
46+
when (event) {
47+
is Event.CreateGroupButtonClick -> {
48+
if (event.isSuccess) {
49+
Snackbar.make(
50+
binding.root,
51+
getString(R.string.text_create_group_success),
52+
Snackbar.LENGTH_SHORT
53+
).show()
54+
findNavController().popBackStack()
55+
} else {
56+
Snackbar.make(
57+
binding.root,
58+
getString(R.string.text_create_group_fail),
59+
Snackbar.LENGTH_SHORT
60+
).show()
61+
}
62+
}
63+
is Event.WarningButtonClick -> {
64+
Snackbar.make(
65+
binding.root,
66+
getString(R.string.text_warning_create_group),
67+
Snackbar.LENGTH_SHORT
68+
).show()
69+
}
70+
is Event.AddRuleButtonClick -> {
71+
binding.composeView.apply {
72+
setViewCompositionStrategy(
73+
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
74+
)
75+
viewModel.onOpenDialogClicked()
76+
setContent {
77+
val showDialogState: Boolean by viewModel.showDialog.collectAsState()
78+
MaterialTheme {
79+
RulePicker(showDialogState, viewModel)
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
87+
private fun setupMenu() {
88+
with(binding.topAppBar) {
89+
inflateMenu(R.menu.create_group_menu)
90+
91+
setOnMenuItemClickListener { menuItem ->
92+
when (menuItem.itemId) {
93+
R.id.create_group_button -> {
94+
viewModel.emitEvent(Event.CreateGroupButtonClick())
95+
true
96+
}
97+
R.id.warning_about_create_group_button -> {
98+
viewModel.emitEvent(Event.WarningButtonClick)
99+
true
100+
}
101+
else -> {
102+
false
103+
}
104+
}
105+
}
106+
}
107+
108+
repeatWhenUiStarted {
109+
viewModel.isButtonEnable.collect { isEnable ->
110+
if (isEnable) {
111+
binding.topAppBar.menu.setGroupVisible(R.id.ready_to_create, true)
112+
binding.topAppBar.menu.setGroupVisible(R.id.not_ready_to_create, false)
113+
} else {
114+
binding.topAppBar.menu.setGroupVisible(R.id.ready_to_create, false)
115+
binding.topAppBar.menu.setGroupVisible(R.id.not_ready_to_create, true)
116+
}
117+
}
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)