diff --git a/app/build.gradle b/app/build.gradle index 1d8daaa2..bf613eab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,4 +108,6 @@ dependencies { implementation Dependencies.workermanager + implementation Dependencies.coil + } \ No newline at end of file diff --git a/app/src/main/java/com/depromeet/housekeeper/adapter/HouseWorkAdapter.kt b/app/src/main/java/com/depromeet/housekeeper/adapter/HouseWorkAdapter.kt index f7ae5943..5683cb4b 100644 --- a/app/src/main/java/com/depromeet/housekeeper/adapter/HouseWorkAdapter.kt +++ b/app/src/main/java/com/depromeet/housekeeper/adapter/HouseWorkAdapter.kt @@ -1,6 +1,7 @@ package com.depromeet.housekeeper.adapter import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.depromeet.housekeeper.databinding.ItemHouseworkBinding @@ -14,6 +15,8 @@ class HouseWorkAdapter( private val onClick: (HouseWork) -> Unit, private val onDone: (HouseWork) -> Unit, ) : RecyclerView.Adapter() { + private var doneHouseWorks : MutableList = mutableListOf() + private fun getTime(houseWork: HouseWork): String { houseWork.scheduledTime?.let { @@ -26,9 +29,11 @@ class HouseWorkAdapter( } ?: return "하루 종일" } - fun updateDate(houseWork: MutableList) { + fun updateDate(remainHouseWork: MutableList, doneHouseWork : MutableList) { list.clear() - list.addAll(houseWork) + list.addAll(remainHouseWork) + list.addAll(doneHouseWork) + doneHouseWorks = doneHouseWork notifyDataSetChanged() } fun callDone(layoutPosition: Int) { @@ -63,6 +68,15 @@ class HouseWorkAdapter( inner class ItemViewHolder(private val binding: ItemHouseworkBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(houseWork: HouseWork) { + if(doneHouseWorks.isNotEmpty()){ + if(doneHouseWorks.first()==houseWork){ + binding.tvTitle.text = String.format("끝낸 집안일 %d" , doneHouseWorks.size) + binding.tvTitle.visibility = View.VISIBLE + } + else binding.tvTitle.visibility = View.GONE + } + else binding.tvTitle.visibility = View.GONE + binding.isOver = when { houseWork.success -> false houseWork.scheduledTime == null -> false @@ -81,10 +95,6 @@ class HouseWorkAdapter( binding.root.setOnClickListener { onClick.invoke(houseWork) } - - /*binding.btDone.setOnClickListener { - onDone.invoke(houseWork) - }*/ val adapter = SmallProfileAdapter(houseWork.assignees.toMutableList()) binding.rvProfileAdapter.adapter = adapter diff --git a/app/src/main/java/com/depromeet/housekeeper/model/SectionHouseWorks.kt b/app/src/main/java/com/depromeet/housekeeper/model/SectionHouseWorks.kt new file mode 100644 index 00000000..0fbd067e --- /dev/null +++ b/app/src/main/java/com/depromeet/housekeeper/model/SectionHouseWorks.kt @@ -0,0 +1,6 @@ +package com.depromeet.housekeeper.model + +data class SectionHouseWorks( + val title : String?, + val list: MutableList +) diff --git a/app/src/main/java/com/depromeet/housekeeper/ui/MainFragment.kt b/app/src/main/java/com/depromeet/housekeeper/ui/MainFragment.kt index 97112d24..72e16ea4 100644 --- a/app/src/main/java/com/depromeet/housekeeper/ui/MainFragment.kt +++ b/app/src/main/java/com/depromeet/housekeeper/ui/MainFragment.kt @@ -33,10 +33,10 @@ import com.depromeet.housekeeper.model.enums.ViewType import com.depromeet.housekeeper.util.SwipeHelperCallback import com.depromeet.housekeeper.util.VerticalItemDecorator import kotlinx.coroutines.flow.collect +import timber.log.Timber import java.text.SimpleDateFormat import java.util.* - class MainFragment : Fragment() { lateinit var binding: FragmentMainBinding @@ -62,7 +62,6 @@ class MainFragment : Fragment() { mainViewModel.apply { getRules() getGroupName() - updateState(MainViewModel.CurrentState.REMAIN) updateSelectDate(getToday()) } @@ -89,15 +88,11 @@ class MainFragment : Fragment() { binding.tvMonth.setOnClickListener { createDatePickerDialog() } - binding.tvRemain.setOnClickListener { - mainViewModel.updateState(MainViewModel.CurrentState.REMAIN) - } - binding.tvEnd.setOnClickListener { - mainViewModel.updateState(MainViewModel.CurrentState.DONE) - } + binding.mainHeader.mainHeaderSettingIv.setOnClickListener { findNavController().navigate(MainFragmentDirections.actionMainFragmentToSettingFragment()) } + binding.lvRule.root.setOnClickListener { findNavController().navigate(MainFragmentDirections.actionMainFragmentToRuleFragment()) } @@ -142,7 +137,7 @@ class MainFragment : Fragment() { val list = mainViewModel.selectHouseWork.value?.houseWorks?.toMutableList() ?: mutableListOf() - houseWorkAdapter = HouseWorkAdapter(list, onClick = { it + houseWorkAdapter = HouseWorkAdapter(list, onClick = { findNavController().navigate( MainFragmentDirections.actionMainFragmentToAddDirectTodoFragment( viewType = ViewType.EDIT, @@ -151,7 +146,7 @@ class MainFragment : Fragment() { ) ) }, { - mainViewModel.updateChoreState(it.houseWorkId) + mainViewModel.updateChoreState(it) } ) binding.rvHouseWork.adapter = houseWorkAdapter @@ -165,7 +160,6 @@ class MainFragment : Fragment() { swipeHelperCallback.removePreviousClamp(binding.rvHouseWork) false } - groupProfileAdapter = GroupProfileAdapter(mainViewModel.groups.value.toMutableList()) { mainViewModel.updateSelectUser(it.memberId) } @@ -180,8 +174,7 @@ class MainFragment : Fragment() { binding.tvCompleteHouseChore.text = getString(R.string.complete_chore_yet) } else -> { - val completeFormat = - String.format(resources.getString(R.string.complete_chore), it) + val completeFormat = String.format(resources.getString(R.string.complete_chore), it) binding.tvCompleteHouseChore.text = getSpannableText( completeFormat, @@ -195,19 +188,13 @@ class MainFragment : Fragment() { lifecycleScope.launchWhenCreated { mainViewModel.selectHouseWork.collect { houseWork -> - houseWork?.let { - binding.isEmptyDone = it.countDone == 0 - binding.isEmptyRemain = it.countLeft == 0 - binding.layoutDoneScreen.root.isVisible = - mainViewModel.currentState.value == MainViewModel.CurrentState.REMAIN && it.countLeft == 0 && it.countDone > 0 + it.countLeft == 0 && it.countDone > 0 binding.layoutEmptyScreen.root.isVisible = (it.countLeft == 0 && it.countDone == 0) - binding.tvRemainBadge.text = it.countLeft.toString() - dayOfAdapter.updateChoreSize(it.countLeft) - binding.tvEndBadge.text = it.countDone.toString() + dayOfAdapter.updateChoreSize(it.countLeft)//TODO 나중에 api 연결할때 수정 binding.layoutEmptyScreen.root.isVisible = houseWork.houseWorks.isEmpty() updateHouseWorkData(houseWork) @@ -218,20 +205,6 @@ class MainFragment : Fragment() { } } - lifecycleScope.launchWhenStarted { - mainViewModel.currentState.collect { - binding.isSelectDone = it == MainViewModel.CurrentState.DONE - binding.isSelectRemain = it == MainViewModel.CurrentState.REMAIN - val houseWork = mainViewModel.selectHouseWork.value ?: return@collect - binding.layoutDoneScreen.root.isVisible = - it == MainViewModel.CurrentState.REMAIN && (houseWork.countLeft == 0 && houseWork.countDone > 0) - - mainViewModel.selectHouseWork.value?.let { - updateHouseWorkData(it) - } - } - } - lifecycleScope.launchWhenStarted { mainViewModel.dayOfWeek.collect { val year = it.date.split("-")[0] @@ -294,87 +267,85 @@ class MainFragment : Fragment() { } private fun updateHouseWorkData(houseWork: HouseWorks) { - val list = when (mainViewModel.currentState.value) { - MainViewModel.CurrentState.REMAIN -> { - houseWork.houseWorks - .filter { !it.success } - .sortedBy { it.scheduledTime } - .toMutableList() - } - else -> { - houseWork.houseWorks - .filter { it.success } - .sortedBy { it.scheduledTime } - .toMutableList() - } - } - houseWorkAdapter?.updateDate(list) + val remainList = + houseWork.houseWorks + .filter { !it.success } + .sortedBy { it.scheduledTime } + .toMutableList() + + val doneList = + houseWork.houseWorks + .filter { it.success } + .sortedBy { it.scheduledTime } + .toMutableList() + + houseWorkAdapter?.updateDate(remainList,doneList) +} + +private fun getCurrentWeek(): MutableList { + val format = SimpleDateFormat("yyyy-MM-dd-EEE", Locale.getDefault()) + val calendar: Calendar = Calendar.getInstance().apply { + set(Calendar.MONTH, this.get(Calendar.MONTH)) + firstDayOfWeek = Calendar.SUNDAY + set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY) } - - private fun getCurrentWeek(): MutableList { - val format = SimpleDateFormat("yyyy-MM-dd-EEE", Locale.getDefault()) - val calendar: Calendar = Calendar.getInstance().apply { - set(Calendar.MONTH, this.get(Calendar.MONTH)) - firstDayOfWeek = Calendar.SUNDAY - set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY) - } - val days = mutableListOf() + val days = mutableListOf() + days.add(format.format(calendar.time)) + repeat(6) { + calendar.add(Calendar.DATE, 1) days.add(format.format(calendar.time)) - repeat(6) { - calendar.add(Calendar.DATE, 1) - days.add(format.format(calendar.time)) - } - return days.map { - DayOfWeek( - date = it, - isSelect = it == format.format(Calendar.getInstance().time) - ) - }.toMutableList() } + return days.map { + DayOfWeek( + date = it, + isSelect = it == format.format(Calendar.getInstance().time) + ) + }.toMutableList() +} + +private fun rvWeekSwipeListener() { + val itemTouchCallback = object : ItemTouchHelper.SimpleCallback( + 0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT + ) { + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean { + return false + } - private fun rvWeekSwipeListener(){ - val itemTouchCallback = object : ItemTouchHelper.SimpleCallback( - 0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean ) { - override fun onMove( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder - ): Boolean { - return false - } - - override fun onChildDraw( - c: Canvas, - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - dX: Float, - dY: Float, - actionState: Int, - isCurrentlyActive: Boolean - ) { - if (actionState == ACTION_STATE_SWIPE) { - val view = binding.rvWeek - val newX = 0.0 // newX 만큼 이동(고정 시 이동 위치/고정 해제 시 이동 위치 결정) - getDefaultUIUtil().onDraw( - c, - recyclerView, - view, - newX.toFloat(), - dY, - actionState, - isCurrentlyActive - ) - } + if (actionState == ACTION_STATE_SWIPE) { + val view = binding.rvWeek + val newX = 0.0 // newX 만큼 이동(고정 시 이동 위치/고정 해제 시 이동 위치 결정) + getDefaultUIUtil().onDraw( + c, + recyclerView, + view, + newX.toFloat(), + dY, + actionState, + isCurrentlyActive + ) } + } - override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - when(direction){ - ItemTouchHelper.LEFT -> dayOfAdapter.updateDate(mainViewModel.getNextWeek()) - ItemTouchHelper.RIGHT -> dayOfAdapter.updateDate(mainViewModel.getLastWeek()) - } + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + when (direction) { + ItemTouchHelper.LEFT -> dayOfAdapter.updateDate(mainViewModel.getNextWeek()) + ItemTouchHelper.RIGHT -> dayOfAdapter.updateDate(mainViewModel.getLastWeek()) } } - ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.rvWeek) } + ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.rvWeek) +} } \ No newline at end of file diff --git a/app/src/main/java/com/depromeet/housekeeper/ui/MainViewModel.kt b/app/src/main/java/com/depromeet/housekeeper/ui/MainViewModel.kt index ec4bc1f0..f848197d 100644 --- a/app/src/main/java/com/depromeet/housekeeper/ui/MainViewModel.kt +++ b/app/src/main/java/com/depromeet/housekeeper/ui/MainViewModel.kt @@ -18,6 +18,8 @@ class MainViewModel : ViewModel() { getCompleteHouseWorkNumber() getGroupName() } + + //캘린더 관련 private val todayCalendar: Calendar = Calendar.getInstance() private var calendar: Calendar = Calendar.getInstance().apply { @@ -26,7 +28,6 @@ class MainViewModel : ViewModel() { set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY) } - private val datePattern = "yyyy-MM-dd-EEE" val format = SimpleDateFormat(datePattern, Locale.getDefault()) @@ -116,22 +117,19 @@ class MainViewModel : ViewModel() { .toMutableList() } + //집안일 관련 private val _completeChoreNum: MutableStateFlow = MutableStateFlow(0) val completeChoreNum: StateFlow get() = _completeChoreNum + //선택된 유저의 집안일 private val _selectHouseWorks: MutableStateFlow = MutableStateFlow(null) val selectHouseWork: StateFlow get() = _selectHouseWorks private val _allHouseWorks: MutableStateFlow> = MutableStateFlow(listOf()) - private val _currentState: MutableStateFlow = - MutableStateFlow(CurrentState.REMAIN) - val currentState: StateFlow - get() = _currentState - private val _networkError: MutableStateFlow = MutableStateFlow(false) val networkError: StateFlow get() = _networkError @@ -145,7 +143,7 @@ class MainViewModel : ViewModel() { val userProfiles: StateFlow> get() = _userProfiles - fun getHouseWorksSize():Int{ + fun getHouseWorksSize(): Int { return _allHouseWorks.value.size } @@ -163,7 +161,7 @@ class MainViewModel : ViewModel() { _allHouseWorks.value.find { it.memberId == _selectUserId.value } } }.onFailure { - // _networkError.value = true + _networkError.value = true } } getCompleteHouseWorkNumber() @@ -173,6 +171,7 @@ class MainViewModel : ViewModel() { _selectHouseWorks.value = _allHouseWorks.value.find { it.memberId == selectUser } } + //이번주에 끝낸 집안일 private fun getCompleteHouseWorkNumber() { val requestFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) viewModelScope.launch { @@ -187,18 +186,14 @@ class MainViewModel : ViewModel() { } } - fun updateState(afterState: CurrentState) { - _currentState.value = afterState - } - - fun updateChoreState(houWorkId: Int) { - val toBeStatus = when (currentState.value) { - CurrentState.REMAIN -> 1 + fun updateChoreState(houseWork: HouseWork) { + val toBeStatus = when (houseWork.success) { + false -> 1 else -> 0 } viewModelScope.launch { Repository.updateChoreState( - houseWorkId = houWorkId, + houseWorkId = houseWork.houseWorkId, updateChoreBody = UpdateChoreBody(toBeStatus) ).runCatching { collect { @@ -285,9 +280,4 @@ class MainViewModel : ViewModel() { } } } - - enum class CurrentState { - REMAIN, - DONE - } } \ No newline at end of file diff --git a/app/src/main/java/com/depromeet/housekeeper/ui/SettingProfileFragment.kt b/app/src/main/java/com/depromeet/housekeeper/ui/SettingProfileFragment.kt index 2eccb58c..063a5ee1 100644 --- a/app/src/main/java/com/depromeet/housekeeper/ui/SettingProfileFragment.kt +++ b/app/src/main/java/com/depromeet/housekeeper/ui/SettingProfileFragment.kt @@ -13,11 +13,10 @@ import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs -import com.bumptech.glide.Glide +import coil.load import com.depromeet.housekeeper.R import com.depromeet.housekeeper.databinding.FragmentSettingProfileBinding import com.depromeet.housekeeper.model.enums.ProfileViewType -import kotlinx.coroutines.flow.collect class SettingProfileFragment : Fragment() { lateinit var binding: FragmentSettingProfileBinding @@ -163,13 +162,16 @@ class SettingProfileFragment : Fragment() { } private fun ImageView.setImg(url: String?) { - Glide.with(binding.ivImageview.context) + /*Glide.with(binding.ivImageview.context) .load(url) .placeholder(R.drawable.bg_profile_imageview_inactive) .error(R.drawable.bg_profile_imageview_inactive) .fitCenter() .override(84, 84) - .into(binding.ivImageview) + .into(binding.ivImageview)*/ + binding.ivImageview.load(url){ + crossfade(true) + } } diff --git a/app/src/main/java/com/depromeet/housekeeper/util/BindingAdapter.kt b/app/src/main/java/com/depromeet/housekeeper/util/BindingAdapter.kt index a11c961c..912a5bae 100644 --- a/app/src/main/java/com/depromeet/housekeeper/util/BindingAdapter.kt +++ b/app/src/main/java/com/depromeet/housekeeper/util/BindingAdapter.kt @@ -6,10 +6,7 @@ import android.text.util.Linkify import android.widget.ImageButton import android.widget.ImageView import android.widget.TextView -import com.bumptech.glide.Glide -import com.bumptech.glide.load.DecodeFormat -import com.bumptech.glide.request.RequestOptions -import com.bumptech.glide.request.target.Target +import coil.load import com.depromeet.housekeeper.R import com.depromeet.housekeeper.model.enums.SignViewType import java.util.regex.Pattern @@ -28,14 +25,17 @@ object BindingAdapter { @androidx.databinding.BindingAdapter("app:loadImage") @JvmStatic fun loadImage(imageView: ImageView, url: String) { - Glide.with(imageView.context) + /*Glide.with(imageView.context) .load(url) .override(Target.SIZE_ORIGINAL) .placeholder(R.drawable.bg_profile_imageview_inactive) .error(R.drawable.bg_profile_imageview_inactive) .format(DecodeFormat.PREFER_ARGB_8888) .fitCenter() - .into(imageView) + .into(imageView)*/ + imageView.load(url){ + crossfade(true) + } } @androidx.databinding.BindingAdapter("app:signViewType") @@ -60,14 +60,19 @@ object BindingAdapter { @androidx.databinding.BindingAdapter("app:imageUrl", "app:placeholder") @JvmStatic fun loadImage(imageView: ImageView, url: String, placeholder: Drawable) { - Glide.with(imageView.context) + /*Glide.with(imageView.context) .load(url) .format(DecodeFormat.PREFER_ARGB_8888) .override(Target.SIZE_ORIGINAL) .placeholder(placeholder) .error(placeholder) .apply(RequestOptions().fitCenter()) - .into(imageView) + .into(imageView)*/ + imageView.load(url){ + placeholder(placeholder) + crossfade(true) + } + } @androidx.databinding.BindingAdapter("app:setLinkify") diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 48bd119c..fbe35d5b 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -11,14 +11,6 @@ name="vm" type="com.depromeet.housekeeper.ui.MainViewModel" /> - - - - @@ -219,101 +211,43 @@ tools:listitem="@layout/item_day_of_week" /> - - - - - - - - + + + + - + android:visibility="gone" /> - - - - - + android:visibility="gone" /> + + + - + + - - - + android:layout_height="wrap_content" + android:orientation="vertical"> + + + - - - - - - - - - - - - - - - - - - - - - - - + android:weightSum="8"> + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_section_recyclerview.xml b/app/src/main/res/layout/item_section_recyclerview.xml new file mode 100644 index 00000000..28ee28c7 --- /dev/null +++ b/app/src/main/res/layout/item_section_recyclerview.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_home_add_chore.xml b/app/src/main/res/layout/layout_home_add_chore.xml index 46a9a117..feec7654 100644 --- a/app/src/main/res/layout/layout_home_add_chore.xml +++ b/app/src/main/res/layout/layout_home_add_chore.xml @@ -33,7 +33,8 @@ + android:layout_height="match_parent" + android:layout_marginHorizontal="24dp"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ba9934bd..4045f38a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,7 +66,7 @@ %s님 이번주에 %s개나 해주셨어요! 아직 집안일을 하지 않으셨네요. - 끝낸 집안일 + 끝낸 집안일 %s 남은 집안일 집안일 추가 해야 할 집안일이 없어요 @@ -79,6 +79,7 @@ 여기를 눌러 하우스의 규칙을 입력해주세요 오늘 완료 + 되돌리기 diff --git a/buildSrc/src/main/kotlin/deptromeet/housekeeper/Dependencies.kt b/buildSrc/src/main/kotlin/deptromeet/housekeeper/Dependencies.kt index 94a71cba..92ac7bfd 100644 --- a/buildSrc/src/main/kotlin/deptromeet/housekeeper/Dependencies.kt +++ b/buildSrc/src/main/kotlin/deptromeet/housekeeper/Dependencies.kt @@ -100,4 +100,8 @@ object Dependencies { private const val WORKER_MANAGER = "2.7.1" const val workermanager = "androidx.work:work-runtime-ktx:$WORKER_MANAGER" + + private const val COIL = "2.1.0" + const val coil = "io.coil-kt:coil:$COIL" + } \ No newline at end of file