diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c5050383..e747582f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -57,22 +57,22 @@ android:screenOrientation="portrait" /> @@ -87,67 +87,67 @@ android:screenOrientation="portrait" /> diff --git a/core-ui/src/main/java/com/going/ui/extension/ActivityExt.kt b/core-ui/src/main/java/com/going/ui/extension/ActivityExt.kt new file mode 100644 index 00000000..eb2601d6 --- /dev/null +++ b/core-ui/src/main/java/com/going/ui/extension/ActivityExt.kt @@ -0,0 +1,9 @@ +package com.going.ui.extension + +import android.app.Activity +import androidx.core.content.ContextCompat + +fun Activity.setStatusBarColorFromResource(colorResId: Int) { + val statusBarColor = ContextCompat.getColor(this, colorResId) + window.statusBarColor = statusBarColor +} \ No newline at end of file diff --git a/core-ui/src/main/java/com/going/ui/extension/FragmentExt.kt b/core-ui/src/main/java/com/going/ui/extension/FragmentExt.kt index 6fba2cf3..c2dfd9bb 100644 --- a/core-ui/src/main/java/com/going/ui/extension/FragmentExt.kt +++ b/core-ui/src/main/java/com/going/ui/extension/FragmentExt.kt @@ -29,6 +29,13 @@ fun Fragment.colorOf(@ColorRes resId: Int) = ContextCompat.getColor(requireConte fun Fragment.drawableOf(@DrawableRes resId: Int) = ContextCompat.getDrawable(requireContext(), resId) +fun Fragment.setStatusBarColor(colorResId: Int) { + activity?.let { + val statusBarColor = ContextCompat.getColor(it, colorResId) + it.window.statusBarColor = statusBarColor + } +} + val Fragment.viewLifeCycle get() = viewLifecycleOwner.lifecycle diff --git a/data/src/main/java/com/going/data/datasource/TendencyDataSource.kt b/data/src/main/java/com/going/data/datasource/TendencyDataSource.kt index 320da64e..5fd6a4d2 100644 --- a/data/src/main/java/com/going/data/datasource/TendencyDataSource.kt +++ b/data/src/main/java/com/going/data/datasource/TendencyDataSource.kt @@ -4,5 +4,7 @@ import com.going.data.dto.NonDataBaseResponse import com.going.data.dto.request.TendencyTestRequestDto interface TendencyDataSource { - suspend fun patchTendencyTest(result: TendencyTestRequestDto): NonDataBaseResponse + suspend fun patchTendencyTest( + result: TendencyTestRequestDto + ): NonDataBaseResponse } diff --git a/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt index f356dae7..dd451e03 100644 --- a/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt +++ b/data/src/main/java/com/going/data/datasourceImpl/AuthDataSourceImpl.kt @@ -22,7 +22,9 @@ class AuthDataSourceImpl @Inject constructor( override suspend fun postSignUp( Authorization: String, data: SignUpRequestDto, - ): BaseResponse = authService.postSignUp(Authorization, data) + ): BaseResponse = + authService.postSignUp(Authorization, data) - override suspend fun getSplash(): NonDataBaseResponse = authService.getSplash() + override suspend fun getSplash(): NonDataBaseResponse = + authService.getSplash() } diff --git a/data/src/main/java/com/going/data/datasourceImpl/MockDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/MockDataSourceImpl.kt index 82fb7862..9d82c2ad 100644 --- a/data/src/main/java/com/going/data/datasourceImpl/MockDataSourceImpl.kt +++ b/data/src/main/java/com/going/data/datasourceImpl/MockDataSourceImpl.kt @@ -11,8 +11,7 @@ class MockDataSourceImpl @Inject constructor( override suspend fun getFollowerListData( page: Int - ): MockFollowerResponseDto { - return mockService.getFollowerList(page) - } + ): MockFollowerResponseDto = + mockService.getFollowerList(page) } \ No newline at end of file diff --git a/data/src/main/java/com/going/data/datasourceImpl/SettingDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/SettingDataSourceImpl.kt index af959b78..891d4c05 100644 --- a/data/src/main/java/com/going/data/datasourceImpl/SettingDataSourceImpl.kt +++ b/data/src/main/java/com/going/data/datasourceImpl/SettingDataSourceImpl.kt @@ -8,6 +8,9 @@ import javax.inject.Inject class SettingDataSourceImpl @Inject constructor( private val settingService: SettingService, ) : SettingDataSource { - override suspend fun patchSignOut(): NonDataBaseResponse = settingService.patchSignOut() - override suspend fun deleteWithDraw(): NonDataBaseResponse = settingService.deleteWithDraw() + override suspend fun patchSignOut(): NonDataBaseResponse = + settingService.patchSignOut() + + override suspend fun deleteWithDraw(): NonDataBaseResponse = + settingService.deleteWithDraw() } diff --git a/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt index f5e55515..98397522 100644 --- a/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt +++ b/data/src/main/java/com/going/data/repositoryImpl/AuthRepositoryImpl.kt @@ -35,7 +35,8 @@ class AuthRepositoryImpl @Inject constructor( ).data.toAuthTokenModel() } - override suspend fun getSplash(): Result = runCatching { - authDataSource.getSplash() - } + override suspend fun getSplash(): Result = + runCatching { + authDataSource.getSplash() + } } diff --git a/data/src/main/java/com/going/data/repositoryImpl/EnterTripRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/EnterTripRepositoryImpl.kt index e10fc465..3e9af756 100644 --- a/data/src/main/java/com/going/data/repositoryImpl/EnterTripRepositoryImpl.kt +++ b/data/src/main/java/com/going/data/repositoryImpl/EnterTripRepositoryImpl.kt @@ -19,19 +19,21 @@ class EnterTripRepositoryImpl @Inject constructor( override suspend fun postEnterTrip( requestEnterTripModel: EnterTripRequestModel - ): Result = runCatching { - enterTripDataSource.postEnterTrip( - requestEnterTripModel.toEnterTripRequestDto(), - ).data.toEnterTripModel() - } + ): Result = + runCatching { + enterTripDataSource.postEnterTrip( + requestEnterTripModel.toEnterTripRequestDto(), + ).data.toEnterTripModel() + } override suspend fun postStartInviteTrip( tripId: Long, requestStartInviteTripModel: StartInviteTripRequestModel - ): Result = runCatching { - enterTripDataSource.postStartInviteTrip( - tripId, requestStartInviteTripModel.toStartInviteTripRequestDto(), - ).data.toStartInviteTripModel() - } + ): Result = + runCatching { + enterTripDataSource.postStartInviteTrip( + tripId, requestStartInviteTripModel.toStartInviteTripRequestDto(), + ).data.toStartInviteTripModel() + } override suspend fun postEnterPreferenceTrip( request: EnterPreferenceRequestModel diff --git a/data/src/main/java/com/going/data/repositoryImpl/MockRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/MockRepositoryImpl.kt index 039fa9e4..a32283cc 100644 --- a/data/src/main/java/com/going/data/repositoryImpl/MockRepositoryImpl.kt +++ b/data/src/main/java/com/going/data/repositoryImpl/MockRepositoryImpl.kt @@ -11,10 +11,9 @@ class MockRepositoryImpl @Inject constructor( override suspend fun getFollowerList( page: Int - ): Result> { - return runCatching { + ): Result> = + runCatching { mockDataSource.getFollowerListData(page).toMockFollowerModel() } - } } \ No newline at end of file diff --git a/data/src/main/java/com/going/data/repositoryImpl/ProfileRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/ProfileRepositoryImpl.kt index 8e78739e..1448cef3 100644 --- a/data/src/main/java/com/going/data/repositoryImpl/ProfileRepositoryImpl.kt +++ b/data/src/main/java/com/going/data/repositoryImpl/ProfileRepositoryImpl.kt @@ -1,16 +1,15 @@ package com.going.data.repositoryImpl -import com.going.data.datasource.AuthDataSource import com.going.data.datasource.ProfileDataSource import com.going.domain.entity.request.UserProfileRequestModel -import com.going.domain.repository.AuthRepository import com.going.domain.repository.ProfileRepository import javax.inject.Inject class ProfileRepositoryImpl @Inject constructor( private val profileDataSource: ProfileDataSource ) : ProfileRepository { - override suspend fun getUserProfile(): Result = runCatching { - profileDataSource.getUserProfile().data.toProfileModel() - } + override suspend fun getUserProfile(): Result = + runCatching { + profileDataSource.getUserProfile().data.toProfileModel() + } } diff --git a/data/src/main/java/com/going/data/repositoryImpl/SettingRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/SettingRepositoryImpl.kt index 501963d1..3e85a0e2 100644 --- a/data/src/main/java/com/going/data/repositoryImpl/SettingRepositoryImpl.kt +++ b/data/src/main/java/com/going/data/repositoryImpl/SettingRepositoryImpl.kt @@ -7,11 +7,13 @@ import javax.inject.Inject class SettingRepositoryImpl @Inject constructor( private val settingDataSource: SettingDataSource, ) : SettingRepository { - override suspend fun patchSignOut(): Result = runCatching { - settingDataSource.patchSignOut() - } + override suspend fun patchSignOut(): Result = + runCatching { + settingDataSource.patchSignOut() + } - override suspend fun deleteWithDraw(): Result = runCatching { - settingDataSource.deleteWithDraw() - } + override suspend fun deleteWithDraw(): Result = + runCatching { + settingDataSource.deleteWithDraw() + } } diff --git a/domain/src/main/kotlin/com/going/domain/repository/EnterTripRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/EnterTripRepository.kt index 6338fdca..a41d2880 100644 --- a/domain/src/main/kotlin/com/going/domain/repository/EnterTripRepository.kt +++ b/domain/src/main/kotlin/com/going/domain/repository/EnterTripRepository.kt @@ -9,12 +9,12 @@ import com.going.domain.entity.response.StartInviteTripModel interface EnterTripRepository { suspend fun postEnterTrip( - requestEnterTripModel: EnterTripRequestModel + request: EnterTripRequestModel ): Result suspend fun postStartInviteTrip( tripId: Long, - requestStartInviteTripModel: StartInviteTripRequestModel + request: StartInviteTripRequestModel ): Result suspend fun postEnterPreferenceTrip( diff --git a/domain/src/main/kotlin/com/going/domain/repository/TendencyRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/TendencyRepository.kt index 41b1ec5e..19cabb43 100644 --- a/domain/src/main/kotlin/com/going/domain/repository/TendencyRepository.kt +++ b/domain/src/main/kotlin/com/going/domain/repository/TendencyRepository.kt @@ -3,5 +3,7 @@ package com.going.domain.repository import com.going.domain.entity.request.TendencyRequestModel interface TendencyRepository { - suspend fun patchTendencyTest(result: TendencyRequestModel): Result + suspend fun patchTendencyTest( + result: TendencyRequestModel + ): Result } diff --git a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt index d1efac09..324be034 100644 --- a/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt +++ b/presentation/src/main/java/com/going/presentation/onboarding/splash/SplashActivity.kt @@ -15,6 +15,7 @@ import com.going.presentation.databinding.ActivitySplashBinding import com.going.presentation.onboarding.signin.SignInActivity import com.going.presentation.tendency.splash.TendencySplashActivity import com.going.ui.base.BaseActivity +import com.going.ui.extension.setStatusBarColorFromResource import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -26,11 +27,16 @@ class SplashActivity : BaseActivity(R.layout.activity_spl override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setStatusBarColor() checkConnectedNetwork() observeUserState() } + private fun setStatusBarColor() { + setStatusBarColorFromResource(R.color.red_500) + } + private fun checkConnectedNetwork() { if (NetworkManager.checkNetworkState(this)) { initSplash() diff --git a/presentation/src/main/java/com/going/presentation/todo/TodoActivity.kt b/presentation/src/main/java/com/going/presentation/todo/TodoActivity.kt index 7e7f9220..caa67a8d 100644 --- a/presentation/src/main/java/com/going/presentation/todo/TodoActivity.kt +++ b/presentation/src/main/java/com/going/presentation/todo/TodoActivity.kt @@ -9,6 +9,7 @@ import com.going.presentation.databinding.ActivityTodoBinding import com.going.presentation.todo.mytodo.MyTodoFragment import com.going.presentation.todo.ourtodo.OurTodoFragment import com.going.ui.base.BaseActivity +import com.going.ui.extension.setStatusBarColorFromResource import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -19,11 +20,16 @@ class TodoActivity() : BaseActivity(R.layout.activity_todo) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setStatusBarColor() getTripId() initBnvItemIconTintList() initBnvItemSelectedListener() } + private fun setStatusBarColor() { + setStatusBarColorFromResource(R.color.gray_50) + } + private fun getTripId() { if (intent != null) { tripId = intent.getLongExtra(EXTRA_TRIP_ID, 0) diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoDecoration.kt b/presentation/src/main/java/com/going/presentation/todo/TodoDecoration.kt similarity index 57% rename from presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoDecoration.kt rename to presentation/src/main/java/com/going/presentation/todo/TodoDecoration.kt index f44012d2..0d079aa6 100644 --- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoDecoration.kt +++ b/presentation/src/main/java/com/going/presentation/todo/TodoDecoration.kt @@ -1,11 +1,17 @@ -package com.going.presentation.todo.ourtodo +package com.going.presentation.todo import android.content.Context import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView -class OurTodoDecoration(val context: Context) : RecyclerView.ItemDecoration() { +class TodoDecoration( + val context: Context, + private val top: Int, + private val left: Int, + private val right: Int, + private val bottom: Int + ) : RecyclerView.ItemDecoration() { override fun getItemOffsets( outRect: Rect, @@ -17,7 +23,10 @@ class OurTodoDecoration(val context: Context) : RecyclerView.ItemDecoration() { val position = parent.getChildAdapterPosition(view) if (position == parent.adapter?.itemCount?.minus(1)) { - outRect.right = 150 + outRect.top = top + outRect.left = left + outRect.right = right + outRect.bottom = bottom } } } diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoFragment.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoFragment.kt index 147687c9..25bd976b 100644 --- a/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoFragment.kt @@ -6,6 +6,7 @@ import android.text.SpannableStringBuilder import android.text.Spanned import android.text.style.ForegroundColorSpan import android.view.View +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle @@ -21,6 +22,7 @@ import com.going.ui.base.BaseFragment import com.going.ui.extension.UiState import com.going.ui.extension.setOnSingleClickListener import com.going.ui.extension.toast +import com.google.android.material.appbar.AppBarLayout import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn @@ -138,6 +140,17 @@ class MyTodoFragment() : BaseFragment(R.layout.fragment_m } } + + fun setAppbarDragAvailable(isAvailable: Boolean) { + binding.appbarMyTodo + val params = binding.appbarMyTodo.layoutParams as CoordinatorLayout.LayoutParams + val behavior = params.behavior as AppBarLayout.Behavior + + behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() { + override fun canDrag(appBarLayout: AppBarLayout): Boolean = isAvailable + }) + } + companion object { const val TAB_UNCOMPLETE = "해야 해요" const val TAB_COMPLETE = "완료했어요" diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoViewModel.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoViewModel.kt index d7850499..43eeb45a 100644 --- a/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoViewModel.kt +++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/MyTodoViewModel.kt @@ -36,7 +36,7 @@ class MyTodoViewModel @Inject constructor( private val _todoRedoState = MutableStateFlow(EnumUiState.EMPTY) val todoRedoState: StateFlow = _todoRedoState - var tripId : Long = 0 + var tripId: Long = 0 var participantId: Long = 9 fun increaseTodoCount() { @@ -62,8 +62,12 @@ class MyTodoViewModel @Inject constructor( viewModelScope.launch { todoRepository.getTodoList(tripId, category, progress) .onSuccess { response -> - _todoUncompleteListState.value = UiState.Success(response) _totalUncompletedTodoCount.value = response.size + if (response.isEmpty()) { + _todoUncompleteListState.value = UiState.Empty + } else { + _todoUncompleteListState.value = UiState.Success(response) + } } .onFailure { _todoUncompleteListState.value = UiState.Failure(it.message.orEmpty()) @@ -76,7 +80,11 @@ class MyTodoViewModel @Inject constructor( viewModelScope.launch { todoRepository.getTodoList(tripId, category, progress) .onSuccess { response -> - _todoCompleteListState.value = UiState.Success(response) + if (response.isEmpty()) { + _todoCompleteListState.value = UiState.Empty + } else { + _todoCompleteListState.value = UiState.Success(response) + } } .onFailure { _todoCompleteListState.value = UiState.Failure(it.message.orEmpty()) diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt index 5c4770f5..1c3158e0 100644 --- a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt @@ -3,14 +3,17 @@ package com.going.presentation.todo.mytodo.todolist import android.content.Intent import android.os.Bundle import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.going.presentation.R import com.going.presentation.databinding.FragmentMyTodoCompleteBinding +import com.going.presentation.todo.TodoDecoration import com.going.presentation.todo.detail.PrivateDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity.Companion.EXTRA_TODO_ID +import com.going.presentation.todo.mytodo.MyTodoFragment import com.going.presentation.todo.mytodo.MyTodoViewModel import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.COMPLETE import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.MY_TODO @@ -36,6 +39,7 @@ class MyTodoCompleteFragment() : super.onViewCreated(view, savedInstanceState) initAdapterWithClickListener() + initItemDecoration() observeTodoListState() observeTodoRedoState() } @@ -62,6 +66,11 @@ class MyTodoCompleteFragment() : binding.rvMyTodoComplete.adapter = adapter } + private fun initItemDecoration() { + val itemDeco = TodoDecoration(requireContext(),0,0,0,30) + binding.rvMyTodoComplete.addItemDecoration(itemDeco) + } + private fun startDetailActivity(targetActivity: Class<*>, todoId: Long) { Intent(activity, targetActivity).apply { putExtra(EXTRA_TODO_ID, todoId) @@ -76,17 +85,29 @@ class MyTodoCompleteFragment() : private fun observeTodoListState() { viewModel.todoCompleteListState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { - is UiState.Success -> adapter.submitList(state.data) + is UiState.Success -> { + setLayoutEmpty(false) + adapter.submitList(state.data) + } - is UiState.Failure -> toast(getString(R.string.server_error)) + is UiState.Failure -> { + setLayoutEmpty(true) + toast(getString(R.string.server_error)) + } is UiState.Loading -> return@onEach - is UiState.Empty -> return@onEach + is UiState.Empty -> setLayoutEmpty(true) } }.launchIn(lifecycleScope) } + private fun setLayoutEmpty(isEmpty: Boolean) { + binding.rvMyTodoComplete.isVisible = !isEmpty + binding.layoutMyTodoCompleteEmpty.isVisible = isEmpty + (parentFragment as MyTodoFragment).setAppbarDragAvailable(!isEmpty) + } + private fun observeTodoRedoState() { viewModel.todoRedoState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt index 566cf44d..d5cc3e82 100644 --- a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt @@ -4,17 +4,20 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.going.presentation.R import com.going.presentation.databinding.FragmentMyTodoUncompleteBinding -import com.going.presentation.todo.mytodo.MyTodoViewModel -import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.MY_TODO -import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.UNCOMPLETE +import com.going.presentation.todo.TodoDecoration import com.going.presentation.todo.detail.PrivateDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity.Companion.EXTRA_TODO_ID +import com.going.presentation.todo.mytodo.MyTodoFragment +import com.going.presentation.todo.mytodo.MyTodoViewModel +import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.MY_TODO +import com.going.presentation.todo.mytodo.MyTodoViewModel.Companion.UNCOMPLETE import com.going.ui.base.BaseFragment import com.going.ui.extension.EnumUiState import com.going.ui.extension.UiState @@ -55,9 +58,17 @@ class MyTodoUncompleteFragment() : { }, { todoModel -> if (todoModel.allocators.size <= 1) { - startDetailActivity(activity, PrivateDetailActivity::class.java, todoModel.todoId) + startDetailActivity( + activity, + PrivateDetailActivity::class.java, + todoModel.todoId + ) } else { - startDetailActivity(activity, PublicDetailActivity::class.java, todoModel.todoId) + startDetailActivity( + activity, + PublicDetailActivity::class.java, + todoModel.todoId + ) } }) binding.rvMyTodoUncomplete.adapter = adapter @@ -77,17 +88,36 @@ class MyTodoUncompleteFragment() : private fun observeTodoListState() { viewModel.todoUncompleteListState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { - is UiState.Success -> adapter.submitList(state.data) + is UiState.Success -> { + setLayoutEmpty(false) + adapter.submitList(state.data) + setItemDecoration() + } - is UiState.Failure -> toast(getString(R.string.server_error)) + is UiState.Failure -> { + setLayoutEmpty(true) + toast(getString(R.string.server_error)) + } is UiState.Loading -> return@onEach - is UiState.Empty -> return@onEach + is UiState.Empty -> setLayoutEmpty(true) } }.launchIn(lifecycleScope) } + private fun setLayoutEmpty(isEmpty: Boolean) { + binding.rvMyTodoUncomplete.isVisible = !isEmpty + binding.layoutMyTodoUncompleteEmpty.isVisible = isEmpty + (parentFragment as MyTodoFragment).setAppbarDragAvailable(!isEmpty) + } + + private fun setItemDecoration() { + val itemDeco = TodoDecoration(requireContext(),0,0,0,30) + if (binding.rvMyTodoUncomplete.itemDecorationCount > 0) binding.rvMyTodoUncomplete.removeItemDecoration(itemDeco) + binding.rvMyTodoUncomplete.addItemDecoration(itemDeco) + } + private fun observeTodoFinishState() { viewModel.todoFinishState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt index 99cf9453..33d82b24 100644 --- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt @@ -6,6 +6,7 @@ import android.text.SpannableStringBuilder import android.text.Spanned import android.text.style.ForegroundColorSpan import android.view.View +import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle @@ -13,6 +14,7 @@ import androidx.lifecycle.lifecycleScope import com.going.domain.entity.response.TripParticipantModel import com.going.presentation.R import com.going.presentation.databinding.FragmentOurTodoBinding +import com.going.presentation.todo.TodoDecoration import com.going.presentation.todo.TodoActivity.Companion.EXTRA_TRIP_ID import com.going.presentation.todo.ourtodo.checkfriends.CheckFriendsActivity import com.going.presentation.todo.ourtodo.create.OurTodoCreateActivity @@ -25,6 +27,7 @@ import com.going.ui.base.BaseFragment import com.going.ui.extension.UiState import com.going.ui.extension.setOnSingleClickListener import com.going.ui.extension.toast +import com.google.android.material.appbar.AppBarLayout import com.google.android.material.tabs.TabLayoutMediator import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.launchIn @@ -81,7 +84,7 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment } private fun initItemDecoration() { - val itemDeco = OurTodoDecoration(requireContext()) + val itemDeco = TodoDecoration(requireContext(),0,0,150,0) binding.rvOurTripFriend.addItemDecoration(itemDeco) } @@ -199,6 +202,16 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment } } + fun setAppbarDragAvailable(isAvailable: Boolean) { + binding.appbarOurTodo + val params = binding.appbarOurTodo.layoutParams as CoordinatorLayout.LayoutParams + val behavior = params.behavior as AppBarLayout.Behavior + + behavior.setDragCallback(object : AppBarLayout.Behavior.DragCallback() { + override fun canDrag(appBarLayout: AppBarLayout): Boolean = isAvailable + }) + } + override fun onDestroyView() { super.onDestroyView() _adapter = null diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoViewModel.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoViewModel.kt index d0a3dca2..807aa079 100644 --- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoViewModel.kt +++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoViewModel.kt @@ -53,7 +53,11 @@ class OurTodoViewModel @Inject constructor( viewModelScope.launch { todoRepository.getTodoList(tripId, category, progress) .onSuccess { response -> - todoListState.value = UiState.Success(response) + if (response.isEmpty()) { + todoListState.value = UiState.Empty + } else { + todoListState.value = UiState.Success(response) + } } .onFailure { todoListState.value = UiState.Failure(it.message.orEmpty()) diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt index 8b2f1c97..6b06f417 100644 --- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt @@ -3,16 +3,19 @@ package com.going.presentation.todo.ourtodo.todolist import android.content.Intent import android.os.Bundle import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.going.presentation.R import com.going.presentation.databinding.FragmentOurTodoCompleteBinding +import com.going.presentation.todo.TodoDecoration import com.going.presentation.todo.ourtodo.OurTodoViewModel import com.going.presentation.todo.ourtodo.OurTodoViewModel.Companion.COMPLETE import com.going.presentation.todo.ourtodo.OurTodoViewModel.Companion.OUR_TODO import com.going.presentation.todo.detail.PublicDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity.Companion.EXTRA_TODO_ID +import com.going.presentation.todo.ourtodo.OurTodoFragment import com.going.ui.base.BaseFragment import com.going.ui.extension.UiState import com.going.ui.extension.toast @@ -34,6 +37,7 @@ class OurTodoCompleteFragment() : super.onViewCreated(view, savedInstanceState) initAdapterWithClickListener() + initItemDecoration() setTodoList() observeTodoListState() } @@ -50,6 +54,11 @@ class OurTodoCompleteFragment() : binding.rvOurTodoComplete.adapter = adapter } + private fun initItemDecoration() { + val itemDeco = TodoDecoration(requireContext(),0,0,0,30) + binding.rvOurTodoComplete.addItemDecoration(itemDeco) + } + private fun setTodoList() { viewModel.getTodoListFromServer(OUR_TODO, COMPLETE) } @@ -57,17 +66,29 @@ class OurTodoCompleteFragment() : private fun observeTodoListState() { viewModel.todoCompleteListState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { - is UiState.Success -> adapter.submitList(state.data) + is UiState.Success -> { + setLayoutEmpty(false) + adapter.submitList(state.data) + } - is UiState.Failure -> toast(getString(R.string.server_error)) + is UiState.Failure -> { + setLayoutEmpty(true) + toast(getString(R.string.server_error)) + } is UiState.Loading -> return@onEach - is UiState.Empty -> return@onEach + is UiState.Empty -> setLayoutEmpty(true) } }.launchIn(lifecycleScope) } + private fun setLayoutEmpty(isEmpty: Boolean) { + binding.rvOurTodoComplete.isVisible = !isEmpty + binding.layoutOurTodoCompleteEmpty.isVisible = isEmpty + (parentFragment as OurTodoFragment).setAppbarDragAvailable(!isEmpty) + } + override fun onDestroyView() { super.onDestroyView() _adapter = null diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt index d29385a1..e572cebd 100644 --- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt +++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt @@ -3,16 +3,19 @@ package com.going.presentation.todo.ourtodo.todolist import android.content.Intent import android.os.Bundle import android.view.View +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.going.presentation.R import com.going.presentation.databinding.FragmentOurTodoUncompleteBinding +import com.going.presentation.todo.TodoDecoration import com.going.presentation.todo.ourtodo.OurTodoViewModel import com.going.presentation.todo.ourtodo.OurTodoViewModel.Companion.OUR_TODO import com.going.presentation.todo.ourtodo.OurTodoViewModel.Companion.UNCOMPLETE import com.going.presentation.todo.detail.PublicDetailActivity import com.going.presentation.todo.detail.PublicDetailActivity.Companion.EXTRA_TODO_ID +import com.going.presentation.todo.ourtodo.OurTodoFragment import com.going.ui.base.BaseFragment import com.going.ui.extension.UiState import com.going.ui.extension.toast @@ -34,7 +37,7 @@ class OurTodoUncompleteFragment() : super.onViewCreated(view, savedInstanceState) initAdapterWithClickListener() - setTodoList() + initItemDecoration() observeTodoListState() } @@ -56,6 +59,11 @@ class OurTodoUncompleteFragment() : binding.rvOurTodoUncomplete.adapter = adapter } + private fun initItemDecoration() { + val itemDeco = TodoDecoration(requireContext(),0,0,0,30) + binding.rvOurTodoUncomplete.addItemDecoration(itemDeco) + } + private fun setTodoList() { viewModel.getTodoListFromServer(OUR_TODO, UNCOMPLETE) } @@ -63,17 +71,29 @@ class OurTodoUncompleteFragment() : private fun observeTodoListState() { viewModel.todoUncompleteListState.flowWithLifecycle(lifecycle).onEach { state -> when (state) { - is UiState.Success -> adapter.submitList(state.data) + is UiState.Success -> { + setLayoutEmpty(false) + adapter.submitList(state.data) + } - is UiState.Failure -> toast(getString(R.string.server_error)) + is UiState.Failure -> { + setLayoutEmpty(true) + toast(getString(R.string.server_error)) + } is UiState.Loading -> return@onEach - is UiState.Empty -> return@onEach + is UiState.Empty -> setLayoutEmpty(true) } }.launchIn(lifecycleScope) } + private fun setLayoutEmpty(isEmpty: Boolean) { + binding.rvOurTodoUncomplete.isVisible = !isEmpty + binding.layoutOurTodoUncompleteEmpty.isVisible = isEmpty + (parentFragment as OurTodoFragment).setAppbarDragAvailable(!isEmpty) + } + override fun onDestroyView() { super.onDestroyView() _adapter = null diff --git a/presentation/src/main/res/drawable/img_mytodo_empty.xml b/presentation/src/main/res/drawable/img_mytodo_empty.xml new file mode 100644 index 00000000..a18f0fe0 --- /dev/null +++ b/presentation/src/main/res/drawable/img_mytodo_empty.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/presentation/src/main/res/drawable/img_ourtodo_empty.xml b/presentation/src/main/res/drawable/img_ourtodo_empty.xml new file mode 100644 index 00000000..12ad5f3c --- /dev/null +++ b/presentation/src/main/res/drawable/img_ourtodo_empty.xml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/presentation/src/main/res/layout/fragment_my_todo.xml b/presentation/src/main/res/layout/fragment_my_todo.xml index 32c4ea5b..a7a383c0 100644 --- a/presentation/src/main/res/layout/fragment_my_todo.xml +++ b/presentation/src/main/res/layout/fragment_my_todo.xml @@ -33,7 +33,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - + app:contentScrim="@android:color/transparent" + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:statusBarScrim="@android:color/transparent"> + + + + diff --git a/presentation/src/main/res/layout/fragment_my_todo_complete.xml b/presentation/src/main/res/layout/fragment_my_todo_complete.xml index 71476aed..52a0b137 100644 --- a/presentation/src/main/res/layout/fragment_my_todo_complete.xml +++ b/presentation/src/main/res/layout/fragment_my_todo_complete.xml @@ -15,18 +15,54 @@ + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/fragment_my_todo_uncomplete.xml b/presentation/src/main/res/layout/fragment_my_todo_uncomplete.xml index 4d934d35..c58919f1 100644 --- a/presentation/src/main/res/layout/fragment_my_todo_uncomplete.xml +++ b/presentation/src/main/res/layout/fragment_my_todo_uncomplete.xml @@ -10,23 +10,59 @@ + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/fragment_our_todo.xml b/presentation/src/main/res/layout/fragment_our_todo.xml index adcf15af..5363ed98 100644 --- a/presentation/src/main/res/layout/fragment_our_todo.xml +++ b/presentation/src/main/res/layout/fragment_our_todo.xml @@ -51,11 +51,11 @@ android:background="@color/gray_50"> @@ -292,18 +292,28 @@ - + app:contentScrim="@android:color/transparent" + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:statusBarScrim="@android:color/transparent"> + + + + diff --git a/presentation/src/main/res/layout/fragment_our_todo_complete.xml b/presentation/src/main/res/layout/fragment_our_todo_complete.xml index 62ce026a..6fd74d90 100644 --- a/presentation/src/main/res/layout/fragment_our_todo_complete.xml +++ b/presentation/src/main/res/layout/fragment_our_todo_complete.xml @@ -15,18 +15,54 @@ + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/layout/fragment_our_todo_uncomplete.xml b/presentation/src/main/res/layout/fragment_our_todo_uncomplete.xml index 634c04b7..995d5a85 100644 --- a/presentation/src/main/res/layout/fragment_our_todo_uncomplete.xml +++ b/presentation/src/main/res/layout/fragment_our_todo_uncomplete.xml @@ -15,18 +15,54 @@ + + + + + + + + \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index e662956e..aee39e65 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -78,6 +78,7 @@ 나의 할일 혼자할일 나에게 남은 할일 %s개 + 할일을 추가해보세요 할일 추가