-
Notifications
You must be signed in to change notification settings - Fork 2
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
[feat] 나의 단체 뷰 구현 #201
[feat] 나의 단체 뷰 구현 #201
Changes from 12 commits
c06dc52
fc7ae00
5d57c48
edb4951
7ddaad9
d364248
6707090
d3dce46
8cb2205
c293513
acb6eb3
fda97c8
1efd17e
c22fe8c
46574d2
2715e79
74cfc62
7d16745
51dec5d
c36b0d9
45319c2
62b6a15
9924c7c
46cd733
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,33 @@ | ||
package org.sopt.pingle.data.model.remote.response | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import org.sopt.pingle.domain.model.GroupListEntity | ||
|
||
@Serializable | ||
data class ResponseGroupListDto( | ||
@SerialName("id") | ||
val id: Int, | ||
@SerialName("keyword") | ||
val keyword: String, | ||
@SerialName("name") | ||
val name: String, | ||
@SerialName("meetingCount") | ||
val meetingCount: Int, | ||
@SerialName("participantCount") | ||
val participantCount: Int, | ||
@SerialName("isOwner") | ||
val isOwner: Boolean, | ||
@SerialName("code") | ||
val code: String | ||
) { | ||
fun toResponseGroupListEntity() = GroupListEntity( | ||
id = id, | ||
keyword = keyword, | ||
name = name, | ||
meetingCount = meetingCount.toString(), | ||
participantCount = participantCount.toString(), | ||
isOwner = isOwner, | ||
code = code | ||
) | ||
} |
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.sopt.pingle.domain.model | ||
|
||
data class GroupListEntity( | ||
val id: Int, | ||
val keyword: String, | ||
val name: String, | ||
val meetingCount: String, | ||
val participantCount: String, | ||
val isOwner: Boolean, | ||
val code: String | ||
) |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,12 +1,162 @@ | ||||||||||||||||
package org.sopt.pingle.presentation.ui.mygroup | ||||||||||||||||
|
||||||||||||||||
import android.content.ClipData | ||||||||||||||||
import android.content.ClipboardManager | ||||||||||||||||
import android.content.Context | ||||||||||||||||
import android.content.Intent | ||||||||||||||||
import android.os.Bundle | ||||||||||||||||
import android.view.View | ||||||||||||||||
import androidx.activity.OnBackPressedCallback | ||||||||||||||||
import androidx.activity.viewModels | ||||||||||||||||
import dagger.hilt.android.AndroidEntryPoint | ||||||||||||||||
import org.sopt.pingle.R | ||||||||||||||||
import org.sopt.pingle.databinding.ActivityMyGroupBinding | ||||||||||||||||
import org.sopt.pingle.presentation.type.SnackbarType | ||||||||||||||||
import org.sopt.pingle.presentation.ui.onboarding.OnBoardingActivity | ||||||||||||||||
import org.sopt.pingle.util.base.BindingActivity | ||||||||||||||||
import org.sopt.pingle.util.component.AllModalDialogFragment | ||||||||||||||||
import org.sopt.pingle.util.component.PingleSnackbar | ||||||||||||||||
import org.sopt.pingle.util.context.stringOf | ||||||||||||||||
|
||||||||||||||||
@AndroidEntryPoint | ||||||||||||||||
class MyGroupActivity : BindingActivity<ActivityMyGroupBinding>(R.layout.activity_my_group) { | ||||||||||||||||
|
||||||||||||||||
private val viewModel by viewModels<MyGroupViewModel>() | ||||||||||||||||
private lateinit var onBackPressed: OnBackPressedCallback | ||||||||||||||||
|
||||||||||||||||
override fun onCreate(savedInstanceState: Bundle?) { | ||||||||||||||||
super.onCreate(savedInstanceState) | ||||||||||||||||
|
||||||||||||||||
initLayout() | ||||||||||||||||
addListeners() | ||||||||||||||||
onBackPressedBtn() | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
override fun onDestroy() { | ||||||||||||||||
binding.rvMyGroupList.adapter = null | ||||||||||||||||
super.onDestroy() | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun initLayout() { | ||||||||||||||||
checkMyGroupOwner() | ||||||||||||||||
|
||||||||||||||||
with(binding) { | ||||||||||||||||
toolbar.text = getString(R.string.my_group_title) | ||||||||||||||||
// TODO chip 머지되면 text에 localStorage에 저장된 keyword 가져오기 | ||||||||||||||||
tvMyGroupNowName.text = viewModel.getGroupName() | ||||||||||||||||
tvMyGroupNowMeetingCount.text = | ||||||||||||||||
getString(R.string.my_group_meeting_count, viewModel.getGroupMeetingCount()) | ||||||||||||||||
tvMyGroupNowMemberCount.text = | ||||||||||||||||
getString(R.string.my_group_member_count, viewModel.getGroupParticipantCount()) | ||||||||||||||||
|
||||||||||||||||
val adapter = MyGroupAdapter(::showChangeGroupModal) | ||||||||||||||||
rvMyGroupList.adapter = adapter | ||||||||||||||||
adapter.submitList(viewModel.dummyGroupList) | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun addListeners() { | ||||||||||||||||
with(binding) { | ||||||||||||||||
toolbar.ivAllTopbarArrowWithTitleArrowLeft.setOnClickListener { finish() } | ||||||||||||||||
tvMyGroupMoveNewGroup.setOnClickListener { navigateToNewGroupInfo() } | ||||||||||||||||
ivMyGroupNowMenu.setOnClickListener { showMyGroupMenu() } | ||||||||||||||||
root.setOnClickListener { layoutMyGroupMenu.visibility = View.INVISIBLE } | ||||||||||||||||
layoutMyGroupMenuCopy.setOnClickListener { copyGroupCode() } | ||||||||||||||||
layoutMyGroupMenuShare.setOnClickListener { shareGroupCode() } | ||||||||||||||||
} | ||||||||||||||||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun checkMyGroupOwner() { | ||||||||||||||||
with(binding) { | ||||||||||||||||
if (viewModel.getMyGroupIsOwner()) { | ||||||||||||||||
ivMyGroupNowOwner.visibility = View.VISIBLE | ||||||||||||||||
} else { | ||||||||||||||||
ivMyGroupNowOwner.visibility = View.INVISIBLE | ||||||||||||||||
} | ||||||||||||||||
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. 코드가 한줄인경우 대괄호를 빼는게 예쁜거같아요!
Suggested change
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. 이게ㅜㅜ 저도 그렇게 쓰고싶은데 컨트롤 엘이었나 린트였나 돌리면 일케 바뀌더라구요.. if~else문에 braces 없으면 안 좋다 어쩌구 하면서•• 참나!! 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. 저는 가독성 때문에 if, else 괄호 치는게 좋음 ㅋㅋ 개취인듯여 ~~ |
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun showMyGroupMenu() { | ||||||||||||||||
with(binding) { | ||||||||||||||||
if (layoutMyGroupMenu.visibility == View.VISIBLE) { | ||||||||||||||||
layoutMyGroupMenu.visibility = View.INVISIBLE | ||||||||||||||||
} else { | ||||||||||||||||
layoutMyGroupMenu.visibility = View.VISIBLE | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun showChangeGroupModal() { | ||||||||||||||||
// TODO viewModel에서 Entity의 특정 position에 해당하는 값 가져와서 현재 단체랑 위치 바꾸기 | ||||||||||||||||
AllModalDialogFragment( | ||||||||||||||||
title = getString(R.string.my_group_modal_move_question, viewModel.getGroupName()), | ||||||||||||||||
detail = null, | ||||||||||||||||
buttonText = getString(R.string.my_group_modal_change), | ||||||||||||||||
jihyunniiii marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
textButtonText = getString(R.string.my_group_modal_back), | ||||||||||||||||
clickBtn = { chageToNewGroup() }, | ||||||||||||||||
clickTextBtn = { } | ||||||||||||||||
).show(supportFragmentManager, CHANGE_MODAL) | ||||||||||||||||
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. 기존 모달 사용하면 마진이 다르지 않나용? 확인 하셨을까욤?? 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. 넹 확인했서요 AllModalFragment 같은 칭구를 하나 더 만들어서 띄우려구요! 테스트용으로 썼습니둥 |
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun chageToNewGroup() { | ||||||||||||||||
// TODO 서버통신으로 단체 get 해오고 현재 local에 저장된 것과 다른 경우만 리사이클러뷰 데이터로 업데이트 | ||||||||||||||||
|
||||||||||||||||
PingleSnackbar.makeSnackbar( | ||||||||||||||||
view = binding.root, | ||||||||||||||||
message = stringOf(R.string.my_group_snack_bar_chage_group_complete), | ||||||||||||||||
bottomMarin = SNACKBAR_BOTTOM_MARGIN, | ||||||||||||||||
snackbarType = SnackbarType.GUIDE | ||||||||||||||||
) | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun copyGroupCode() { | ||||||||||||||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager | ||||||||||||||||
val clip: ClipData = ClipData.newPlainText(GROUP_CODE_COPY, viewModel.getGroupCode()) | ||||||||||||||||
clipboard.setPrimaryClip(clip) | ||||||||||||||||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
||||||||||||||||
PingleSnackbar.makeSnackbar( | ||||||||||||||||
view = binding.root, | ||||||||||||||||
message = stringOf(R.string.my_group_snack_bar_code_copy_complete), | ||||||||||||||||
bottomMarin = SNACKBAR_BOTTOM_MARGIN, | ||||||||||||||||
snackbarType = SnackbarType.GUIDE | ||||||||||||||||
) | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun shareGroupCode() { | ||||||||||||||||
val intent = Intent(Intent.ACTION_SEND_MULTIPLE) | ||||||||||||||||
with(intent) { | ||||||||||||||||
type = SHARE_TYPE | ||||||||||||||||
// TODO 기획에서 전달해준 템플릿 적용 | ||||||||||||||||
putExtra( | ||||||||||||||||
Intent.EXTRA_TEXT, | ||||||||||||||||
"핑글 앱을 다운받고, ${viewModel.getGroupName()} 사람들을 만나보세요!\n\n$PINGLE_SHARE_CODE ${viewModel.getGroupCode()} \n\n $PINGLE_PLAY_STORE_LINK" | ||||||||||||||||
) | ||||||||||||||||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
} | ||||||||||||||||
startActivity(Intent.createChooser(intent, null)) | ||||||||||||||||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun navigateToNewGroupInfo() { | ||||||||||||||||
Intent(this, OnBoardingActivity::class.java).apply { | ||||||||||||||||
startActivity(this) | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private fun onBackPressedBtn() { | ||||||||||||||||
onBackPressed = object : OnBackPressedCallback(true) { | ||||||||||||||||
override fun handleOnBackPressed() { | ||||||||||||||||
finish() | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
onBackPressedDispatcher.addCallback(this, onBackPressed) | ||||||||||||||||
} | ||||||||||||||||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
|
||||||||||||||||
companion object { | ||||||||||||||||
private const val CHANGE_MODAL = "ChangeGroupModal" | ||||||||||||||||
private const val SNACKBAR_BOTTOM_MARGIN = 57 | ||||||||||||||||
private const val GROUP_CODE_COPY = "CopyGroupCode" | ||||||||||||||||
private const val PINGLE_PLAY_STORE_LINK = | ||||||||||||||||
"앱 링크 : https://play.google.com/store/apps/details?id=org.sopt.pingle&pcampaignid=web_share" | ||||||||||||||||
private const val PINGLE_SHARE_CODE = "초대코드 : " | ||||||||||||||||
private const val SHARE_TYPE = "text/plain" | ||||||||||||||||
} | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package org.sopt.pingle.presentation.ui.mygroup | ||
|
||
import android.view.LayoutInflater | ||
import android.view.ViewGroup | ||
import androidx.recyclerview.widget.ListAdapter | ||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.pingle.databinding.ItemMyGroupBinding | ||
import org.sopt.pingle.databinding.ItemMyGroupOwnerBinding | ||
import org.sopt.pingle.domain.model.GroupListEntity | ||
import org.sopt.pingle.util.view.ItemDiffCallback | ||
|
||
class MyGroupAdapter( | ||
private val groupOnClick: () -> Unit | ||
) : ListAdapter<GroupListEntity, RecyclerView.ViewHolder>( | ||
ItemDiffCallback<GroupListEntity>( | ||
onContentsTheSame = { old, new -> old == new }, | ||
onItemsTheSame = { old, new -> old.id == new.id } | ||
) | ||
) { | ||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||
return when (viewType) { | ||
1 -> MyGroupViewHolder( | ||
ItemMyGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false), | ||
groupOnClick | ||
) | ||
2 -> MyGroupOwnerViewHolder( | ||
ItemMyGroupOwnerBinding.inflate(LayoutInflater.from(parent.context), parent, false), | ||
groupOnClick | ||
) | ||
else -> throw RuntimeException() | ||
HAJIEUN02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||
when (holder) { | ||
is MyGroupViewHolder -> holder.onBind(currentList[position]) | ||
is MyGroupOwnerViewHolder -> holder.onBind(currentList[position]) | ||
} | ||
} | ||
|
||
override fun getItemViewType(position: Int): Int { | ||
return if (currentList[position].isOwner) { | ||
2 | ||
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. 상수화 하는게 좋겠네여 ~~ 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. 넹 반영해서 상수화 했숨다!! |
||
} else { | ||
1 | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.sopt.pingle.presentation.ui.mygroup | ||
|
||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.pingle.databinding.ItemMyGroupOwnerBinding | ||
import org.sopt.pingle.domain.model.GroupListEntity | ||
|
||
class MyGroupOwnerViewHolder( | ||
private val binding: ItemMyGroupOwnerBinding, | ||
private val groupOnClick: () -> Unit | ||
) : | ||
RecyclerView.ViewHolder(binding.root) { | ||
fun onBind(groupListEntity: GroupListEntity) { | ||
with(binding) { | ||
this.groupListEntity = groupListEntity | ||
layoutMyGroupListOwner.setOnClickListener { groupOnClick() } | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.sopt.pingle.presentation.ui.mygroup | ||
|
||
import androidx.recyclerview.widget.RecyclerView | ||
import org.sopt.pingle.databinding.ItemMyGroupBinding | ||
import org.sopt.pingle.domain.model.GroupListEntity | ||
|
||
class MyGroupViewHolder( | ||
private val binding: ItemMyGroupBinding, | ||
private val groupOnClick: () -> Unit | ||
) : | ||
RecyclerView.ViewHolder(binding.root) { | ||
fun onBind(groupListEntity: GroupListEntity) { | ||
with(binding) { | ||
this.groupListEntity = groupListEntity | ||
layoutMyGroupListDefault.setOnClickListener { groupOnClick() } | ||
} | ||
} | ||
} |
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.
오옹,, 이 정보 서버에서 아무것도 안내려주는건가요..? 어느 api에서도,,?
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.
서버에서 내려주는 값이 있고 그거 사용할 수 있다면 너무 많은 정보를 로컬에 저장해놓는건 핸드폰 기종에 따라 약간 무리일수도 ~~
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.
이거 단체 디테일 조회 API 있어서 그거 사용하면 될 듯 합니다 ~
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.
api 연동하면서 로직도 수정하겠습니다! localStorage에는 정말 필요한 정보만 집어넣어두는 걸로 할게욥!!