From 5e669dd064e6a19925258794ce7303d9435ada88 Mon Sep 17 00:00:00 2001 From: bn-tw2020 Date: Mon, 11 Apr 2022 13:23:47 +0900 Subject: [PATCH 01/18] =?UTF-8?q?feat:=20=ED=8C=9D=EC=97=85=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=ED=85=9C=EC=97=90=20=EC=97=B0=EA=B2=B0,=20task=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C,=20=EC=9D=B4=EB=8F=99=20=EA=B5=AC=ED=98=84-#35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todolist/model/response/TasksResponse.kt | 2 +- .../todolist/repository/TaskRepository.kt | 38 +++++++++++++++---- .../com/example/todolist/ui/MainActivity.kt | 33 ++++------------ .../com/example/todolist/ui/TaskAdapter.kt | 37 +++++++++++++++--- .../com/example/todolist/ui/TaskViewModel.kt | 14 +++++++ .../res/menu/{popup.xml => menu_popup.xml} | 2 +- .../app/src/main/res/values-night/strings.xml | 2 +- android/app/src/main/res/values/strings.xml | 2 +- 8 files changed, 87 insertions(+), 43 deletions(-) rename android/app/src/main/res/menu/{popup.xml => menu_popup.xml} (86%) diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index 25ec6896d..13a972510 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -10,6 +10,6 @@ data class TaskDetailResponse( val id: Int, val title: String, val content: String, - val status: Status, + var status: Status, val author: String = "Android", ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 7ebdf038a..7bf187f5a 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -44,28 +44,50 @@ class TaskRepository { fun addTask(task: Task): TasksResponse { when (task.status) { - Status.TODO -> tasks.todo.add(TaskDetailResponse(todoIndex++, + Status.TODO -> tasks.todo.add(0, TaskDetailResponse(todoIndex++, task.title, task.content, task.status)) - Status.IN_PROGRESS -> tasks.inProgress.add(TaskDetailResponse(inProgressIndex++, + Status.IN_PROGRESS -> tasks.inProgress.add(0, TaskDetailResponse(inProgressIndex++, task.title, task.content, task.status)) - Status.DONE -> tasks.done.add(TaskDetailResponse(doneIndex++, + Status.DONE -> tasks.done.add(0, TaskDetailResponse(doneIndex++, task.title, task.content, - task.status)) + task.status) + ) + } + return tasks + } + + fun moveDone(task: TaskDetailResponse): TasksResponse { + deleteTask(task) + if (task.status == Status.TODO) { + task.status = Status.DONE + tasks.done.add(0, task) + } else if (task.status == Status.IN_PROGRESS) { + task.status = Status.DONE + tasks.done.add(0, task) + } + return tasks + } + + fun deleteTask(task: TaskDetailResponse): TasksResponse { + when (task.status) { + Status.TODO -> tasks.todo.remove(task) + Status.IN_PROGRESS -> tasks.inProgress.remove(task) + else -> tasks.done.remove(task) } return tasks } fun getHistory(): List { return listOf( - History(1, ActionType.MOVE, "HTML/CSS공부하기", "해야할 일", "하고 있는 일", "2022-04-05 21:19:00"), - History(2, ActionType.ADD, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), - History(3, ActionType.REMOVE, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), - History(4, ActionType.UPDATE, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), + History(4, ActionType.MOVE, "HTML/CSS공부하기", "해야할 일", "하고 있는 일", "2022-04-05 21:19:00"), + History(3, ActionType.ADD, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), + History(2, ActionType.REMOVE, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), + History(1, ActionType.UPDATE, "HTML/CSS공부하기", "해야할 일", null, "2022-04-05 21:05:03"), ) } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index 5d31f5f0b..e0d9d5d33 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -3,8 +3,6 @@ package com.example.todolist.ui import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.* -import android.widget.PopupMenu -import android.widget.Toast import androidx.activity.viewModels import androidx.databinding.DataBindingUtil import com.example.todolist.R @@ -12,13 +10,13 @@ import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status import com.example.todolist.ui.common.ViewModelFactory -class MainActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener { +class MainActivity : AppCompatActivity() { private val viewModel: TaskViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } - private val toDoAdapter: TaskAdapter by lazy { TaskAdapter() } - private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter() } - private val doneAdapter: TaskAdapter by lazy { TaskAdapter() } + private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } + private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } + private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -48,17 +46,17 @@ class MainActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener { binding.includeTodo.rvTodo.adapter = toDoAdapter viewModel.todoTask.observe(this) { todoTask -> - toDoAdapter.submitList(todoTask) + toDoAdapter.submitList(todoTask.toList()) } binding.includeInProgress.rvInProgress.adapter = inProgressAdapter viewModel.inProgressTask.observe(this) { inProgressTask -> - inProgressAdapter.submitList(inProgressTask) + inProgressAdapter.submitList(inProgressTask.toList()) } binding.includeDone.rvDone.adapter = doneAdapter viewModel.doneTask.observe(this) { doneTask -> - doneAdapter.submitList(doneTask) + doneAdapter.submitList(doneTask.toList()) } } @@ -73,21 +71,4 @@ class MainActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener { binding.dlDrawer.closeDrawer(Gravity.RIGHT) } } - - private fun showPopup(view: View) { - val wrapper = ContextThemeWrapper(this, R.style.PopupWindow) - val popup = PopupMenu(wrapper, view) - popup.menuInflater.inflate(R.menu.popup, popup.menu) - popup.setOnMenuItemClickListener(this) - popup.show() - } - - override fun onMenuItemClick(item: MenuItem?): Boolean { - when (item?.itemId) { - R.id.popup_go_done -> Toast.makeText(this, "popup_go_done", Toast.LENGTH_LONG).show() - R.id.popup_modify -> Toast.makeText(this, "popup_modify", Toast.LENGTH_LONG).show() - R.id.popup_delete -> Toast.makeText(this, "popup_delete", Toast.LENGTH_LONG).show() - } - return item != null - } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 70647bd09..565bac0d8 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -1,14 +1,16 @@ package com.example.todolist.ui -import android.view.LayoutInflater -import android.view.ViewGroup +import android.util.Log +import android.view.* +import android.widget.PopupMenu import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.example.todolist.R import com.example.todolist.databinding.ItemTaskBinding import com.example.todolist.model.TaskDetailResponse -class TaskAdapter : ListAdapter(TaskDiffCallback) { +class TaskAdapter(private val viewModel: TaskViewModel) : ListAdapter(TaskDiffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder { val binding = ItemTaskBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -19,11 +21,36 @@ class TaskAdapter : ListAdapter( holder.bind(getItem(position)) } - class TaskViewHolder(private val binding: ItemTaskBinding) : - RecyclerView.ViewHolder(binding.root) { + inner class TaskViewHolder(private val binding: ItemTaskBinding) : + RecyclerView.ViewHolder(binding.root), PopupMenu.OnMenuItemClickListener { + + private lateinit var task: TaskDetailResponse + fun bind(task: TaskDetailResponse) { + this.task = task binding.task = task binding.executePendingBindings() + itemView.setOnLongClickListener { + showPopup(it) + true + } + } + + private fun showPopup(view: View) { + val wrapper = ContextThemeWrapper(view.context, R.style.PopupWindow) + val popup = PopupMenu(wrapper, view) + popup.menuInflater.inflate(R.menu.menu_popup, popup.menu) + popup.setOnMenuItemClickListener(this) + popup.show() + } + + override fun onMenuItemClick(item: MenuItem?): Boolean { + when (item?.itemId) { + R.id.popup_go_done -> viewModel.moveDone(task) + R.id.popup_modify -> Log.d("test", "popup_modify") + R.id.popup_delete -> viewModel.deleteTask(task) + } + return item != null } } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index cf8b27d61..a28ad7dea 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -53,4 +53,18 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { val tasks = repository.addTask(task) _doneTask.value = tasks.done } + + fun moveDone(task: TaskDetailResponse) { + val tasks = repository.moveDone(task) + _todoTask.value = tasks.todo + _inProgressTask.value = tasks.inProgress + _doneTask.value = tasks.done + } + + fun deleteTask(task: TaskDetailResponse) { + val tasks = repository.deleteTask(task) + _todoTask.value = tasks.todo + _inProgressTask.value = tasks.inProgress + _doneTask.value = tasks.done + } } \ No newline at end of file diff --git a/android/app/src/main/res/menu/popup.xml b/android/app/src/main/res/menu/menu_popup.xml similarity index 86% rename from android/app/src/main/res/menu/popup.xml rename to android/app/src/main/res/menu/menu_popup.xml index 5ba1c3ab9..bee6f22ac 100644 --- a/android/app/src/main/res/menu/popup.xml +++ b/android/app/src/main/res/menu/menu_popup.xml @@ -7,5 +7,5 @@ android:title="@string/label_popup_modify" /> + android:title="@string/label_popup_delete" /> \ No newline at end of file diff --git a/android/app/src/main/res/values-night/strings.xml b/android/app/src/main/res/values-night/strings.xml index 5c89a2487..db0d591d2 100644 --- a/android/app/src/main/res/values-night/strings.xml +++ b/android/app/src/main/res/values-night/strings.xml @@ -22,5 +22,5 @@ 완료한 일로 이동 수정하기 - 삭제하기 + 삭제하기 \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 8536906be..ff7d56680 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -22,5 +22,5 @@ author by %s 완료한 일로 이동 수정하기 - 삭제하기 + 삭제하기 \ No newline at end of file From 25ea26deef6806dcd2a6af899ded28996b2f4842 Mon Sep 17 00:00:00 2001 From: bn-tw2020 Date: Mon, 11 Apr 2022 21:54:04 +0900 Subject: [PATCH 02/18] =?UTF-8?q?feat:=20Task=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84-#35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todolist/model/response/TasksResponse.kt | 2 +- .../todolist/repository/TaskRepository.kt | 41 +++++--- .../com/example/todolist/ui/MainActivity.kt | 19 ++-- ...ogFragment.kt => NewTaskDialogFragment.kt} | 2 +- .../com/example/todolist/ui/TaskAdapter.kt | 12 ++- .../com/example/todolist/ui/TaskViewModel.kt | 15 +++ .../todolist/ui/UpdateTaskDialogFragment.kt | 92 ++++++++++++++++++ .../main/res/layout/dialog_update_card.xml | 93 +++++++++++++++++++ android/app/src/main/res/values/strings.xml | 2 + 9 files changed, 254 insertions(+), 24 deletions(-) rename android/app/src/main/java/com/example/todolist/ui/{TaskDialogFragment.kt => NewTaskDialogFragment.kt} (97%) create mode 100644 android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt create mode 100644 android/app/src/main/res/layout/dialog_update_card.xml diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index 13a972510..25ec6896d 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -10,6 +10,6 @@ data class TaskDetailResponse( val id: Int, val title: String, val content: String, - var status: Status, + val status: Status, val author: String = "Android", ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 7bf187f5a..ef2357826 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -17,25 +17,25 @@ class TaskRepository { "Android"), TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.TODO, "Android")), mutableListOf( - TaskDetailResponse(1, + TaskDetailResponse(4, "GitHub 공부하기", "add, commit, push", Status.IN_PROGRESS, "Android"), - TaskDetailResponse(2, + TaskDetailResponse(5, "블로그에 포스팅할 것", "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.IN_PROGRESS, "Android"), - TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.IN_PROGRESS, "Android")), + TaskDetailResponse(6, "HTML/CSS", "input 태그 실습", Status.IN_PROGRESS, "Android")), mutableListOf( - TaskDetailResponse(1, "GitHub 공부하기", "add, commit, push", Status.DONE, "Android"), - TaskDetailResponse(2, + TaskDetailResponse(7, "GitHub 공부하기", "add, commit, push", Status.DONE, "Android"), + TaskDetailResponse(8, "블로그에 포스팅할 것", "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.DONE, "Android"), - TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.DONE, "Android")), + TaskDetailResponse(9, "HTML/CSS", "input 태그 실습", Status.DONE, "Android")), ) fun getTasks(): TasksResponse { @@ -61,14 +61,31 @@ class TaskRepository { return tasks } + fun updateTask(task: TaskDetailResponse): TasksResponse { + when (task.status) { + Status.TODO -> { + val originalTask = tasks.todo.find { task.id == it.id } + val index = tasks.todo.indexOf(originalTask) + tasks.todo[index] = task + } + Status.IN_PROGRESS -> { + val originalTask = tasks.inProgress.find { task.id == it.id } + val index = tasks.inProgress.indexOf(originalTask) + tasks.inProgress[index] = task + } + Status.DONE -> { + val originalTask = tasks.done.find { task.id == it.id } + val index = tasks.done.indexOf(originalTask) + tasks.done[index] = task + } + } + return tasks + } + fun moveDone(task: TaskDetailResponse): TasksResponse { deleteTask(task) - if (task.status == Status.TODO) { - task.status = Status.DONE - tasks.done.add(0, task) - } else if (task.status == Status.IN_PROGRESS) { - task.status = Status.DONE - tasks.done.add(0, task) + if (task.status != Status.DONE) { + tasks.done.add(0, task.copy(status = Status.DONE)) } return tasks } diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index e0d9d5d33..b397b81e0 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -8,15 +8,16 @@ import androidx.databinding.DataBindingUtil import com.example.todolist.R import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status +import com.example.todolist.model.TaskDetailResponse import com.example.todolist.ui.common.ViewModelFactory -class MainActivity : AppCompatActivity() { +class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private val viewModel: TaskViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } - private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } - private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } - private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel) } + private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -32,15 +33,15 @@ class MainActivity : AppCompatActivity() { with(binding) { includeTodo.btnAdd.setOnClickListener { - TaskDialogFragment(Status.TODO).show(supportFragmentManager, "todoDialog") + NewTaskDialogFragment(Status.TODO).show(supportFragmentManager, "todoDialog") } includeInProgress.btnAdd.setOnClickListener { - TaskDialogFragment(Status.IN_PROGRESS).show(supportFragmentManager, "inProgressDialog") + NewTaskDialogFragment(Status.IN_PROGRESS).show(supportFragmentManager, "inProgressDialog") } includeDone.btnAdd.setOnClickListener { - TaskDialogFragment(Status.DONE).show(supportFragmentManager, "doneDialog") + NewTaskDialogFragment(Status.DONE).show(supportFragmentManager, "doneDialog") } } @@ -71,4 +72,8 @@ class MainActivity : AppCompatActivity() { binding.dlDrawer.closeDrawer(Gravity.RIGHT) } } + + override fun updateDialog(task: TaskDetailResponse) { + UpdateTaskDialogFragment(task).show(supportFragmentManager, "updateDialog") + } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt similarity index 97% rename from android/app/src/main/java/com/example/todolist/ui/TaskDialogFragment.kt rename to android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt index 9f9a70972..71067db3b 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt @@ -15,7 +15,7 @@ import com.example.todolist.databinding.DialogNewCardBinding import com.example.todolist.model.Status import com.example.todolist.model.Task -class TaskDialogFragment(private val status: Status) : DialogFragment() { +class NewTaskDialogFragment(private val status: Status) : DialogFragment() { private lateinit var binding: DialogNewCardBinding private val viewModel: TaskViewModel by activityViewModels() private var titleFlag = false diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 565bac0d8..2fee6418d 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -1,6 +1,5 @@ package com.example.todolist.ui -import android.util.Log import android.view.* import android.widget.PopupMenu import androidx.recyclerview.widget.DiffUtil @@ -10,7 +9,14 @@ import com.example.todolist.R import com.example.todolist.databinding.ItemTaskBinding import com.example.todolist.model.TaskDetailResponse -class TaskAdapter(private val viewModel: TaskViewModel) : ListAdapter(TaskDiffCallback) { +class TaskAdapter( + private val viewModel: TaskViewModel, + private val listener: DialogListener +) : ListAdapter(TaskDiffCallback) { + + interface DialogListener { + fun updateDialog(task: TaskDetailResponse) + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder { val binding = ItemTaskBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -47,7 +53,7 @@ class TaskAdapter(private val viewModel: TaskViewModel) : ListAdapter viewModel.moveDone(task) - R.id.popup_modify -> Log.d("test", "popup_modify") + R.id.popup_modify -> listener.updateDialog(task) R.id.popup_delete -> viewModel.deleteTask(task) } return item != null diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index a28ad7dea..134c72bc1 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -67,4 +67,19 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { _inProgressTask.value = tasks.inProgress _doneTask.value = tasks.done } + + fun updateTodoTask(task: TaskDetailResponse) { + val tasks = repository.updateTask(task) + _todoTask.value = tasks.todo + } + + fun updateInProgressTask(task: TaskDetailResponse) { + val tasks = repository.updateTask(task) + _inProgressTask.value = tasks.inProgress + } + + fun updateDoneTask(task: TaskDetailResponse) { + val tasks = repository.updateTask(task) + _doneTask.value = tasks.done + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt new file mode 100644 index 000000000..db081e432 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -0,0 +1,92 @@ +package com.example.todolist.ui + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.Window +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels +import com.example.todolist.databinding.DialogUpdateCardBinding +import com.example.todolist.model.Status +import com.example.todolist.model.TaskDetailResponse + +class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { + private lateinit var binding: DialogUpdateCardBinding + private val viewModel: TaskViewModel by activityViewModels() + private var titleFlag = false + private var contentsFlag = false + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + binding = DialogUpdateCardBinding.inflate(inflater, container, false) + dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // 다이얼로그의 곡선 주변에 배경색을 맞춰주는 코드 + dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE) + dialog?.setCanceledOnTouchOutside(false) // 다이얼로그 외부의 영역 터치 시 취소 불가능 + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + binding.btnCancel.setOnClickListener { dismiss() } + + binding.etTitle.addTextChangedListener(titleListener) + binding.etContents.addTextChangedListener(contentsListener) + binding.etTitle.setText(task.title) + binding.etContents.setText(task.content) + + binding.btnUpdate.setOnClickListener { + val updateTask = task.copy(title = binding.etTitle.text.toString(), + content = binding.etContents.text.toString()) + when (task.status) { + Status.TODO -> viewModel.updateTodoTask(updateTask) + Status.IN_PROGRESS -> viewModel.updateInProgressTask(updateTask) + else -> viewModel.updateDoneTask(updateTask) + } + dismiss() + } + } + + private val titleListener = object : TextWatcher { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + override fun afterTextChanged(s: Editable?) { + if (s != null) { + titleFlag = when { + s.isEmpty() -> false + else -> true + } + } + flagCheck() + } + } + + private val contentsListener = object : TextWatcher { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} + + override fun afterTextChanged(s: Editable?) { + if (s != null) { + contentsFlag = when { + s.isEmpty() -> false + else -> true + } + } + flagCheck() + } + } + + fun flagCheck() { + binding.btnUpdate.isEnabled = titleFlag && contentsFlag + } +} \ No newline at end of file diff --git a/android/app/src/main/res/layout/dialog_update_card.xml b/android/app/src/main/res/layout/dialog_update_card.xml new file mode 100644 index 000000000..78123e20c --- /dev/null +++ b/android/app/src/main/res/layout/dialog_update_card.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index ff7d56680..7b322f192 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -14,7 +14,9 @@ 완료한 일 add_button 새로운 카드 추가 + 카드 수정 등록 + 수정 취소 제목을 입력하세요 내용을 입력하세요 From e8af1006dccdc789edc11741e2901758a429a403 Mon Sep 17 00:00:00 2001 From: hwj Date: Tue, 12 Apr 2022 22:09:38 +0900 Subject: [PATCH 03/18] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todolist/model/request/TaskRequest.kt | 8 +++ .../model/response/LoadTasksResponse.kt | 31 ++++++++++ .../todolist/model/response/TasksResponse.kt | 14 ++++- .../example/todolist/network/RetrofitAPI.kt | 30 ++++++++++ .../com/example/todolist/network/Service.kt | 21 +++++++ .../todolist/repository/TaskDataSource.kt | 12 ++++ .../repository/TaskRemoteDataSource.kt | 44 ++++++++++++++ .../repository/TaskRemoteRepository.kt | 20 +++++++ .../todolist/repository/TaskRepository.kt | 17 ++++-- .../com/example/todolist/ui/MainActivity.kt | 11 ++-- .../todolist/ui/NewTaskDialogFragment.kt | 8 +-- .../com/example/todolist/ui/TaskAdapter.kt | 4 +- .../todolist/ui/TaskRemoteViewModel.kt | 57 +++++++++++++++++++ .../com/example/todolist/ui/TaskViewModel.kt | 1 + .../todolist/ui/UpdateTaskDialogFragment.kt | 2 +- .../todolist/ui/common/ViewModelFactory.kt | 9 ++- .../res/layout-sw720dp-land/activity_main.xml | 3 + .../app/src/main/res/layout/activity_main.xml | 3 + android/app/src/main/res/layout/item_task.xml | 2 +- android/app/src/main/res/layout/view_done.xml | 2 +- .../src/main/res/layout/view_in_progress.xml | 2 +- android/app/src/main/res/layout/view_todo.xml | 2 +- 22 files changed, 280 insertions(+), 23 deletions(-) create mode 100644 android/app/src/main/java/com/example/todolist/model/request/TaskRequest.kt create mode 100644 android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt create mode 100644 android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt create mode 100644 android/app/src/main/java/com/example/todolist/network/Service.kt create mode 100644 android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt create mode 100644 android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt create mode 100644 android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt create mode 100644 android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt diff --git a/android/app/src/main/java/com/example/todolist/model/request/TaskRequest.kt b/android/app/src/main/java/com/example/todolist/model/request/TaskRequest.kt new file mode 100644 index 000000000..61fcac171 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/model/request/TaskRequest.kt @@ -0,0 +1,8 @@ +package com.example.todolist.model.request + +data class TaskRequest( + val title: String, + val contents: String, + val status: String, + val author: String +) diff --git a/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt new file mode 100644 index 000000000..2f4320141 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt @@ -0,0 +1,31 @@ +package com.example.todolist.model.response + +data class LoadTasksResponse( + val doneCollection: MutableList, + val inProgressCollection: MutableList, + val todoCollection: MutableList +) + +data class DoneCollection( + val author: String, + val contents: String, + val id: Int, + val status: String, + val title: String +) + +data class InProgressCollection( + val author: String, + val contents: String, + val id: Int, + val status: String, + val title: String +) + +data class TodoCollection( + val author: String, + val contents: String, + val id: Int, + val status: String, + val title: String +) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index 25ec6896d..428d0e149 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -1,8 +1,14 @@ -package com.example.todolist.model +package com.example.todolist.model.response + +import com.example.todolist.model.Status +import com.google.gson.annotations.SerializedName data class TasksResponse( + @SerializedName("todoCollection") val todo: MutableList, + @SerializedName("inProgressCollection") val inProgress: MutableList, + @SerializedName("doneCollection") val done: MutableList, ) @@ -12,4 +18,10 @@ data class TaskDetailResponse( val content: String, val status: Status, val author: String = "Android", + val updateDateTime: String? +) + +data class AddTasksResponse( + val status: Int, + val resources: TaskDetailResponse ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt b/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt new file mode 100644 index 000000000..c536d6742 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt @@ -0,0 +1,30 @@ +package com.example.todolist.network + +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +object RetrofitAPI { + private const val BASE_URL = "www.louie-03.com/" + + private val okHttpClient: OkHttpClient by lazy { + OkHttpClient.Builder() + .addInterceptor(HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + }) + .build() + } + + private val retrofit: Retrofit by lazy { + Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .client(okHttpClient) + .build() + } + + val service: Service by lazy { + retrofit.create(Service::class.java) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt new file mode 100644 index 000000000..d7d32abcf --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -0,0 +1,21 @@ +package com.example.todolist.network + +import com.example.todolist.model.Task +import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.response.TasksResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Headers +import retrofit2.http.POST + +interface Service { + + @Headers("Content-Type: application/json") + @GET("cards") + suspend fun loadTasks(): Response + + @Headers("Content-Type: application/json") + @POST("cards") + suspend fun saveTask(@Body cardInfo: Task): Response +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt new file mode 100644 index 000000000..19b46641a --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -0,0 +1,12 @@ +package com.example.todolist.repository + +import com.example.todolist.model.Task +import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.response.TasksResponse + +interface TaskDataSource { + + suspend fun loadTasks(): TasksResponse? + + suspend fun addTask(cardData: Task): AddTasksResponse? +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt new file mode 100644 index 000000000..2fdb31c31 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -0,0 +1,44 @@ +package com.example.todolist.repository + +import android.util.Log +import com.example.todolist.model.Task +import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.response.TaskDetailResponse +import com.example.todolist.model.response.LoadTasksResponse +import com.example.todolist.model.response.TasksResponse +import com.example.todolist.network.RetrofitAPI + +class TaskRemoteDataSource : TaskDataSource { + + override suspend fun loadTasks(): TasksResponse? { + var task: TasksResponse? = null + + val service = RetrofitAPI.service + val response = service.loadTasks() + if (response.isSuccessful) { + val result = response.body() + task = result + Log.d("카드 저장 성공", "$result") + } else { + // TODO 실패했을 시 담을 데이터 정하기 + Log.d("카드 저장 실패", "${response.code()}") + } + return task + } + + override suspend fun addTask(cardData: Task): AddTasksResponse? { + var task: AddTasksResponse? = null + + val service = RetrofitAPI.service + val response = service.saveTask(cardData) + if (response.isSuccessful) { + val result = response.body() + task = result + Log.d("카드 저장 성공", "$result") + } else { + // TODO 실패했을 시 담을 데이터 정하기 + Log.d("카드 저장 실패", "${response.code()}") + } + return task + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt new file mode 100644 index 000000000..0eee28ba9 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -0,0 +1,20 @@ +package com.example.todolist.repository + +import com.example.todolist.model.Status +import com.example.todolist.model.Task +import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.response.TaskDetailResponse +import com.example.todolist.model.response.TasksResponse + +class TaskRemoteRepository( + private val taskRemoteDataSource: TaskRemoteDataSource +) { + + suspend fun loadTask(): TasksResponse? { + return taskRemoteDataSource.loadTasks() + } + + suspend fun addTask(cardData: Task): AddTasksResponse? { + return taskRemoteDataSource.addTask(cardData) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index ef2357826..1dbcf3685 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -1,6 +1,8 @@ package com.example.todolist.repository import com.example.todolist.model.* +import com.example.todolist.model.response.TaskDetailResponse +import com.example.todolist.model.response.TasksResponse class TaskRepository { @@ -15,7 +17,8 @@ class TaskRepository { "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.TODO, "Android"), - TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.TODO, "Android")), + TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.TODO, "Android") + ), mutableListOf( TaskDetailResponse(4, "GitHub 공부하기", @@ -27,7 +30,8 @@ class TaskRepository { "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.IN_PROGRESS, "Android"), - TaskDetailResponse(6, "HTML/CSS", "input 태그 실습", Status.IN_PROGRESS, "Android")), + TaskDetailResponse(6, "HTML/CSS", "input 태그 실습", Status.IN_PROGRESS, "Android") + ), mutableListOf( TaskDetailResponse(7, "GitHub 공부하기", "add, commit, push", Status.DONE, "Android"), TaskDetailResponse(8, @@ -35,7 +39,8 @@ class TaskRepository { "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.DONE, "Android"), - TaskDetailResponse(9, "HTML/CSS", "input 태그 실습", Status.DONE, "Android")), + TaskDetailResponse(9, "HTML/CSS", "input 태그 실습", Status.DONE, "Android") + ), ) fun getTasks(): TasksResponse { @@ -47,11 +52,13 @@ class TaskRepository { Status.TODO -> tasks.todo.add(0, TaskDetailResponse(todoIndex++, task.title, task.content, - task.status)) + task.status) + ) Status.IN_PROGRESS -> tasks.inProgress.add(0, TaskDetailResponse(inProgressIndex++, task.title, task.content, - task.status)) + task.status) + ) Status.DONE -> tasks.done.add(0, TaskDetailResponse(doneIndex++, task.title, task.content, diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index b397b81e0..eab614e58 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -8,11 +8,12 @@ import androidx.databinding.DataBindingUtil import com.example.todolist.R import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status -import com.example.todolist.model.TaskDetailResponse +import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.ui.common.ViewModelFactory class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private val viewModel: TaskViewModel by viewModels { ViewModelFactory() } + private val remoteViewModel: TaskRemoteViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } @@ -22,7 +23,7 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) - binding.viewModel = viewModel + binding.viewModel = remoteViewModel binding.lifecycleOwner = this onDrawerEvent() @@ -46,17 +47,17 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } binding.includeTodo.rvTodo.adapter = toDoAdapter - viewModel.todoTask.observe(this) { todoTask -> + remoteViewModel.todoTask.observe(this) { todoTask -> toDoAdapter.submitList(todoTask.toList()) } binding.includeInProgress.rvInProgress.adapter = inProgressAdapter - viewModel.inProgressTask.observe(this) { inProgressTask -> + remoteViewModel.inProgressTask.observe(this) { inProgressTask -> inProgressAdapter.submitList(inProgressTask.toList()) } binding.includeDone.rvDone.adapter = doneAdapter - viewModel.doneTask.observe(this) { doneTask -> + remoteViewModel.doneTask.observe(this) { doneTask -> doneAdapter.submitList(doneTask.toList()) } diff --git a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt index 71067db3b..1a9f42a63 100644 --- a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt @@ -17,7 +17,7 @@ import com.example.todolist.model.Task class NewTaskDialogFragment(private val status: Status) : DialogFragment() { private lateinit var binding: DialogNewCardBinding - private val viewModel: TaskViewModel by activityViewModels() + private val remoteViewModel: TaskRemoteViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -48,7 +48,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.TODO ) - viewModel.addTodoTask(task) + remoteViewModel.addTask(task) } Status.IN_PROGRESS -> { val task = Task( @@ -56,7 +56,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.IN_PROGRESS ) - viewModel.addInProgressTask(task) + remoteViewModel.addTask(task) } else -> { val task = Task( @@ -64,7 +64,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.DONE ) - viewModel.addDoneTask(task) + remoteViewModel.addTask(task) } } dismiss() diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 2fee6418d..ef57ad27c 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -7,10 +7,10 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.example.todolist.R import com.example.todolist.databinding.ItemTaskBinding -import com.example.todolist.model.TaskDetailResponse +import com.example.todolist.model.response.TaskDetailResponse class TaskAdapter( - private val viewModel: TaskViewModel, + private val viewModel: TaskRemoteViewModel, private val listener: DialogListener ) : ListAdapter(TaskDiffCallback) { diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt new file mode 100644 index 000000000..3162d6d35 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -0,0 +1,57 @@ +package com.example.todolist.ui + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.todolist.model.Status +import com.example.todolist.model.Task +import com.example.todolist.model.response.TaskDetailResponse +import com.example.todolist.repository.TaskRemoteRepository +import kotlinx.coroutines.launch + +class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository) : ViewModel() { + + private val _todoTask = MutableLiveData>() + val todoTask: LiveData> + get() = _todoTask + + private val _inProgressTask = MutableLiveData>() + val inProgressTask: LiveData> + get() = _inProgressTask + + private val _doneTask = MutableLiveData>() + val doneTask: LiveData> + get() = _doneTask + + init { + loadTasks() + } + + private fun loadTasks() { + viewModelScope.launch { + val tasks = taskRemoteRepository.loadTask() + _todoTask.value = tasks?.todo + _inProgressTask.value = tasks?.inProgress + _doneTask.value = tasks?.done + } + } + + fun addTask(task: Task) { + viewModelScope.launch { + taskRemoteRepository.addTask(task)?.let { + when (it.resources.status) { + Status.TODO -> { + _todoTask.value?.add(it.resources) + } + Status.IN_PROGRESS -> { + _inProgressTask.value?.add(it.resources) + } + Status.DONE -> { + _doneTask.value?.add(it.resources) + } + } + } + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index 134c72bc1..8cf22b856 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.example.todolist.model.* +import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.repository.TaskRepository class TaskViewModel(private val repository: TaskRepository) : ViewModel() { diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt index db081e432..ff766318f 100644 --- a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -13,7 +13,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.example.todolist.databinding.DialogUpdateCardBinding import com.example.todolist.model.Status -import com.example.todolist.model.TaskDetailResponse +import com.example.todolist.model.response.TaskDetailResponse class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { private lateinit var binding: DialogUpdateCardBinding diff --git a/android/app/src/main/java/com/example/todolist/ui/common/ViewModelFactory.kt b/android/app/src/main/java/com/example/todolist/ui/common/ViewModelFactory.kt index aa51b866c..e5537782b 100644 --- a/android/app/src/main/java/com/example/todolist/ui/common/ViewModelFactory.kt +++ b/android/app/src/main/java/com/example/todolist/ui/common/ViewModelFactory.kt @@ -2,13 +2,20 @@ package com.example.todolist.ui.common import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.example.todolist.repository.TaskRemoteDataSource +import com.example.todolist.repository.TaskRemoteRepository import com.example.todolist.repository.TaskRepository +import com.example.todolist.ui.TaskRemoteViewModel import com.example.todolist.ui.TaskViewModel -class ViewModelFactory() : ViewModelProvider.Factory { +class ViewModelFactory : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return when { modelClass.isAssignableFrom(TaskViewModel::class.java) -> TaskViewModel(TaskRepository()) as T + modelClass.isAssignableFrom(TaskRemoteViewModel::class.java) -> { + val repository = TaskRemoteRepository(TaskRemoteDataSource()) + TaskRemoteViewModel(repository) as T + } else -> throw IllegalAccessException("Failed to create ViewModel: ${modelClass.name}") } } diff --git a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml index cbd1cbe67..cc5c30e03 100644 --- a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml +++ b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml @@ -8,6 +8,9 @@ + diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index cbd1cbe67..cc5c30e03 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -8,6 +8,9 @@ + diff --git a/android/app/src/main/res/layout/item_task.xml b/android/app/src/main/res/layout/item_task.xml index 2bc90a9ab..4b786392e 100644 --- a/android/app/src/main/res/layout/item_task.xml +++ b/android/app/src/main/res/layout/item_task.xml @@ -7,7 +7,7 @@ + type="com.example.todolist.model.response.TaskDetailResponse" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> Date: Wed, 13 Apr 2022 16:11:47 +0900 Subject: [PATCH 04/18] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/request/ModifyTaskRequest.kt | 8 ++++ .../todolist/model/response/TasksResponse.kt | 9 ++--- .../com/example/todolist/network/Service.kt | 17 +++++--- .../todolist/repository/TaskDataSource.kt | 8 +++- .../repository/TaskRemoteDataSource.kt | 28 ++++++++++--- .../repository/TaskRemoteRepository.kt | 10 +++-- .../todolist/repository/TaskRepository.kt | 10 ++--- .../com/example/todolist/ui/MainActivity.kt | 8 ++-- .../todolist/ui/TaskRemoteViewModel.kt | 39 +++++++++++++++++-- .../com/example/todolist/ui/TaskViewModel.kt | 10 ++--- .../todolist/ui/UpdateTaskDialogFragment.kt | 13 +++---- 11 files changed, 113 insertions(+), 47 deletions(-) create mode 100644 android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt diff --git a/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt b/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt new file mode 100644 index 000000000..ffe466061 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt @@ -0,0 +1,8 @@ +package com.example.todolist.model.request + +data class ModifyTaskRequest( + val id: Int, + val title: String, + val contents: String, + val author: String = "Android" +) diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index 428d0e149..6d96c4bc9 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -12,6 +12,10 @@ data class TasksResponse( val done: MutableList, ) +data class Result( + val status: Int, + val taskDetailResponse: TaskDetailResponse +) data class TaskDetailResponse( val id: Int, val title: String, @@ -19,9 +23,4 @@ data class TaskDetailResponse( val status: Status, val author: String = "Android", val updateDateTime: String? -) - -data class AddTasksResponse( - val status: Int, - val resources: TaskDetailResponse ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index d7d32abcf..3686b9278 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -1,13 +1,11 @@ package com.example.todolist.network import com.example.todolist.model.Task -import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.request.ModifyTaskRequest +import com.example.todolist.model.response.Result import com.example.todolist.model.response.TasksResponse import retrofit2.Response -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.Headers -import retrofit2.http.POST +import retrofit2.http.* interface Service { @@ -17,5 +15,12 @@ interface Service { @Headers("Content-Type: application/json") @POST("cards") - suspend fun saveTask(@Body cardInfo: Task): Response + suspend fun saveTask(@Body cardInfo: Task): Response + + @Headers("Content-Type: application/json") + @PATCH("cards") + suspend fun modifyTask( + @Path("id") id: Int, + @Body modifyTaskRequest: ModifyTaskRequest + ): Response } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index 19b46641a..19f1dd662 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -1,12 +1,16 @@ package com.example.todolist.repository import com.example.todolist.model.Task -import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.request.ModifyTaskRequest +import com.example.todolist.model.response.Result +import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse interface TaskDataSource { suspend fun loadTasks(): TasksResponse? - suspend fun addTask(cardData: Task): AddTasksResponse? + suspend fun addTask(cardData: Task): Result? + + suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index 2fdb31c31..96d8590cd 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -2,9 +2,9 @@ package com.example.todolist.repository import android.util.Log import com.example.todolist.model.Task -import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.request.ModifyTaskRequest +import com.example.todolist.model.response.Result import com.example.todolist.model.response.TaskDetailResponse -import com.example.todolist.model.response.LoadTasksResponse import com.example.todolist.model.response.TasksResponse import com.example.todolist.network.RetrofitAPI @@ -18,16 +18,16 @@ class TaskRemoteDataSource : TaskDataSource { if (response.isSuccessful) { val result = response.body() task = result - Log.d("카드 저장 성공", "$result") + Log.d("카드 조회 성공", "$result") } else { // TODO 실패했을 시 담을 데이터 정하기 - Log.d("카드 저장 실패", "${response.code()}") + Log.d("카드 조회 실패", "${response.code()}") } return task } - override suspend fun addTask(cardData: Task): AddTasksResponse? { - var task: AddTasksResponse? = null + override suspend fun addTask(cardData: Task): Result? { + var task: Result? = null val service = RetrofitAPI.service val response = service.saveTask(cardData) @@ -41,4 +41,20 @@ class TaskRemoteDataSource : TaskDataSource { } return task } + + override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { + var task: TaskDetailResponse? = null + + val service = RetrofitAPI.service + val response = service.modifyTask(modifyTaskRequest.id, modifyTaskRequest) + if (response.isSuccessful) { + val result = response.body() + task = result?.taskDetailResponse + Log.d("카드 수정 성공", "$result") + } else { + // TODO 실패했을 시 담을 데이터 정하기 + Log.d("카드 수정 실패", "${response.code()}") + } + return task + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 0eee28ba9..88a3ac52b 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -1,8 +1,8 @@ package com.example.todolist.repository -import com.example.todolist.model.Status import com.example.todolist.model.Task -import com.example.todolist.model.response.AddTasksResponse +import com.example.todolist.model.request.ModifyTaskRequest +import com.example.todolist.model.response.Result import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse @@ -14,7 +14,11 @@ class TaskRemoteRepository( return taskRemoteDataSource.loadTasks() } - suspend fun addTask(cardData: Task): AddTasksResponse? { + suspend fun addTask(cardData: Task): Result? { return taskRemoteDataSource.addTask(cardData) } + + suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { + return taskRemoteDataSource.modifyTask(modifyTaskRequest) + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 1dbcf3685..4472a88b9 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -54,7 +54,7 @@ class TaskRepository { task.content, task.status) ) - Status.IN_PROGRESS -> tasks.inProgress.add(0, TaskDetailResponse(inProgressIndex++, + Status.IN_PROGRESS -> tasks.inProgresses.add(0, TaskDetailResponse(inProgressIndex++, task.title, task.content, task.status) @@ -76,9 +76,9 @@ class TaskRepository { tasks.todo[index] = task } Status.IN_PROGRESS -> { - val originalTask = tasks.inProgress.find { task.id == it.id } - val index = tasks.inProgress.indexOf(originalTask) - tasks.inProgress[index] = task + val originalTask = tasks.inProgresses.find { task.id == it.id } + val index = tasks.inProgresses.indexOf(originalTask) + tasks.inProgresses[index] = task } Status.DONE -> { val originalTask = tasks.done.find { task.id == it.id } @@ -100,7 +100,7 @@ class TaskRepository { fun deleteTask(task: TaskDetailResponse): TasksResponse { when (task.status) { Status.TODO -> tasks.todo.remove(task) - Status.IN_PROGRESS -> tasks.inProgress.remove(task) + Status.IN_PROGRESS -> tasks.inProgresses.remove(task) else -> tasks.done.remove(task) } return tasks diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index eab614e58..b28fd9170 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -8,6 +8,8 @@ import androidx.databinding.DataBindingUtil import com.example.todolist.R import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status +import com.example.todolist.model.Task +import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.ui.common.ViewModelFactory @@ -16,9 +18,9 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private val remoteViewModel: TaskRemoteViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } - private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } - private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } - private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } + private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } + private val doneAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index 3162d6d35..37d790b0a 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.todolist.model.Status import com.example.todolist.model.Task +import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.repository.TaskRemoteRepository import kotlinx.coroutines.launch @@ -40,15 +41,45 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository fun addTask(task: Task) { viewModelScope.launch { taskRemoteRepository.addTask(task)?.let { - when (it.resources.status) { + when (it.taskDetailResponse.status) { Status.TODO -> { - _todoTask.value?.add(it.resources) + _todoTask.value?.add(it.taskDetailResponse) } Status.IN_PROGRESS -> { - _inProgressTask.value?.add(it.resources) + _inProgressTask.value?.add(it.taskDetailResponse) } Status.DONE -> { - _doneTask.value?.add(it.resources) + _doneTask.value?.add(it.taskDetailResponse) + } + } + } + } + } + + fun modifyTask(modifyTaskRequest: ModifyTaskRequest) { + viewModelScope.launch { + taskRemoteRepository.modifyTask(modifyTaskRequest)?.let { + when (it.status) { + Status.TODO -> { + val originalTask = _todoTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val index = _todoTask.value?.indexOf(originalTask) + if (index != null) { + _todoTask.value?.set(index, it) + } + } + Status.IN_PROGRESS -> { + val originalTask = _inProgressTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val index = _inProgressTask.value?.indexOf(originalTask) + if (index != null) { + _inProgressTask.value?.set(index, it) + } + } + Status.DONE -> { + val originalTask = _doneTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val index = _doneTask.value?.indexOf(originalTask) + if (index != null) { + _doneTask.value?.set(index, it) + } } } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index 8cf22b856..ef2245378 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -32,7 +32,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { private fun loadTasks() { val tasks = repository.getTasks() _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgress + _inProgressTask.value = tasks.inProgresses _doneTask.value = tasks.done } @@ -47,7 +47,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun addInProgressTask(task: Task) { val tasks = repository.addTask(task) - _inProgressTask.value = tasks.inProgress + _inProgressTask.value = tasks.inProgresses } fun addDoneTask(task: Task) { @@ -58,14 +58,14 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun moveDone(task: TaskDetailResponse) { val tasks = repository.moveDone(task) _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgress + _inProgressTask.value = tasks.inProgresses _doneTask.value = tasks.done } fun deleteTask(task: TaskDetailResponse) { val tasks = repository.deleteTask(task) _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgress + _inProgressTask.value = tasks.inProgresses _doneTask.value = tasks.done } @@ -76,7 +76,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun updateInProgressTask(task: TaskDetailResponse) { val tasks = repository.updateTask(task) - _inProgressTask.value = tasks.inProgress + _inProgressTask.value = tasks.inProgresses } fun updateDoneTask(task: TaskDetailResponse) { diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt index ff766318f..44120ca98 100644 --- a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -13,11 +13,13 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.example.todolist.databinding.DialogUpdateCardBinding import com.example.todolist.model.Status +import com.example.todolist.model.Task +import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { private lateinit var binding: DialogUpdateCardBinding - private val viewModel: TaskViewModel by activityViewModels() + private val viewModel: TaskRemoteViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -43,13 +45,8 @@ class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFra binding.etContents.setText(task.content) binding.btnUpdate.setOnClickListener { - val updateTask = task.copy(title = binding.etTitle.text.toString(), - content = binding.etContents.text.toString()) - when (task.status) { - Status.TODO -> viewModel.updateTodoTask(updateTask) - Status.IN_PROGRESS -> viewModel.updateInProgressTask(updateTask) - else -> viewModel.updateDoneTask(updateTask) - } + val updateTask = ModifyTaskRequest(task.id, binding.etTitle.text.toString(), binding.etContents.text.toString()) + viewModel.modifyTask(updateTask) dismiss() } } From 0c6e127166c859f0356419bbb1fc9295ce093587 Mon Sep 17 00:00:00 2001 From: hwj Date: Wed, 13 Apr 2022 17:23:12 +0900 Subject: [PATCH 05/18] =?UTF-8?q?fix:=20=EC=8B=A4=ED=96=89=EC=98=A4?= =?UTF-8?q?=EB=A5=98=EC=A0=9C=EA=B1=B0-#39?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/request/ModifyTaskRequest.kt | 3 +- .../todolist/model/response/TasksResponse.kt | 3 +- .../com/example/todolist/network/Service.kt | 2 +- .../todolist/repository/TaskDataSource.kt | 2 +- .../repository/TaskRemoteDataSource.kt | 7 +- .../repository/TaskRemoteRepository.kt | 2 +- .../todolist/repository/TaskRepository.kt | 67 ++++++++++++------- .../com/example/todolist/ui/MainActivity.kt | 20 +++--- .../todolist/ui/NewTaskDialogFragment.kt | 8 +-- .../com/example/todolist/ui/TaskAdapter.kt | 2 +- .../todolist/ui/TaskRemoteViewModel.kt | 9 ++- .../com/example/todolist/ui/TaskViewModel.kt | 10 +-- .../todolist/ui/UpdateTaskDialogFragment.kt | 13 +++- .../todolist/ui/common/TextBindingAdapters.kt | 6 +- .../res/layout-sw720dp-land/activity_main.xml | 4 -- .../app/src/main/res/layout/activity_main.xml | 3 - android/app/src/main/res/layout/view_done.xml | 2 +- .../src/main/res/layout/view_in_progress.xml | 2 +- android/app/src/main/res/layout/view_todo.xml | 2 +- 19 files changed, 96 insertions(+), 71 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt b/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt index ffe466061..ee2685219 100644 --- a/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt +++ b/android/app/src/main/java/com/example/todolist/model/request/ModifyTaskRequest.kt @@ -4,5 +4,6 @@ data class ModifyTaskRequest( val id: Int, val title: String, val contents: String, - val author: String = "Android" + val author: String = "Android", + val status: String ) diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index 6d96c4bc9..aaa821db8 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -16,11 +16,12 @@ data class Result( val status: Int, val taskDetailResponse: TaskDetailResponse ) + data class TaskDetailResponse( val id: Int, val title: String, val content: String, val status: Status, val author: String = "Android", - val updateDateTime: String? + val updateDateTime: String? = null ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index 3686b9278..121628d5e 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -18,7 +18,7 @@ interface Service { suspend fun saveTask(@Body cardInfo: Task): Response @Headers("Content-Type: application/json") - @PATCH("cards") + @PATCH("cards/{id}") suspend fun modifyTask( @Path("id") id: Int, @Body modifyTaskRequest: ModifyTaskRequest diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index 19f1dd662..67cf939c6 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -12,5 +12,5 @@ interface TaskDataSource { suspend fun addTask(cardData: Task): Result? - suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? + suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): Result? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index 96d8590cd..8f947f336 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -4,7 +4,6 @@ import android.util.Log import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.Result -import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse import com.example.todolist.network.RetrofitAPI @@ -42,14 +41,14 @@ class TaskRemoteDataSource : TaskDataSource { return task } - override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { - var task: TaskDetailResponse? = null + override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): Result? { + var task: Result? = null val service = RetrofitAPI.service val response = service.modifyTask(modifyTaskRequest.id, modifyTaskRequest) if (response.isSuccessful) { val result = response.body() - task = result?.taskDetailResponse + task = result Log.d("카드 수정 성공", "$result") } else { // TODO 실패했을 시 담을 데이터 정하기 diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 88a3ac52b..ae8d65f9f 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -19,6 +19,6 @@ class TaskRemoteRepository( } suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { - return taskRemoteDataSource.modifyTask(modifyTaskRequest) + return taskRemoteDataSource.modifyTask(modifyTaskRequest)?.taskDetailResponse } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 4472a88b9..b67e09914 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -12,33 +12,41 @@ class TaskRepository { private val tasks = TasksResponse( mutableListOf( TaskDetailResponse(1, "GitHub 공부하기", "add, commit, push", Status.TODO, "Android"), - TaskDetailResponse(2, + TaskDetailResponse( + 2, "블로그에 포스팅할 것", "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.TODO, - "Android"), + "Android" + ), TaskDetailResponse(3, "HTML/CSS", "input 태그 실습", Status.TODO, "Android") ), mutableListOf( - TaskDetailResponse(4, + TaskDetailResponse( + 4, "GitHub 공부하기", "add, commit, push", Status.IN_PROGRESS, - "Android"), - TaskDetailResponse(5, + "Android" + ), + TaskDetailResponse( + 5, "블로그에 포스팅할 것", "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.IN_PROGRESS, - "Android"), + "Android" + ), TaskDetailResponse(6, "HTML/CSS", "input 태그 실습", Status.IN_PROGRESS, "Android") ), mutableListOf( TaskDetailResponse(7, "GitHub 공부하기", "add, commit, push", Status.DONE, "Android"), - TaskDetailResponse(8, + TaskDetailResponse( + 8, "블로그에 포스팅할 것", "• GitHub 공부내용\n• 모던 자바스크립트 1장 공부내용", Status.DONE, - "Android"), + "Android" + ), TaskDetailResponse(9, "HTML/CSS", "input 태그 실습", Status.DONE, "Android") ), ) @@ -49,20 +57,29 @@ class TaskRepository { fun addTask(task: Task): TasksResponse { when (task.status) { - Status.TODO -> tasks.todo.add(0, TaskDetailResponse(todoIndex++, - task.title, - task.content, - task.status) + Status.TODO -> tasks.todo.add( + 0, TaskDetailResponse( + todoIndex++, + task.title, + task.content, + task.status + ) ) - Status.IN_PROGRESS -> tasks.inProgresses.add(0, TaskDetailResponse(inProgressIndex++, - task.title, - task.content, - task.status) + Status.IN_PROGRESS -> tasks.inProgress.add( + 0, TaskDetailResponse( + inProgressIndex++, + task.title, + task.content, + task.status + ) ) - Status.DONE -> tasks.done.add(0, TaskDetailResponse(doneIndex++, - task.title, - task.content, - task.status) + Status.DONE -> tasks.done.add( + 0, TaskDetailResponse( + doneIndex++, + task.title, + task.content, + task.status + ) ) } return tasks @@ -76,9 +93,9 @@ class TaskRepository { tasks.todo[index] = task } Status.IN_PROGRESS -> { - val originalTask = tasks.inProgresses.find { task.id == it.id } - val index = tasks.inProgresses.indexOf(originalTask) - tasks.inProgresses[index] = task + val originalTask = tasks.inProgress.find { task.id == it.id } + val index = tasks.inProgress.indexOf(originalTask) + tasks.inProgress[index] = task } Status.DONE -> { val originalTask = tasks.done.find { task.id == it.id } @@ -90,9 +107,9 @@ class TaskRepository { } fun moveDone(task: TaskDetailResponse): TasksResponse { - deleteTask(task) if (task.status != Status.DONE) { tasks.done.add(0, task.copy(status = Status.DONE)) + deleteTask(task) } return tasks } @@ -100,7 +117,7 @@ class TaskRepository { fun deleteTask(task: TaskDetailResponse): TasksResponse { when (task.status) { Status.TODO -> tasks.todo.remove(task) - Status.IN_PROGRESS -> tasks.inProgresses.remove(task) + Status.IN_PROGRESS -> tasks.inProgress.remove(task) else -> tasks.done.remove(task) } return tasks diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index b28fd9170..741504401 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -15,17 +15,16 @@ import com.example.todolist.ui.common.ViewModelFactory class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private val viewModel: TaskViewModel by viewModels { ViewModelFactory() } - private val remoteViewModel: TaskRemoteViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } - private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } - private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } - private val doneAdapter: TaskAdapter by lazy { TaskAdapter(remoteViewModel, this) } + private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) - binding.viewModel = remoteViewModel + binding.viewModel = viewModel binding.lifecycleOwner = this onDrawerEvent() @@ -40,7 +39,10 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } includeInProgress.btnAdd.setOnClickListener { - NewTaskDialogFragment(Status.IN_PROGRESS).show(supportFragmentManager, "inProgressDialog") + NewTaskDialogFragment(Status.IN_PROGRESS).show( + supportFragmentManager, + "inProgressDialog" + ) } includeDone.btnAdd.setOnClickListener { @@ -49,17 +51,17 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } binding.includeTodo.rvTodo.adapter = toDoAdapter - remoteViewModel.todoTask.observe(this) { todoTask -> + viewModel.todoTask.observe(this) { todoTask -> toDoAdapter.submitList(todoTask.toList()) } binding.includeInProgress.rvInProgress.adapter = inProgressAdapter - remoteViewModel.inProgressTask.observe(this) { inProgressTask -> + viewModel.inProgressTask.observe(this) { inProgressTask -> inProgressAdapter.submitList(inProgressTask.toList()) } binding.includeDone.rvDone.adapter = doneAdapter - remoteViewModel.doneTask.observe(this) { doneTask -> + viewModel.doneTask.observe(this) { doneTask -> doneAdapter.submitList(doneTask.toList()) } diff --git a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt index 1a9f42a63..71067db3b 100644 --- a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt @@ -17,7 +17,7 @@ import com.example.todolist.model.Task class NewTaskDialogFragment(private val status: Status) : DialogFragment() { private lateinit var binding: DialogNewCardBinding - private val remoteViewModel: TaskRemoteViewModel by activityViewModels() + private val viewModel: TaskViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -48,7 +48,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.TODO ) - remoteViewModel.addTask(task) + viewModel.addTodoTask(task) } Status.IN_PROGRESS -> { val task = Task( @@ -56,7 +56,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.IN_PROGRESS ) - remoteViewModel.addTask(task) + viewModel.addInProgressTask(task) } else -> { val task = Task( @@ -64,7 +64,7 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.etContents.text.toString(), Status.DONE ) - remoteViewModel.addTask(task) + viewModel.addDoneTask(task) } } dismiss() diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index ef57ad27c..a554d72d8 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -10,7 +10,7 @@ import com.example.todolist.databinding.ItemTaskBinding import com.example.todolist.model.response.TaskDetailResponse class TaskAdapter( - private val viewModel: TaskRemoteViewModel, + private val viewModel: TaskViewModel, private val listener: DialogListener ) : ListAdapter(TaskDiffCallback) { diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index 37d790b0a..bc03bf80c 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -61,21 +61,24 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository taskRemoteRepository.modifyTask(modifyTaskRequest)?.let { when (it.status) { Status.TODO -> { - val originalTask = _todoTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val originalTask = + _todoTask.value?.find { resources -> modifyTaskRequest.id == resources.id } val index = _todoTask.value?.indexOf(originalTask) if (index != null) { _todoTask.value?.set(index, it) } } Status.IN_PROGRESS -> { - val originalTask = _inProgressTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val originalTask = + _inProgressTask.value?.find { resources -> modifyTaskRequest.id == resources.id } val index = _inProgressTask.value?.indexOf(originalTask) if (index != null) { _inProgressTask.value?.set(index, it) } } Status.DONE -> { - val originalTask = _doneTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + val originalTask = + _doneTask.value?.find { resources -> modifyTaskRequest.id == resources.id } val index = _doneTask.value?.indexOf(originalTask) if (index != null) { _doneTask.value?.set(index, it) diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index ef2245378..8cf22b856 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -32,7 +32,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { private fun loadTasks() { val tasks = repository.getTasks() _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgresses + _inProgressTask.value = tasks.inProgress _doneTask.value = tasks.done } @@ -47,7 +47,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun addInProgressTask(task: Task) { val tasks = repository.addTask(task) - _inProgressTask.value = tasks.inProgresses + _inProgressTask.value = tasks.inProgress } fun addDoneTask(task: Task) { @@ -58,14 +58,14 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun moveDone(task: TaskDetailResponse) { val tasks = repository.moveDone(task) _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgresses + _inProgressTask.value = tasks.inProgress _doneTask.value = tasks.done } fun deleteTask(task: TaskDetailResponse) { val tasks = repository.deleteTask(task) _todoTask.value = tasks.todo - _inProgressTask.value = tasks.inProgresses + _inProgressTask.value = tasks.inProgress _doneTask.value = tasks.done } @@ -76,7 +76,7 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { fun updateInProgressTask(task: TaskDetailResponse) { val tasks = repository.updateTask(task) - _inProgressTask.value = tasks.inProgresses + _inProgressTask.value = tasks.inProgress } fun updateDoneTask(task: TaskDetailResponse) { diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt index 44120ca98..eee7403a8 100644 --- a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -19,7 +19,7 @@ import com.example.todolist.model.response.TaskDetailResponse class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { private lateinit var binding: DialogUpdateCardBinding - private val viewModel: TaskRemoteViewModel by activityViewModels() + private val viewModel: TaskViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -45,8 +45,15 @@ class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFra binding.etContents.setText(task.content) binding.btnUpdate.setOnClickListener { - val updateTask = ModifyTaskRequest(task.id, binding.etTitle.text.toString(), binding.etContents.text.toString()) - viewModel.modifyTask(updateTask) + val updateTask = task.copy( + title = binding.etTitle.text.toString(), + content = binding.etContents.text.toString() + ) + when (task.status) { + Status.TODO -> viewModel.updateTodoTask(updateTask) + Status.IN_PROGRESS -> viewModel.updateInProgressTask(updateTask) + else -> viewModel.updateDoneTask(updateTask) + } dismiss() } } diff --git a/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt b/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt index 5e92d4669..766bef821 100644 --- a/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt +++ b/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt @@ -20,11 +20,13 @@ fun stringFormat(view: TextView, history: History) { view.context.getString(R.string.action_default, nowStatus, title, "삭제").htmlToString() UPDATE -> view.text = view.context.getString(R.string.action_default, nowStatus, title, "변경").htmlToString() - MOVE -> view.text = view.context.getString(R.string.action_move, + MOVE -> view.text = view.context.getString( + R.string.action_move, title, beforeStatus, nowStatus, - "이동").htmlToString() + "이동" + ).htmlToString() } } diff --git a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml index cc5c30e03..aacdd017c 100644 --- a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml +++ b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml @@ -5,12 +5,8 @@ xmlns:tools="http://schemas.android.com/tools"> - - diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index cc5c30e03..cbd1cbe67 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -8,9 +8,6 @@ - diff --git a/android/app/src/main/res/layout/view_done.xml b/android/app/src/main/res/layout/view_done.xml index b51b0a8c5..fafe36514 100644 --- a/android/app/src/main/res/layout/view_done.xml +++ b/android/app/src/main/res/layout/view_done.xml @@ -7,7 +7,7 @@ + type="com.example.todolist.ui.TaskViewModel" /> + type="com.example.todolist.ui.TaskViewModel" /> + type="com.example.todolist.ui.TaskViewModel" /> Date: Wed, 13 Apr 2022 18:00:42 +0900 Subject: [PATCH 06/18] feat: drag-drop-swipe-#40 --- .../todolist/repository/TaskRepository.kt | 14 ++ .../example/todolist/ui/ItemTouchCallback.kt | 128 ++++++++++++++++++ .../todolist/ui/ItemTouchHelperListener.kt | 7 + .../com/example/todolist/ui/MainActivity.kt | 34 ++++- .../com/example/todolist/ui/TaskAdapter.kt | 17 ++- .../com/example/todolist/ui/TaskViewModel.kt | 7 + .../main/res/drawable/item_background_red.xml | 6 + android/app/src/main/res/layout/item_task.xml | 95 +++++++++---- android/app/src/main/res/values/colors.xml | 1 + android/app/src/main/res/values/strings.xml | 1 + android/app/src/main/res/values/styles.xml | 4 + 11 files changed, 278 insertions(+), 36 deletions(-) create mode 100644 android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt create mode 100644 android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt create mode 100644 android/app/src/main/res/drawable/item_background_red.xml diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index b67e09914..6ad7db06b 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -3,6 +3,7 @@ package com.example.todolist.repository import com.example.todolist.model.* import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse +import java.util.* class TaskRepository { @@ -123,6 +124,19 @@ class TaskRepository { return tasks } + fun swap( + currentList: List, + fromPosition: Int, + toPosition: Int, + ): TasksResponse { + when (currentList) { + tasks.todo -> Collections.swap(tasks.todo, fromPosition, toPosition) + tasks.inProgress -> Collections.swap(tasks.inProgress, fromPosition, toPosition) + tasks.done -> Collections.swap(tasks.done, fromPosition, toPosition) + } + return tasks + } + fun getHistory(): List { return listOf( History(4, ActionType.MOVE, "HTML/CSS공부하기", "해야할 일", "하고 있는 일", "2022-04-05 21:19:00"), diff --git a/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt new file mode 100644 index 000000000..2a3d7834b --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt @@ -0,0 +1,128 @@ +package com.example.todolist.ui + +import android.graphics.Canvas +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView +import com.example.todolist.R +import kotlin.math.max +import kotlin.math.min + +class ItemTouchCallback( + private var clamp: Float, + private val listener: ItemTouchHelperListener, +) : ItemTouchHelper.Callback() { + + private var currentPosition: Int? = null + private var previousPosition: Int? = null + private var currentDX = 0f + + override fun getMovementFlags( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + ): Int { + return makeMovementFlags( + ItemTouchHelper.UP or ItemTouchHelper.DOWN, + ItemTouchHelper.START or ItemTouchHelper.END + ) + } + + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder, + ): Boolean { + listener.onItemMove(viewHolder.adapterPosition, target.adapterPosition) + return true + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} + + override fun getSwipeEscapeVelocity(defaultValue: Float): Float { + return defaultValue * 10 + } + + override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float { + val isClamped = getTag(viewHolder) + setTag(viewHolder, !isClamped && currentDX <= -clamp) + return 2f + } + + override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { + currentDX = 0f + previousPosition = viewHolder.adapterPosition + getDefaultUIUtil().clearView(getView(viewHolder)) + } + + override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { + viewHolder?.let { + currentPosition = viewHolder.adapterPosition + getDefaultUIUtil().onSelected(getView(it)) + } + } + + override fun onChildDraw( + c: Canvas, + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean, + ) { + if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { + val view = getView(viewHolder) + if (dX < 0) getDeleteView(viewHolder).visibility = View.VISIBLE + else if (dX > 0) getDeleteView(viewHolder).visibility = View.GONE + val isClamped = getTag(viewHolder) + val x = clampViewPositionHorizontal(view, dX, isClamped, isCurrentlyActive) + + currentDX = x + getDefaultUIUtil().onDraw(c, recyclerView, view, x, dY, actionState, isCurrentlyActive) + } + } + + private fun clampViewPositionHorizontal( + view: View, + dX: Float, + isClamped: Boolean, + isCurrentlyActive: Boolean, + ): Float { + val min: Float = -view.width.toFloat() / 2 + val max: Float = 0f + val x = if (isClamped) { + if (isCurrentlyActive) dX - clamp else -clamp + } else { + dX + } + return min(max(min, x), max) + } + + fun removePreviousClamp(recyclerView: RecyclerView) { + if (currentPosition == previousPosition) return + previousPosition?.let { + val viewHolder = recyclerView.findViewHolderForAdapterPosition(it) ?: return + getView(viewHolder).translationX = 0f + setTag(viewHolder, false) + previousPosition = null + } + } + + private fun getTag(viewHolder: RecyclerView.ViewHolder): Boolean { + return viewHolder.itemView.findViewById(R.id.swipe_view).tag as? Boolean + ?: false + } + + private fun setTag(viewHolder: RecyclerView.ViewHolder, isClamped: Boolean) { + viewHolder.itemView.findViewById(R.id.swipe_view).tag = isClamped + } + + private fun getView(viewHolder: RecyclerView.ViewHolder): View { + return (viewHolder as TaskAdapter.TaskViewHolder).itemView.findViewById(R.id.swipe_view) + } + + private fun getDeleteView(viewHolder: RecyclerView.ViewHolder): View { + return (viewHolder as TaskAdapter.TaskViewHolder).itemView.findViewById(R.id.cl_delete) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt b/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt new file mode 100644 index 000000000..9b2e9907a --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt @@ -0,0 +1,7 @@ +package com.example.todolist.ui + +interface ItemTouchHelperListener { + fun onItemMove(fromPosition: Int, toPosition: Int): Boolean + + fun onItemSwipe(position: Int) +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index 741504401..acb249e50 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.* import androidx.activity.viewModels import androidx.databinding.DataBindingUtil +import androidx.recyclerview.widget.ItemTouchHelper import com.example.todolist.R import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status @@ -20,6 +21,7 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } private val inProgressAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } private val doneAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } + private val clamp: Float = 170f override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -50,21 +52,47 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } } - binding.includeTodo.rvTodo.adapter = toDoAdapter + val todoItemTouchCallback = ItemTouchCallback(clamp, toDoAdapter) + with(binding.includeTodo.rvTodo) { + ItemTouchHelper(todoItemTouchCallback).attachToRecyclerView(this) + adapter = toDoAdapter + setOnTouchListener { _, _ -> + todoItemTouchCallback.removePreviousClamp(this) + false + } + } viewModel.todoTask.observe(this) { todoTask -> toDoAdapter.submitList(todoTask.toList()) } - binding.includeInProgress.rvInProgress.adapter = inProgressAdapter + val inProgressItemTouchCallback = ItemTouchCallback(clamp, inProgressAdapter) + with(binding.includeInProgress.rvInProgress) { + ItemTouchHelper(inProgressItemTouchCallback).attachToRecyclerView(this) + adapter = inProgressAdapter + setOnTouchListener { _, _ -> + inProgressItemTouchCallback.removePreviousClamp(this) + false + } + } viewModel.inProgressTask.observe(this) { inProgressTask -> inProgressAdapter.submitList(inProgressTask.toList()) } + + binding.includeDone.rvDone.adapter = doneAdapter + val doneItemTouchCallback = ItemTouchCallback(clamp, doneAdapter) + with(binding.includeDone.rvDone) { + ItemTouchHelper(doneItemTouchCallback).attachToRecyclerView(this) + adapter = doneAdapter + setOnTouchListener { _, _ -> + doneItemTouchCallback.removePreviousClamp(this) + false + } + } viewModel.doneTask.observe(this) { doneTask -> doneAdapter.submitList(doneTask.toList()) } - } private fun onDrawerEvent() { diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index a554d72d8..acca75db1 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -11,8 +11,9 @@ import com.example.todolist.model.response.TaskDetailResponse class TaskAdapter( private val viewModel: TaskViewModel, - private val listener: DialogListener -) : ListAdapter(TaskDiffCallback) { + private val listener: DialogListener, +) : ListAdapter(TaskDiffCallback), + ItemTouchHelperListener { interface DialogListener { fun updateDialog(task: TaskDetailResponse) @@ -27,7 +28,7 @@ class TaskAdapter( holder.bind(getItem(position)) } - inner class TaskViewHolder(private val binding: ItemTaskBinding) : + inner class TaskViewHolder(private val binding: ItemTaskBinding) : RecyclerView.ViewHolder(binding.root), PopupMenu.OnMenuItemClickListener { private lateinit var task: TaskDetailResponse @@ -36,6 +37,7 @@ class TaskAdapter( this.task = task binding.task = task binding.executePendingBindings() + binding.clDelete.setOnClickListener { onItemSwipe(layoutPosition) } itemView.setOnLongClickListener { showPopup(it) true @@ -59,6 +61,15 @@ class TaskAdapter( return item != null } } + + override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { + viewModel.swapTask(currentList, fromPosition, toPosition) + return true + } + + override fun onItemSwipe(position: Int) { + viewModel.deleteTask(getItem(position)) + } } object TaskDiffCallback : DiffUtil.ItemCallback() { diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt index 8cf22b856..f22923df1 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskViewModel.kt @@ -83,4 +83,11 @@ class TaskViewModel(private val repository: TaskRepository) : ViewModel() { val tasks = repository.updateTask(task) _doneTask.value = tasks.done } + + fun swapTask(currentList: List, fromPosition: Int, toPosition: Int) { + val tasks = repository.swap(currentList, fromPosition, toPosition) + _todoTask.value = tasks.todo + _inProgressTask.value = tasks.inProgress + _doneTask.value = tasks.done + } } \ No newline at end of file diff --git a/android/app/src/main/res/drawable/item_background_red.xml b/android/app/src/main/res/drawable/item_background_red.xml new file mode 100644 index 000000000..730dbefbf --- /dev/null +++ b/android/app/src/main/res/drawable/item_background_red.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/layout/item_task.xml b/android/app/src/main/res/layout/item_task.xml index 4b786392e..85a836f4f 100644 --- a/android/app/src/main/res/layout/item_task.xml +++ b/android/app/src/main/res/layout/item_task.xml @@ -12,46 +12,81 @@ - - + android:layout_height="wrap_content"> - + app:layout_constraintTop_toTopOf="parent"> - + + + + app:layout_constraintTop_toTopOf="parent"> + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 4234664d2..08bee8ec2 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -14,4 +14,5 @@ #FFFFFFFF #0075DE #86C6FF + #FF0000 \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 7b322f192..876dd6835 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -25,4 +25,5 @@ 완료한 일로 이동 수정하기 삭제하기 + 삭제 \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index b22d6c086..938bf6010 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -22,6 +22,10 @@ 14sp + + From 4d297df4cb745d2fa9e522ea5fdbb1831793bbbf Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 11:10:57 +0900 Subject: [PATCH 07/18] =?UTF-8?q?feat:=20ItemTouchCallback=20=EC=B1=85?= =?UTF-8?q?=EC=9E=84=20=EB=B6=84=EB=A6=AC-#59?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/todolist/ui/ItemTouchCallback.kt | 41 ++++++------------- .../com/example/todolist/ui/TaskAdapter.kt | 24 ++++++++++- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt index 2a3d7834b..1c200b6de 100644 --- a/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt +++ b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt @@ -2,10 +2,8 @@ package com.example.todolist.ui import android.graphics.Canvas import android.view.View -import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView -import com.example.todolist.R import kotlin.math.max import kotlin.math.min @@ -44,21 +42,21 @@ class ItemTouchCallback( } override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float { - val isClamped = getTag(viewHolder) - setTag(viewHolder, !isClamped && currentDX <= -clamp) + val isClamped = (viewHolder as TaskAdapter.TaskViewHolder).getTag() + viewHolder.setTag(!isClamped && currentDX <= -clamp) return 2f } override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { currentDX = 0f previousPosition = viewHolder.adapterPosition - getDefaultUIUtil().clearView(getView(viewHolder)) + getDefaultUIUtil().clearView((viewHolder as TaskAdapter.TaskViewHolder).getView()) } override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { viewHolder?.let { currentPosition = viewHolder.adapterPosition - getDefaultUIUtil().onSelected(getView(it)) + getDefaultUIUtil().onSelected((viewHolder as TaskAdapter.TaskViewHolder).getView()) } } @@ -71,11 +69,12 @@ class ItemTouchCallback( actionState: Int, isCurrentlyActive: Boolean, ) { + val taskViewHolder = viewHolder as TaskAdapter.TaskViewHolder if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { - val view = getView(viewHolder) - if (dX < 0) getDeleteView(viewHolder).visibility = View.VISIBLE - else if (dX > 0) getDeleteView(viewHolder).visibility = View.GONE - val isClamped = getTag(viewHolder) + val view = taskViewHolder.getView() + if (dX < 0) taskViewHolder.setVisibility(View.VISIBLE) + else if (dX > 0) taskViewHolder.setVisibility(View.GONE) + val isClamped = taskViewHolder.getTag() val x = clampViewPositionHorizontal(view, dX, isClamped, isCurrentlyActive) currentDX = x @@ -103,26 +102,10 @@ class ItemTouchCallback( if (currentPosition == previousPosition) return previousPosition?.let { val viewHolder = recyclerView.findViewHolderForAdapterPosition(it) ?: return - getView(viewHolder).translationX = 0f - setTag(viewHolder, false) + val taskViewHolder = viewHolder as TaskAdapter.TaskViewHolder + taskViewHolder.getView().translationX = 0f + taskViewHolder.setTag(false) previousPosition = null } } - - private fun getTag(viewHolder: RecyclerView.ViewHolder): Boolean { - return viewHolder.itemView.findViewById(R.id.swipe_view).tag as? Boolean - ?: false - } - - private fun setTag(viewHolder: RecyclerView.ViewHolder, isClamped: Boolean) { - viewHolder.itemView.findViewById(R.id.swipe_view).tag = isClamped - } - - private fun getView(viewHolder: RecyclerView.ViewHolder): View { - return (viewHolder as TaskAdapter.TaskViewHolder).itemView.findViewById(R.id.swipe_view) - } - - private fun getDeleteView(viewHolder: RecyclerView.ViewHolder): View { - return (viewHolder as TaskAdapter.TaskViewHolder).itemView.findViewById(R.id.cl_delete) - } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index acca75db1..1ceea317a 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -60,6 +60,20 @@ class TaskAdapter( } return item != null } + + fun getView(): View = binding.swipeView + + private fun getDeleteView(): View = binding.clDelete + + fun setVisibility(visibility: Int) { + getDeleteView().visibility = visibility + } + + fun getTag(): Boolean = binding.swipeView.tag as? Boolean ?: false + + fun setTag(isClamped: Boolean) { + binding.swipeView.tag = isClamped + } } override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { @@ -73,11 +87,17 @@ class TaskAdapter( } object TaskDiffCallback : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: TaskDetailResponse, newItem: TaskDetailResponse): Boolean { + override fun areItemsTheSame( + oldItem: TaskDetailResponse, + newItem: TaskDetailResponse, + ): Boolean { return oldItem.id == newItem.id } - override fun areContentsTheSame(oldItem: TaskDetailResponse, newItem: TaskDetailResponse): Boolean { + override fun areContentsTheSame( + oldItem: TaskDetailResponse, + newItem: TaskDetailResponse, + ): Boolean { return oldItem == newItem } From 09cf4330b9913d38429100b8f459f786f0dcaad4 Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 11:28:58 +0900 Subject: [PATCH 08/18] =?UTF-8?q?fix:=20setOnTouchListener=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=A0=EB=AC=B8=EA=B3=A0=ED=95=B4=EA=B2=B0-#59?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/example/todolist/ui/MainActivity.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index acb249e50..a2cb94f14 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -9,8 +9,6 @@ import androidx.recyclerview.widget.ItemTouchHelper import com.example.todolist.R import com.example.todolist.databinding.ActivityMainBinding import com.example.todolist.model.Status -import com.example.todolist.model.Task -import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.ui.common.ViewModelFactory @@ -56,8 +54,9 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { with(binding.includeTodo.rvTodo) { ItemTouchHelper(todoItemTouchCallback).attachToRecyclerView(this) adapter = toDoAdapter - setOnTouchListener { _, _ -> + setOnTouchListener { view, _ -> todoItemTouchCallback.removePreviousClamp(this) + view.performClick() false } } @@ -69,8 +68,9 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { with(binding.includeInProgress.rvInProgress) { ItemTouchHelper(inProgressItemTouchCallback).attachToRecyclerView(this) adapter = inProgressAdapter - setOnTouchListener { _, _ -> + setOnTouchListener { view, _ -> inProgressItemTouchCallback.removePreviousClamp(this) + view.performClick() false } } @@ -85,8 +85,9 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { with(binding.includeDone.rvDone) { ItemTouchHelper(doneItemTouchCallback).attachToRecyclerView(this) adapter = doneAdapter - setOnTouchListener { _, _ -> + setOnTouchListener { view, _ -> doneItemTouchCallback.removePreviousClamp(this) + view.performClick() false } } From 2b86c38529670ea1167ff4b4977ee79b79d97cd3 Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 11:31:02 +0900 Subject: [PATCH 09/18] =?UTF-8?q?chore:=20LoadTaskResponse.kt=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=ED=8C=8C=EC=9D=BC=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0-#59?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/response/LoadTasksResponse.kt | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt diff --git a/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt deleted file mode 100644 index 2f4320141..000000000 --- a/android/app/src/main/java/com/example/todolist/model/response/LoadTasksResponse.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.example.todolist.model.response - -data class LoadTasksResponse( - val doneCollection: MutableList, - val inProgressCollection: MutableList, - val todoCollection: MutableList -) - -data class DoneCollection( - val author: String, - val contents: String, - val id: Int, - val status: String, - val title: String -) - -data class InProgressCollection( - val author: String, - val contents: String, - val id: Int, - val status: String, - val title: String -) - -data class TodoCollection( - val author: String, - val contents: String, - val id: Int, - val status: String, - val title: String -) \ No newline at end of file From 32fc36a5536c2505119d1f33fdcb914821f38605 Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 14:09:44 +0900 Subject: [PATCH 10/18] =?UTF-8?q?feat:=20todo,=20inProgress,=20done=20?= =?UTF-8?q?=ED=99=9C=EB=8F=99=20=EC=A1=B0=ED=9A=8C-#62?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/AndroidManifest.xml | 3 ++ .../todolist/model/response/TasksResponse.kt | 6 ++-- .../com/example/todolist/network/Result.kt | 6 ++++ .../example/todolist/network/RetrofitAPI.kt | 2 +- .../com/example/todolist/network/Service.kt | 6 ++-- .../todolist/repository/TaskDataSource.kt | 7 ++-- .../repository/TaskRemoteDataSource.kt | 25 ++++--------- .../repository/TaskRemoteRepository.kt | 15 +++++--- .../com/example/todolist/ui/MainActivity.kt | 35 +++++++++++-------- .../com/example/todolist/ui/TaskAdapter.kt | 14 +++++--- .../todolist/ui/TaskRemoteViewModel.kt | 19 +++++++--- .../res/layout-sw720dp-land/activity_main.xml | 2 +- .../app/src/main/res/layout/activity_main.xml | 3 +- android/app/src/main/res/layout/view_done.xml | 2 +- .../src/main/res/layout/view_in_progress.xml | 2 +- android/app/src/main/res/layout/view_todo.xml | 2 +- android/app/src/main/res/values/strings.xml | 2 ++ 17 files changed, 87 insertions(+), 64 deletions(-) create mode 100644 android/app/src/main/java/com/example/todolist/network/Result.kt diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 105682e23..c5ff89c45 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,10 @@ + + , ) -data class Result( +data class CommonResponse( val status: Int, - val taskDetailResponse: TaskDetailResponse + val taskDetailResponse: TaskDetailResponse, ) data class TaskDetailResponse( @@ -23,5 +23,5 @@ data class TaskDetailResponse( val content: String, val status: Status, val author: String = "Android", - val updateDateTime: String? = null + val updateDateTime: String? = null, ) \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/Result.kt b/android/app/src/main/java/com/example/todolist/network/Result.kt new file mode 100644 index 000000000..1bc88db84 --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/network/Result.kt @@ -0,0 +1,6 @@ +package com.example.todolist.network + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val error: String) : Result() +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt b/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt index c536d6742..4caaabef1 100644 --- a/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt +++ b/android/app/src/main/java/com/example/todolist/network/RetrofitAPI.kt @@ -6,7 +6,7 @@ import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory object RetrofitAPI { - private const val BASE_URL = "www.louie-03.com/" + private const val BASE_URL = "http://www.louie-03.com/" private val okHttpClient: OkHttpClient by lazy { OkHttpClient.Builder() diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index 121628d5e..002d90dfb 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -2,7 +2,7 @@ package com.example.todolist.network import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest -import com.example.todolist.model.response.Result +import com.example.todolist.model.response.CommonResponse import com.example.todolist.model.response.TasksResponse import retrofit2.Response import retrofit2.http.* @@ -15,12 +15,12 @@ interface Service { @Headers("Content-Type: application/json") @POST("cards") - suspend fun saveTask(@Body cardInfo: Task): Response + suspend fun saveTask(@Body cardInfo: Task): Response @Headers("Content-Type: application/json") @PATCH("cards/{id}") suspend fun modifyTask( @Path("id") id: Int, @Body modifyTaskRequest: ModifyTaskRequest - ): Response + ): Response } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index 67cf939c6..3209c9432 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -2,15 +2,14 @@ package com.example.todolist.repository import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest -import com.example.todolist.model.response.Result -import com.example.todolist.model.response.TaskDetailResponse +import com.example.todolist.model.response.CommonResponse import com.example.todolist.model.response.TasksResponse interface TaskDataSource { suspend fun loadTasks(): TasksResponse? - suspend fun addTask(cardData: Task): Result? + suspend fun addTask(cardData: Task): CommonResponse? - suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): Result? + suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): CommonResponse? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index 8f947f336..c62dae805 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -3,30 +3,19 @@ package com.example.todolist.repository import android.util.Log import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest -import com.example.todolist.model.response.Result +import com.example.todolist.model.response.CommonResponse import com.example.todolist.model.response.TasksResponse import com.example.todolist.network.RetrofitAPI class TaskRemoteDataSource : TaskDataSource { override suspend fun loadTasks(): TasksResponse? { - var task: TasksResponse? = null - - val service = RetrofitAPI.service - val response = service.loadTasks() - if (response.isSuccessful) { - val result = response.body() - task = result - Log.d("카드 조회 성공", "$result") - } else { - // TODO 실패했을 시 담을 데이터 정하기 - Log.d("카드 조회 실패", "${response.code()}") - } - return task + val response = RetrofitAPI.service.loadTasks() + return if (response.isSuccessful) response.body() else null } - override suspend fun addTask(cardData: Task): Result? { - var task: Result? = null + override suspend fun addTask(cardData: Task): CommonResponse? { + var task: CommonResponse? = null val service = RetrofitAPI.service val response = service.saveTask(cardData) @@ -41,8 +30,8 @@ class TaskRemoteDataSource : TaskDataSource { return task } - override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): Result? { - var task: Result? = null + override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): CommonResponse? { + var task: CommonResponse? = null val service = RetrofitAPI.service val response = service.modifyTask(modifyTaskRequest.id, modifyTaskRequest) diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index ae8d65f9f..3166f9a64 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -1,20 +1,25 @@ package com.example.todolist.repository +import com.example.todolist.network.Result import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest -import com.example.todolist.model.response.Result +import com.example.todolist.model.response.CommonResponse import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse class TaskRemoteRepository( - private val taskRemoteDataSource: TaskRemoteDataSource + private val taskRemoteDataSource: TaskRemoteDataSource, ) { - suspend fun loadTask(): TasksResponse? { - return taskRemoteDataSource.loadTasks() + suspend fun loadTask(): Result { + val response = taskRemoteDataSource.loadTasks() + response?.let { + return Result.Success(it) + } + return Result.Error("error") } - suspend fun addTask(cardData: Task): Result? { + suspend fun addTask(cardData: Task): CommonResponse? { return taskRemoteDataSource.addTask(cardData) } diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index a2cb94f14..bce838552 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -3,6 +3,7 @@ package com.example.todolist.ui import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.* +import android.widget.Toast import androidx.activity.viewModels import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.ItemTouchHelper @@ -13,7 +14,7 @@ import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.ui.common.ViewModelFactory class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { - private val viewModel: TaskViewModel by viewModels { ViewModelFactory() } + private val viewModel: TaskRemoteViewModel by viewModels { ViewModelFactory() } private lateinit var binding: ActivityMainBinding private val historyAdapter: HistoryAdapter by lazy { HistoryAdapter() } private val toDoAdapter: TaskAdapter by lazy { TaskAdapter(viewModel, this) } @@ -26,11 +27,15 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.viewModel = viewModel binding.lifecycleOwner = this - onDrawerEvent() +// onDrawerEvent() - binding.rvHistory.adapter = historyAdapter - viewModel.history.observe(this) { histories -> - historyAdapter.submitList(histories) +// binding.rvHistory.adapter = historyAdapter +// viewModel.history.observe(this) { histories -> +// historyAdapter.submitList(histories) +// } + + viewModel.error.observe(this) { + Toast.makeText(this, getString(R.string.error_message), Toast.LENGTH_SHORT).show() } with(binding) { @@ -96,16 +101,16 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } } - private fun onDrawerEvent() { - binding.btnDrawer.setOnClickListener { - viewModel.loadDummyData() - binding.dlDrawer.openDrawer(Gravity.RIGHT) - } - - binding.btnClose.setOnClickListener { - binding.dlDrawer.closeDrawer(Gravity.RIGHT) - } - } +// private fun onDrawerEvent() { +// binding.btnDrawer.setOnClickListener { +// viewModel.loadDummyData() +// binding.dlDrawer.openDrawer(Gravity.RIGHT) +// } +// +// binding.btnClose.setOnClickListener { +// binding.dlDrawer.closeDrawer(Gravity.RIGHT) +// } +// } override fun updateDialog(task: TaskDetailResponse) { UpdateTaskDialogFragment(task).show(supportFragmentManager, "updateDialog") diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 1ceea317a..303f57060 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -10,7 +10,7 @@ import com.example.todolist.databinding.ItemTaskBinding import com.example.todolist.model.response.TaskDetailResponse class TaskAdapter( - private val viewModel: TaskViewModel, + private val viewModel: TaskRemoteViewModel, private val listener: DialogListener, ) : ListAdapter(TaskDiffCallback), ItemTouchHelperListener { @@ -54,9 +54,13 @@ class TaskAdapter( override fun onMenuItemClick(item: MenuItem?): Boolean { when (item?.itemId) { - R.id.popup_go_done -> viewModel.moveDone(task) + R.id.popup_go_done -> { +// viewModel.moveDone(task) + } R.id.popup_modify -> listener.updateDialog(task) - R.id.popup_delete -> viewModel.deleteTask(task) + R.id.popup_delete -> { +// viewModel.deleteTask(task) + } } return item != null } @@ -77,12 +81,12 @@ class TaskAdapter( } override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { - viewModel.swapTask(currentList, fromPosition, toPosition) +// viewModel.swapTask(currentList, fromPosition, toPosition) return true } override fun onItemSwipe(position: Int) { - viewModel.deleteTask(getItem(position)) +// viewModel.deleteTask(getItem(position)) } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index bc03bf80c..31e0e0bf2 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -1,6 +1,7 @@ package com.example.todolist.ui import androidx.lifecycle.LiveData +import com.example.todolist.network.Result import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -25,16 +26,26 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository val doneTask: LiveData> get() = _doneTask + private val _error = MutableLiveData() + val error: LiveData + get() = _error + init { loadTasks() } private fun loadTasks() { viewModelScope.launch { - val tasks = taskRemoteRepository.loadTask() - _todoTask.value = tasks?.todo - _inProgressTask.value = tasks?.inProgress - _doneTask.value = tasks?.done + when (val tasks = taskRemoteRepository.loadTask()) { + is Result.Success -> { + _todoTask.value = tasks.data.todo + _inProgressTask.value = tasks.data.inProgress + _doneTask.value = tasks.data.done + } + is Result.Error -> { + _error.value = tasks.error + } + } } } diff --git a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml index aacdd017c..4e475800a 100644 --- a/android/app/src/main/res/layout-sw720dp-land/activity_main.xml +++ b/android/app/src/main/res/layout-sw720dp-land/activity_main.xml @@ -7,7 +7,7 @@ + type="com.example.todolist.ui.TaskRemoteViewModel" /> - + type="com.example.todolist.ui.TaskRemoteViewModel" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> + type="com.example.todolist.ui.TaskRemoteViewModel" /> 수정하기 삭제하기 삭제 + + 서버와의 연결이 실패했습니다. \ No newline at end of file From 573f0e845a2b6a1b9387872705fd77dd4a47175c Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 14:22:39 +0900 Subject: [PATCH 11/18] =?UTF-8?q?feat:=20todo,=20inProgress,=20done=20?= =?UTF-8?q?=ED=99=9C=EB=8F=99=20=EC=A1=B0=ED=9A=8C-#62?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/todolist/ui/MainActivity.kt | 30 +++++++++---------- .../com/example/todolist/ui/TaskAdapter.kt | 12 +++----- .../todolist/ui/TaskRemoteViewModel.kt | 25 ++++++++++++++++ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index bce838552..d9cb27371 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -27,12 +27,12 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.viewModel = viewModel binding.lifecycleOwner = this -// onDrawerEvent() + onDrawerEvent() -// binding.rvHistory.adapter = historyAdapter -// viewModel.history.observe(this) { histories -> -// historyAdapter.submitList(histories) -// } + binding.rvHistory.adapter = historyAdapter + viewModel.history.observe(this) { histories -> + historyAdapter.submitList(histories) + } viewModel.error.observe(this) { Toast.makeText(this, getString(R.string.error_message), Toast.LENGTH_SHORT).show() @@ -101,16 +101,16 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } } -// private fun onDrawerEvent() { -// binding.btnDrawer.setOnClickListener { -// viewModel.loadDummyData() -// binding.dlDrawer.openDrawer(Gravity.RIGHT) -// } -// -// binding.btnClose.setOnClickListener { -// binding.dlDrawer.closeDrawer(Gravity.RIGHT) -// } -// } + private fun onDrawerEvent() { + binding.btnDrawer.setOnClickListener { + viewModel.loadDummyData() + binding.dlDrawer.openDrawer(Gravity.RIGHT) + } + + binding.btnClose.setOnClickListener { + binding.dlDrawer.closeDrawer(Gravity.RIGHT) + } + } override fun updateDialog(task: TaskDetailResponse) { UpdateTaskDialogFragment(task).show(supportFragmentManager, "updateDialog") diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 303f57060..1ecc6bb44 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -54,13 +54,9 @@ class TaskAdapter( override fun onMenuItemClick(item: MenuItem?): Boolean { when (item?.itemId) { - R.id.popup_go_done -> { -// viewModel.moveDone(task) - } + R.id.popup_go_done -> viewModel.moveDone(task) R.id.popup_modify -> listener.updateDialog(task) - R.id.popup_delete -> { -// viewModel.deleteTask(task) - } + R.id.popup_delete -> viewModel.deleteTask(task) } return item != null } @@ -81,12 +77,12 @@ class TaskAdapter( } override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { -// viewModel.swapTask(currentList, fromPosition, toPosition) + viewModel.swapTask(currentList, fromPosition, toPosition) return true } override fun onItemSwipe(position: Int) { -// viewModel.deleteTask(getItem(position)) + viewModel.deleteTask(getItem(position)) } } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index 31e0e0bf2..e44c2ec67 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -5,6 +5,7 @@ import com.example.todolist.network.Result import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.todolist.model.History import com.example.todolist.model.Status import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest @@ -14,6 +15,10 @@ import kotlinx.coroutines.launch class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository) : ViewModel() { + private val _history = MutableLiveData>() + val history: LiveData> + get() = _history + private val _todoTask = MutableLiveData>() val todoTask: LiveData> get() = _todoTask @@ -99,4 +104,24 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository } } } + + fun loadDummyData() {} + + fun addTodoTask(task: Task) {} + + fun addInProgressTask(task: Task) {} + + fun addDoneTask(task: Task) {} + + fun moveDone(task: TaskDetailResponse) {} + + fun deleteTask(task: TaskDetailResponse) {} + + fun updateTodoTask(task: TaskDetailResponse) {} + + fun updateInProgressTask(task: TaskDetailResponse) {} + + fun updateDoneTask(task: TaskDetailResponse) {} + + fun swapTask(currentList: List, fromPosition: Int, toPosition: Int) {} } \ No newline at end of file From edf6f709c4bae883aeb2fd4e1cf040981e8b58dd Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 17:07:36 +0900 Subject: [PATCH 12/18] =?UTF-8?q?feat:=20=ED=9E=88=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20=ED=86=B5?= =?UTF-8?q?=EC=8B=A0-#65?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/todolist/common/extensions.kt | 13 +++----- .../com/example/todolist/model/History.kt | 2 +- .../com/example/todolist/network/Service.kt | 5 +++ .../todolist/repository/TaskDataSource.kt | 3 ++ .../repository/TaskRemoteDataSource.kt | 6 ++++ .../repository/TaskRemoteRepository.kt | 11 +++++++ .../com/example/todolist/ui/MainActivity.kt | 2 +- .../todolist/ui/TaskRemoteViewModel.kt | 13 +++++++- .../todolist/ui/common/TextBindingAdapters.kt | 32 +++++++++++-------- .../app/src/main/res/layout/item_history.xml | 2 +- .../app/src/main/res/values-night/strings.xml | 10 ++++-- android/app/src/main/res/values/strings.xml | 2 +- 12 files changed, 73 insertions(+), 28 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/common/extensions.kt b/android/app/src/main/java/com/example/todolist/common/extensions.kt index e661f95fa..b067b382c 100644 --- a/android/app/src/main/java/com/example/todolist/common/extensions.kt +++ b/android/app/src/main/java/com/example/todolist/common/extensions.kt @@ -1,13 +1,10 @@ package com.example.todolist.common -import android.os.Build -import android.text.Html +import android.text.Spanned +import androidx.core.text.HtmlCompat +import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY -fun String.htmlToString() : String { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY).toString() - } else { - Html.fromHtml(this).toString() - } +fun String.htmlToSpanned() : Spanned { + return HtmlCompat.fromHtml(this, FROM_HTML_MODE_LEGACY) } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/model/History.kt b/android/app/src/main/java/com/example/todolist/model/History.kt index a3a00bcf0..299987f96 100644 --- a/android/app/src/main/java/com/example/todolist/model/History.kt +++ b/android/app/src/main/java/com/example/todolist/model/History.kt @@ -6,7 +6,7 @@ data class History( val title: String, val nowStatus: String, val beforeStatus: String?, - val createData: String, + val createDateTime: String, ) enum class ActionType(val action: String) { diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index 002d90dfb..5ed90dbaa 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -1,5 +1,6 @@ package com.example.todolist.network +import com.example.todolist.model.History import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.CommonResponse @@ -23,4 +24,8 @@ interface Service { @Path("id") id: Int, @Body modifyTaskRequest: ModifyTaskRequest ): Response + + @Headers("Content-Type: application/json") + @GET("activity-logs") + suspend fun loadHistory(): Response> } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index 3209c9432..c4ea895e0 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -1,5 +1,6 @@ package com.example.todolist.repository +import com.example.todolist.model.History import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.CommonResponse @@ -12,4 +13,6 @@ interface TaskDataSource { suspend fun addTask(cardData: Task): CommonResponse? suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): CommonResponse? + + suspend fun loadHistory(): List? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index c62dae805..d5367bdf1 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -1,6 +1,7 @@ package com.example.todolist.repository import android.util.Log +import com.example.todolist.model.History import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.CommonResponse @@ -45,4 +46,9 @@ class TaskRemoteDataSource : TaskDataSource { } return task } + + override suspend fun loadHistory(): List? { + val response = RetrofitAPI.service.loadHistory() + return if (response.isSuccessful) response.body() else null + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 3166f9a64..08cf76f9f 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -1,5 +1,7 @@ package com.example.todolist.repository +import android.util.Log +import com.example.todolist.model.History import com.example.todolist.network.Result import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest @@ -26,4 +28,13 @@ class TaskRemoteRepository( suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { return taskRemoteDataSource.modifyTask(modifyTaskRequest)?.taskDetailResponse } + + suspend fun loadHistory(): Result> { + val response = taskRemoteDataSource.loadHistory() + response?.let { + Log.d("test", "loadHistory: $it") + return Result.Success(it) + } + return Result.Error("error") + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index d9cb27371..c9f4f7c60 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -103,7 +103,7 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { private fun onDrawerEvent() { binding.btnDrawer.setOnClickListener { - viewModel.loadDummyData() + viewModel.loadHistory() binding.dlDrawer.openDrawer(Gravity.RIGHT) } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index e44c2ec67..3badd9132 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -105,7 +105,18 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository } } - fun loadDummyData() {} + fun loadHistory() { + viewModelScope.launch { + when (val history = taskRemoteRepository.loadHistory()) { + is Result.Success -> { + _history.value = history.data + } + is Result.Error -> { + _error.value = history.error + } + } + } + } fun addTodoTask(task: Task) {} diff --git a/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt b/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt index 766bef821..fea5bd71a 100644 --- a/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt +++ b/android/app/src/main/java/com/example/todolist/ui/common/TextBindingAdapters.kt @@ -1,11 +1,10 @@ package com.example.todolist.ui.common -import android.os.Build -import android.text.Html +import android.annotation.SuppressLint import android.widget.TextView import androidx.databinding.BindingAdapter import com.example.todolist.R -import com.example.todolist.common.htmlToString +import com.example.todolist.common.htmlToSpanned import com.example.todolist.model.ActionType.* import com.example.todolist.model.History import java.text.SimpleDateFormat @@ -13,23 +12,30 @@ import java.text.SimpleDateFormat @BindingAdapter("formatting") fun stringFormat(view: TextView, history: History) { val (_, action, title, nowStatus, beforeStatus, _) = history + val now = when (nowStatus) { + "TODO" -> "해야할 일" + "IN_PROGRESS" -> "하고 있는 일" + else -> "완료한 일" + } + val before = when (beforeStatus) { + "TODO" -> "해야할 일" + "IN_PROGRESS" -> "하고 있는 일" + else -> "완료한 일" + } + when (action) { ADD -> view.text = - view.context.getString(R.string.action_default, nowStatus, title, "등록").htmlToString() + view.context.getString(R.string.action_default, now, title, "등록").htmlToSpanned() REMOVE -> view.text = - view.context.getString(R.string.action_default, nowStatus, title, "삭제").htmlToString() + view.context.getString(R.string.action_default, now, title, "삭제").htmlToSpanned() UPDATE -> view.text = - view.context.getString(R.string.action_default, nowStatus, title, "변경").htmlToString() - MOVE -> view.text = view.context.getString( - R.string.action_move, - title, - beforeStatus, - nowStatus, - "이동" - ).htmlToString() + view.context.getString(R.string.action_default, now, title, "변경").htmlToSpanned() + MOVE -> view.text = + view.context.getString(R.string.action_move, title, before, now, "이동").htmlToSpanned() } } +@SuppressLint("SimpleDateFormat") @BindingAdapter("formattingDate") fun dateFormat(view: TextView, stringDate: String) { val format = SimpleDateFormat(view.context.getString(R.string.date_format)) diff --git a/android/app/src/main/res/layout/item_history.xml b/android/app/src/main/res/layout/item_history.xml index 54f72ada9..7f0f04a46 100644 --- a/android/app/src/main/res/layout/item_history.xml +++ b/android/app/src/main/res/layout/item_history.xml @@ -49,7 +49,7 @@ <b>%s</b>에 <b>%s</b>를 <b>%s</b>하였습니다. <b>%s</b>를 <b>%s</b>에서 <b>%s</b>로 <b>%s</b>하였습니다. - yyyy-MM-dd HH:mm:ss + yyyy-MM-dd\'T\'HH:mm:ss 해야 할 일 + 하고 있는 일 + 완료한 일 add_button 새로운 카드 추가 + 카드 수정 등록 + 수정 취소 제목을 입력하세요 내용을 입력하세요 author by %s - 완료한 일로 이동 수정하기 삭제하기 + 삭제 + + 서버와의 연결이 실패했습니다. \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 9a809ac5b..bd6c36dcf 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -7,7 +7,7 @@ <b>%s</b>에 <b>%s</b>를 <b>%s</b>하였습니다. <b>%s</b>를 <b>%s</b>에서 <b>%s</b>로 <b>%s</b>하였습니다. - yyyy-MM-dd HH:mm:ss + yyyy-MM-dd\'T\'HH:mm:ss 해야 할 일 하고 있는 일 From a8d32cb34b86375561b89332576dbf12c5f2c4a0 Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 17:54:49 +0900 Subject: [PATCH 13/18] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EA=B7=B8=EC=82=AD=EC=A0=9C-#65?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/todolist/repository/TaskRemoteRepository.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 08cf76f9f..9d984dbde 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -32,7 +32,6 @@ class TaskRemoteRepository( suspend fun loadHistory(): Result> { val response = taskRemoteDataSource.loadHistory() response?.let { - Log.d("test", "loadHistory: $it") return Result.Success(it) } return Result.Error("error") From 0b0e3afe28d0f9f4f9d49d6c0b80dd4f922115cf Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 21:18:09 +0900 Subject: [PATCH 14/18] feat: delete-api-#66 --- .../java/com/example/todolist/model/Task.kt | 2 +- .../todolist/model/response/TasksResponse.kt | 4 +- .../com/example/todolist/network/Service.kt | 4 ++ .../todolist/repository/TaskDataSource.kt | 2 + .../repository/TaskRemoteDataSource.kt | 5 +++ .../repository/TaskRemoteRepository.kt | 9 ++++- .../todolist/repository/TaskRepository.kt | 6 +-- .../todolist/ui/TaskRemoteViewModel.kt | 40 ++++++++++++++++++- .../todolist/ui/UpdateTaskDialogFragment.kt | 6 +-- android/app/src/main/res/layout/item_task.xml | 2 +- 10 files changed, 66 insertions(+), 14 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/model/Task.kt b/android/app/src/main/java/com/example/todolist/model/Task.kt index d39aa4400..0d7e3b34f 100644 --- a/android/app/src/main/java/com/example/todolist/model/Task.kt +++ b/android/app/src/main/java/com/example/todolist/model/Task.kt @@ -2,7 +2,7 @@ package com.example.todolist.model data class Task( val title: String, - val content: String, + val contents: String, val status: Status, val author: String = "Android" ) diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index d23b3115a..43a07a15e 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -14,13 +14,13 @@ data class TasksResponse( data class CommonResponse( val status: Int, - val taskDetailResponse: TaskDetailResponse, + @SerializedName("resources") val taskDetailResponse: TaskDetailResponse, ) data class TaskDetailResponse( val id: Int, val title: String, - val content: String, + val contents: String, val status: Status, val author: String = "Android", val updateDateTime: String? = null, diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index 5ed90dbaa..83015e9f5 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -28,4 +28,8 @@ interface Service { @Headers("Content-Type: application/json") @GET("activity-logs") suspend fun loadHistory(): Response> + + @DELETE("cards/{id}") + suspend fun deleteTask(@Path("id") id: Int): Response + } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index c4ea895e0..24b3e9aa6 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -15,4 +15,6 @@ interface TaskDataSource { suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): CommonResponse? suspend fun loadHistory(): List? + + suspend fun deleteTask(id: Int): CommonResponse? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index d5367bdf1..7f11c0ce0 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -51,4 +51,9 @@ class TaskRemoteDataSource : TaskDataSource { val response = RetrofitAPI.service.loadHistory() return if (response.isSuccessful) response.body() else null } + + override suspend fun deleteTask(id: Int): CommonResponse? { + val response = RetrofitAPI.service.deleteTask(id) + return if (response.isSuccessful) response.body() else null + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 9d984dbde..91af8ed25 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -1,6 +1,5 @@ package com.example.todolist.repository -import android.util.Log import com.example.todolist.model.History import com.example.todolist.network.Result import com.example.todolist.model.Task @@ -36,4 +35,12 @@ class TaskRemoteRepository( } return Result.Error("error") } + + suspend fun deleteTask(id: Int): Result { + val response = taskRemoteDataSource.deleteTask(id) + response?.let { + return Result.Success(it.taskDetailResponse) + } + return Result.Error("error") + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 6ad7db06b..0a3aba239 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -62,7 +62,7 @@ class TaskRepository { 0, TaskDetailResponse( todoIndex++, task.title, - task.content, + task.contents, task.status ) ) @@ -70,7 +70,7 @@ class TaskRepository { 0, TaskDetailResponse( inProgressIndex++, task.title, - task.content, + task.contents, task.status ) ) @@ -78,7 +78,7 @@ class TaskRepository { 0, TaskDetailResponse( doneIndex++, task.title, - task.content, + task.contents, task.status ) ) diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index 3badd9132..59e657b56 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -19,14 +19,17 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository val history: LiveData> get() = _history + private var todoItem: MutableList = mutableListOf() private val _todoTask = MutableLiveData>() val todoTask: LiveData> get() = _todoTask + private var inProgressItem: MutableList = mutableListOf() private val _inProgressTask = MutableLiveData>() val inProgressTask: LiveData> get() = _inProgressTask + private var doneItem: MutableList = mutableListOf() private val _doneTask = MutableLiveData>() val doneTask: LiveData> get() = _doneTask @@ -43,8 +46,11 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository viewModelScope.launch { when (val tasks = taskRemoteRepository.loadTask()) { is Result.Success -> { + todoItem = tasks.data.todo _todoTask.value = tasks.data.todo + inProgressItem = tasks.data.inProgress _inProgressTask.value = tasks.data.inProgress + doneItem = tasks.data.done _doneTask.value = tasks.data.done } is Result.Error -> { @@ -118,6 +124,38 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository } } + fun deleteTask(task: TaskDetailResponse) { + viewModelScope.launch { + when (val deleteTask = taskRemoteRepository.deleteTask(task.id)) { + is Result.Success -> { + when (deleteTask.data.status) { + Status.TODO -> { + val originalTask = todoItem.find { it.id == deleteTask.data.id } + val index = todoItem.indexOf(originalTask) + if (index != -1) todoItem.removeAt(index) + _todoTask.value = todoItem + } + Status.IN_PROGRESS -> { + val originalTask = inProgressItem.find { it.id == deleteTask.data.id } + val index = inProgressItem.indexOf(originalTask) + if (index != -1) inProgressItem.removeAt(index) + _inProgressTask.value = inProgressItem + } + Status.DONE -> { + val originalTask = doneItem.find { it.id == deleteTask.data.id } + val index = doneItem.indexOf(originalTask) + if (index != -1) doneItem.removeAt(index) + _doneTask.value = doneItem + } + } + } + is Result.Error -> { + _error.value = deleteTask.error + } + } + } + } + fun addTodoTask(task: Task) {} fun addInProgressTask(task: Task) {} @@ -126,8 +164,6 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository fun moveDone(task: TaskDetailResponse) {} - fun deleteTask(task: TaskDetailResponse) {} - fun updateTodoTask(task: TaskDetailResponse) {} fun updateInProgressTask(task: TaskDetailResponse) {} diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt index eee7403a8..d4fd6702c 100644 --- a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -13,8 +13,6 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.example.todolist.databinding.DialogUpdateCardBinding import com.example.todolist.model.Status -import com.example.todolist.model.Task -import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { @@ -42,12 +40,12 @@ class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFra binding.etTitle.addTextChangedListener(titleListener) binding.etContents.addTextChangedListener(contentsListener) binding.etTitle.setText(task.title) - binding.etContents.setText(task.content) + binding.etContents.setText(task.contents) binding.btnUpdate.setOnClickListener { val updateTask = task.copy( title = binding.etTitle.text.toString(), - content = binding.etContents.text.toString() + contents = binding.etContents.text.toString() ) when (task.status) { Status.TODO -> viewModel.updateTodoTask(updateTask) diff --git a/android/app/src/main/res/layout/item_task.xml b/android/app/src/main/res/layout/item_task.xml index 85a836f4f..52298728a 100644 --- a/android/app/src/main/res/layout/item_task.xml +++ b/android/app/src/main/res/layout/item_task.xml @@ -70,7 +70,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="@{task.content}" + android:text="@{task.contents}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_title" From 2635df073e211d0f46b6fef34de4ae6ca7cca14f Mon Sep 17 00:00:00 2001 From: stitch Date: Thu, 14 Apr 2022 22:04:44 +0900 Subject: [PATCH 15/18] feat: move-api-#67 --- .../com/example/todolist/network/Service.kt | 2 + .../todolist/repository/TaskDataSource.kt | 2 + .../repository/TaskRemoteDataSource.kt | 5 ++ .../repository/TaskRemoteRepository.kt | 9 +++ .../com/example/todolist/ui/TaskAdapter.kt | 3 +- .../todolist/ui/TaskRemoteViewModel.kt | 68 +++++++++++++++---- 6 files changed, 76 insertions(+), 13 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/network/Service.kt b/android/app/src/main/java/com/example/todolist/network/Service.kt index 83015e9f5..b1c9fd917 100644 --- a/android/app/src/main/java/com/example/todolist/network/Service.kt +++ b/android/app/src/main/java/com/example/todolist/network/Service.kt @@ -32,4 +32,6 @@ interface Service { @DELETE("cards/{id}") suspend fun deleteTask(@Path("id") id: Int): Response + @PATCH("cards/{id}/move") + suspend fun moveTask(@Path("id") id: Int, @Body nowStatus: String): Response } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt index 24b3e9aa6..a1ad453d6 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskDataSource.kt @@ -17,4 +17,6 @@ interface TaskDataSource { suspend fun loadHistory(): List? suspend fun deleteTask(id: Int): CommonResponse? + + suspend fun moveTask(id: Int, status: String): CommonResponse? } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index 7f11c0ce0..27f32eae0 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -56,4 +56,9 @@ class TaskRemoteDataSource : TaskDataSource { val response = RetrofitAPI.service.deleteTask(id) return if (response.isSuccessful) response.body() else null } + + override suspend fun moveTask(id: Int, status: String): CommonResponse? { + val response = RetrofitAPI.service.moveTask(id, status) + return if (response.isSuccessful) response.body() else null + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 91af8ed25..19949d54a 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -1,6 +1,7 @@ package com.example.todolist.repository import com.example.todolist.model.History +import com.example.todolist.model.Status import com.example.todolist.network.Result import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest @@ -43,4 +44,12 @@ class TaskRemoteRepository( } return Result.Error("error") } + + suspend fun moveTask(id: Int, status: Status): Result { + val response = taskRemoteDataSource.moveTask(id, status.status) + response?.let { + return Result.Success(it.taskDetailResponse) + } + return Result.Error("error") + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 1ecc6bb44..90199de76 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -7,6 +7,7 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.example.todolist.R import com.example.todolist.databinding.ItemTaskBinding +import com.example.todolist.model.Status import com.example.todolist.model.response.TaskDetailResponse class TaskAdapter( @@ -54,7 +55,7 @@ class TaskAdapter( override fun onMenuItemClick(item: MenuItem?): Boolean { when (item?.itemId) { - R.id.popup_go_done -> viewModel.moveDone(task) + R.id.popup_go_done -> viewModel.moveDone(task, Status.DONE) R.id.popup_modify -> listener.updateDialog(task) R.id.popup_delete -> viewModel.deleteTask(task) } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index 59e657b56..fc3a56eb7 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -12,6 +12,7 @@ import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.repository.TaskRemoteRepository import kotlinx.coroutines.launch +import java.util.* class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository) : ViewModel() { @@ -156,19 +157,62 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository } } - fun addTodoTask(task: Task) {} - - fun addInProgressTask(task: Task) {} - - fun addDoneTask(task: Task) {} - - fun moveDone(task: TaskDetailResponse) {} - - fun updateTodoTask(task: TaskDetailResponse) {} + fun moveDone(task: TaskDetailResponse, status: Status) { + viewModelScope.launch { + when (val updateTask = taskRemoteRepository.moveTask(task.id, status)) { + is Result.Success -> { + when (task.status) { + Status.TODO -> { + todoItem.remove(task) + _todoTask.value = todoItem + } + Status.IN_PROGRESS -> { + inProgressItem.remove(task) + _inProgressTask.value = inProgressItem + } + Status.DONE -> { + doneItem.remove(task) + _doneTask.value = doneItem + } + } - fun updateInProgressTask(task: TaskDetailResponse) {} + when (updateTask.data.status) { + Status.TODO -> { + todoItem.add(0, updateTask.data) + _todoTask.value = todoItem + } + Status.IN_PROGRESS -> { + inProgressItem.add(0, updateTask.data) + _inProgressTask.value = inProgressItem + } + Status.DONE -> { + doneItem.add(0, updateTask.data) + _doneTask.value = doneItem + } + } + } + is Result.Error -> { + _error.value = updateTask.error + } + } + } + } - fun updateDoneTask(task: TaskDetailResponse) {} + fun swapTask(currentList: List, fromPosition: Int, toPosition: Int) { + when (currentList) { + todoItem -> { + Collections.swap(todoItem, fromPosition, toPosition) + _todoTask.value = todoItem + } + inProgressItem -> { + Collections.swap(inProgressItem, fromPosition, toPosition) + _inProgressTask.value = inProgressItem + } + doneItem -> { + Collections.swap(doneItem, fromPosition, toPosition) + _doneTask.value = doneItem + } + } + } - fun swapTask(currentList: List, fromPosition: Int, toPosition: Int) {} } \ No newline at end of file From 0ad17e2a3a8249d5cbe9cfa23805fe0c01473933 Mon Sep 17 00:00:00 2001 From: stitch Date: Fri, 15 Apr 2022 11:15:36 +0900 Subject: [PATCH 16/18] =?UTF-8?q?feat:=20=EB=A6=AC=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=ED=81=B4=EB=9F=AC=EB=B7=B0=EA=B0=84=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=9D=B4=EB=8F=99(=EB=A9=94=EB=AA=A8=EB=A6=AC=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99)-#42?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/todolist/ui/DragListener.kt | 75 +++++++++++++++++++ .../example/todolist/ui/ItemTouchCallback.kt | 10 +-- .../todolist/ui/ItemTouchHelperListener.kt | 6 ++ .../com/example/todolist/ui/MainActivity.kt | 10 ++- .../com/example/todolist/ui/TaskAdapter.kt | 33 +++++++- .../todolist/ui/TaskRemoteViewModel.kt | 46 ++++++++++++ .../app/src/main/res/layout/activity_main.xml | 1 + android/app/src/main/res/layout/item_task.xml | 1 + 8 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 android/app/src/main/java/com/example/todolist/ui/DragListener.kt diff --git a/android/app/src/main/java/com/example/todolist/ui/DragListener.kt b/android/app/src/main/java/com/example/todolist/ui/DragListener.kt new file mode 100644 index 000000000..867bf0e4a --- /dev/null +++ b/android/app/src/main/java/com/example/todolist/ui/DragListener.kt @@ -0,0 +1,75 @@ +package com.example.todolist.ui + +import android.view.DragEvent +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.example.todolist.R + +class DragListener : View.OnDragListener { + + private var isDrop = false + override fun onDrag(view: View, event: DragEvent): Boolean { + when (event.action) { + DragEvent.ACTION_DROP -> { + isDrop = true + var positionTarget = -1 + val viewSource = event.localState as View? + val viewId = view.id + val taskItem = R.id.cl_main + val rvTodo = R.id.rv_todo + val rvInProgress = R.id.rv_in_progress + val rvDone = R.id.rv_done + + when (viewId) { + taskItem, rvTodo, rvInProgress, rvDone -> { + val target: RecyclerView + when (viewId) { + rvTodo -> target = view.rootView.findViewById(rvTodo) as RecyclerView + rvInProgress -> target = + view.rootView.findViewById(rvInProgress) as RecyclerView + rvDone -> target = view.rootView.findViewById(rvDone) as RecyclerView + else -> { + target = view.parent as RecyclerView + positionTarget = view.tag as Int + } + } + + if (viewSource != null) { + val source = viewSource.parent as RecyclerView + val adapterSource = source.adapter as TaskAdapter + val adapterTarget = target.adapter as TaskAdapter + val positionSource = source.getChildAdapterPosition(viewSource) + val sourceData = adapterSource.currentList[positionSource] + val listSource = adapterSource.currentList + val listTarget = adapterTarget.currentList + + if (adapterSource == adapterTarget) { + if (positionTarget < 0) return true + + val targetPosition = target.getChildAdapterPosition(view) + adapterTarget.onItemMove(positionSource, targetPosition) + return true + } + + adapterSource.remove(positionSource, sourceData) + if (positionTarget >= 0) { + when (target.id) { + rvTodo -> adapterTarget.add(1, positionTarget, sourceData) + rvInProgress -> adapterTarget.add(2, positionTarget, sourceData) + rvDone -> adapterTarget.add(3, positionTarget, sourceData) + } + } else { + when (target.id) { + rvTodo -> adapterTarget.add(1, -1, sourceData) + rvInProgress -> adapterTarget.add(2, -1, sourceData) + rvDone -> adapterTarget.add(3, -1, sourceData) + } + } + } + } + } + } + } + return true + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt index 1c200b6de..83b21af82 100644 --- a/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt +++ b/android/app/src/main/java/com/example/todolist/ui/ItemTouchCallback.kt @@ -7,10 +7,7 @@ import androidx.recyclerview.widget.RecyclerView import kotlin.math.max import kotlin.math.min -class ItemTouchCallback( - private var clamp: Float, - private val listener: ItemTouchHelperListener, -) : ItemTouchHelper.Callback() { +class ItemTouchCallback(private var clamp: Float) : ItemTouchHelper.Callback() { private var currentPosition: Int? = null private var previousPosition: Int? = null @@ -30,10 +27,7 @@ class ItemTouchCallback( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder, - ): Boolean { - listener.onItemMove(viewHolder.adapterPosition, target.adapterPosition) - return true - } + ): Boolean = false override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} diff --git a/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt b/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt index 9b2e9907a..083a8508e 100644 --- a/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt +++ b/android/app/src/main/java/com/example/todolist/ui/ItemTouchHelperListener.kt @@ -1,7 +1,13 @@ package com.example.todolist.ui +import com.example.todolist.model.response.TaskDetailResponse + interface ItemTouchHelperListener { fun onItemMove(fromPosition: Int, toPosition: Int): Boolean fun onItemSwipe(position: Int) + + fun add(type: Int, index: Int, task: TaskDetailResponse) + + fun remove(index: Int, task: TaskDetailResponse) } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt index c9f4f7c60..7ebed5f42 100644 --- a/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt +++ b/android/app/src/main/java/com/example/todolist/ui/MainActivity.kt @@ -2,6 +2,7 @@ package com.example.todolist.ui import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.util.Log import android.view.* import android.widget.Toast import androidx.activity.viewModels @@ -55,10 +56,11 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { } } - val todoItemTouchCallback = ItemTouchCallback(clamp, toDoAdapter) + val todoItemTouchCallback = ItemTouchCallback(clamp) with(binding.includeTodo.rvTodo) { ItemTouchHelper(todoItemTouchCallback).attachToRecyclerView(this) adapter = toDoAdapter + setOnDragListener(DragListener()) setOnTouchListener { view, _ -> todoItemTouchCallback.removePreviousClamp(this) view.performClick() @@ -69,10 +71,11 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { toDoAdapter.submitList(todoTask.toList()) } - val inProgressItemTouchCallback = ItemTouchCallback(clamp, inProgressAdapter) + val inProgressItemTouchCallback = ItemTouchCallback(clamp) with(binding.includeInProgress.rvInProgress) { ItemTouchHelper(inProgressItemTouchCallback).attachToRecyclerView(this) adapter = inProgressAdapter + setOnDragListener(DragListener()) setOnTouchListener { view, _ -> inProgressItemTouchCallback.removePreviousClamp(this) view.performClick() @@ -86,10 +89,11 @@ class MainActivity : AppCompatActivity(), TaskAdapter.DialogListener { binding.includeDone.rvDone.adapter = doneAdapter - val doneItemTouchCallback = ItemTouchCallback(clamp, doneAdapter) + val doneItemTouchCallback = ItemTouchCallback(clamp) with(binding.includeDone.rvDone) { ItemTouchHelper(doneItemTouchCallback).attachToRecyclerView(this) adapter = doneAdapter + setOnDragListener(DragListener()) setOnTouchListener { view, _ -> doneItemTouchCallback.removePreviousClamp(this) view.performClick() diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt index 90199de76..0a4006f7a 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskAdapter.kt @@ -1,7 +1,9 @@ package com.example.todolist.ui +import android.os.Build import android.view.* import android.widget.PopupMenu +import androidx.annotation.RequiresApi import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView @@ -27,10 +29,11 @@ class TaskAdapter( override fun onBindViewHolder(holder: TaskViewHolder, position: Int) { holder.bind(getItem(position)) + holder.itemView.tag = position } inner class TaskViewHolder(private val binding: ItemTaskBinding) : - RecyclerView.ViewHolder(binding.root), PopupMenu.OnMenuItemClickListener { + RecyclerView.ViewHolder(binding.root), PopupMenu.OnMenuItemClickListener, View.OnTouchListener { private lateinit var task: TaskDetailResponse @@ -38,6 +41,8 @@ class TaskAdapter( this.task = task binding.task = task binding.executePendingBindings() + itemView.setOnTouchListener(this) + itemView.setOnDragListener(DragListener()) binding.clDelete.setOnClickListener { onItemSwipe(layoutPosition) } itemView.setOnLongClickListener { showPopup(it) @@ -75,6 +80,24 @@ class TaskAdapter( fun setTag(isClamped: Boolean) { binding.swipeView.tag = isClamped } + + @RequiresApi(Build.VERSION_CODES.N) + override fun onTouch(view: View?, event: MotionEvent?): Boolean { + val shadowBuilder = View.DragShadowBuilder(view) + val isDrag = getTag() + when(event?.action) { + MotionEvent.ACTION_DOWN -> { } + MotionEvent.ACTION_MOVE -> { + if(!isDrag) { + view?.startDragAndDrop(null, shadowBuilder, view , 0) + return true + } + } + MotionEvent.ACTION_UP -> return true + } + view?.performClick() + return false + } } override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { @@ -85,6 +108,14 @@ class TaskAdapter( override fun onItemSwipe(position: Int) { viewModel.deleteTask(getItem(position)) } + + override fun add(type: Int, index: Int, task: TaskDetailResponse) { + viewModel.addTask(type, index, task) + } + + override fun remove(index: Int, task: TaskDetailResponse) { + viewModel.remove(index, task) + } } object TaskDiffCallback : DiffUtil.ItemCallback() { diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index fc3a56eb7..6cf572619 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -1,5 +1,6 @@ package com.example.todolist.ui +import android.util.Log import androidx.lifecycle.LiveData import com.example.todolist.network.Result import androidx.lifecycle.MutableLiveData @@ -215,4 +216,49 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository } } + fun addTask(type: Int, index: Int, task: TaskDetailResponse) { + when(type) { + 1 -> { + if(index == -1) todoItem.add(task.copy(status = Status.TODO)) + else todoItem.add(index, task.copy(status = Status.TODO)) + Log.d("test", "onCreate: $todoItem") + Log.d("test", "onCreate: $inProgressItem") + Log.d("test", "onCreate: $doneItem") + _todoTask.value = todoItem + } + 2 -> { + if(index == -1) inProgressItem.add(task.copy(status = Status.IN_PROGRESS)) + else inProgressItem.add(index, task.copy(status = Status.IN_PROGRESS)) + Log.d("test", "onCreate: $todoItem") + Log.d("test", "onCreate: $inProgressItem") + Log.d("test", "onCreate: $doneItem") + _inProgressTask.value = inProgressItem + } + else -> { + if(index == -1) doneItem.add(task.copy(status = Status.DONE)) + else doneItem.add(index, task.copy(status = Status.DONE)) + Log.d("test", "onCreate: $todoItem") + Log.d("test", "onCreate: $inProgressItem") + Log.d("test", "onCreate: $doneItem") + _doneTask.value = doneItem + } + } + } + + fun remove(index: Int, task: TaskDetailResponse) { + when(task.status) { + Status.TODO -> { + todoItem.removeAt(index) + _todoTask.value = todoItem + } + Status.IN_PROGRESS -> { + inProgressItem.removeAt(index) + _inProgressTask.value = inProgressItem + } + else -> { + doneItem.removeAt(index) + _doneTask.value = doneItem + } + } + } } \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 4e475800a..66de91a55 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -5,6 +5,7 @@ xmlns:tools="http://schemas.android.com/tools"> + diff --git a/android/app/src/main/res/layout/item_task.xml b/android/app/src/main/res/layout/item_task.xml index 52298728a..b2d28e664 100644 --- a/android/app/src/main/res/layout/item_task.xml +++ b/android/app/src/main/res/layout/item_task.xml @@ -11,6 +11,7 @@ From e9f50452a9b22ad9fe04bbbc2d6e9c088ce9709b Mon Sep 17 00:00:00 2001 From: hwj Date: Fri, 15 Apr 2022 11:52:46 +0900 Subject: [PATCH 17/18] =?UTF-8?q?feat:=20=EC=B6=94=EA=B0=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20=ED=86=B5?= =?UTF-8?q?=EC=8B=A0=20=EA=B5=AC=ED=98=84-#63?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/todolist/model/Task.kt | 2 +- .../todolist/model/response/TasksResponse.kt | 3 +- .../repository/TaskRemoteDataSource.kt | 31 +----- .../repository/TaskRemoteRepository.kt | 17 ++- .../todolist/repository/TaskRepository.kt | 6 +- .../todolist/ui/NewTaskDialogFragment.kt | 24 ++-- .../todolist/ui/TaskRemoteViewModel.kt | 103 +++++++++--------- .../todolist/ui/UpdateTaskDialogFragment.kt | 21 ++-- android/app/src/main/res/layout/item_task.xml | 2 +- 9 files changed, 96 insertions(+), 113 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/model/Task.kt b/android/app/src/main/java/com/example/todolist/model/Task.kt index d39aa4400..0d7e3b34f 100644 --- a/android/app/src/main/java/com/example/todolist/model/Task.kt +++ b/android/app/src/main/java/com/example/todolist/model/Task.kt @@ -2,7 +2,7 @@ package com.example.todolist.model data class Task( val title: String, - val content: String, + val contents: String, val status: Status, val author: String = "Android" ) diff --git a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt index d23b3115a..c8a0dda76 100644 --- a/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt +++ b/android/app/src/main/java/com/example/todolist/model/response/TasksResponse.kt @@ -14,13 +14,14 @@ data class TasksResponse( data class CommonResponse( val status: Int, + @SerializedName("resources") val taskDetailResponse: TaskDetailResponse, ) data class TaskDetailResponse( val id: Int, val title: String, - val content: String, + val contents: String, val status: Status, val author: String = "Android", val updateDateTime: String? = null, diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt index c62dae805..69af7a1d8 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteDataSource.kt @@ -1,6 +1,5 @@ package com.example.todolist.repository -import android.util.Log import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.CommonResponse @@ -15,34 +14,12 @@ class TaskRemoteDataSource : TaskDataSource { } override suspend fun addTask(cardData: Task): CommonResponse? { - var task: CommonResponse? = null - - val service = RetrofitAPI.service - val response = service.saveTask(cardData) - if (response.isSuccessful) { - val result = response.body() - task = result - Log.d("카드 저장 성공", "$result") - } else { - // TODO 실패했을 시 담을 데이터 정하기 - Log.d("카드 저장 실패", "${response.code()}") - } - return task + val response = RetrofitAPI.service.saveTask(cardData) + return if (response.isSuccessful) response.body() else null } override suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): CommonResponse? { - var task: CommonResponse? = null - - val service = RetrofitAPI.service - val response = service.modifyTask(modifyTaskRequest.id, modifyTaskRequest) - if (response.isSuccessful) { - val result = response.body() - task = result - Log.d("카드 수정 성공", "$result") - } else { - // TODO 실패했을 시 담을 데이터 정하기 - Log.d("카드 수정 실패", "${response.code()}") - } - return task + val response = RetrofitAPI.service.modifyTask(modifyTaskRequest.id, modifyTaskRequest) + return if (response.isSuccessful) response.body() else null } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt index 3166f9a64..a651c5140 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRemoteRepository.kt @@ -4,7 +4,6 @@ import com.example.todolist.network.Result import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.CommonResponse -import com.example.todolist.model.response.TaskDetailResponse import com.example.todolist.model.response.TasksResponse class TaskRemoteRepository( @@ -19,11 +18,19 @@ class TaskRemoteRepository( return Result.Error("error") } - suspend fun addTask(cardData: Task): CommonResponse? { - return taskRemoteDataSource.addTask(cardData) + suspend fun addTask(cardData: Task): Result { + val response = taskRemoteDataSource.addTask(cardData) + response?.let { + return Result.Success(it) + } + return Result.Error("error") } - suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): TaskDetailResponse? { - return taskRemoteDataSource.modifyTask(modifyTaskRequest)?.taskDetailResponse + suspend fun modifyTask(modifyTaskRequest: ModifyTaskRequest): Result { + val response = taskRemoteDataSource.modifyTask(modifyTaskRequest) + response?.let { + return Result.Success(it) + } + return Result.Error("error") } } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt index 6ad7db06b..0a3aba239 100644 --- a/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt +++ b/android/app/src/main/java/com/example/todolist/repository/TaskRepository.kt @@ -62,7 +62,7 @@ class TaskRepository { 0, TaskDetailResponse( todoIndex++, task.title, - task.content, + task.contents, task.status ) ) @@ -70,7 +70,7 @@ class TaskRepository { 0, TaskDetailResponse( inProgressIndex++, task.title, - task.content, + task.contents, task.status ) ) @@ -78,7 +78,7 @@ class TaskRepository { 0, TaskDetailResponse( doneIndex++, task.title, - task.content, + task.contents, task.status ) ) diff --git a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt index 71067db3b..ed5683182 100644 --- a/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/NewTaskDialogFragment.kt @@ -5,6 +5,7 @@ import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -17,7 +18,7 @@ import com.example.todolist.model.Task class NewTaskDialogFragment(private val status: Status) : DialogFragment() { private lateinit var binding: DialogNewCardBinding - private val viewModel: TaskViewModel by activityViewModels() + private val viewModel: TaskRemoteViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -42,30 +43,27 @@ class NewTaskDialogFragment(private val status: Status) : DialogFragment() { binding.btnRegister.setOnClickListener { when (status) { - Status.TODO -> { - val task = Task( + Status.TODO -> viewModel.addTask( + Task( binding.etTitle.text.toString(), binding.etContents.text.toString(), Status.TODO ) - viewModel.addTodoTask(task) - } - Status.IN_PROGRESS -> { - val task = Task( + ) + Status.IN_PROGRESS -> viewModel.addTask( + Task( binding.etTitle.text.toString(), binding.etContents.text.toString(), Status.IN_PROGRESS ) - viewModel.addInProgressTask(task) - } - else -> { - val task = Task( + ) + Status.DONE -> viewModel.addTask( + Task( binding.etTitle.text.toString(), binding.etContents.text.toString(), Status.DONE ) - viewModel.addDoneTask(task) - } + ) } dismiss() } diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index e44c2ec67..18d82698a 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -19,14 +19,17 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository val history: LiveData> get() = _history + private var todoItem: MutableList = mutableListOf() private val _todoTask = MutableLiveData>() val todoTask: LiveData> get() = _todoTask + private var inProgressItem: MutableList = mutableListOf() private val _inProgressTask = MutableLiveData>() val inProgressTask: LiveData> get() = _inProgressTask + private var doneItem: MutableList = mutableListOf() private val _doneTask = MutableLiveData>() val doneTask: LiveData> get() = _doneTask @@ -43,61 +46,73 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository viewModelScope.launch { when (val tasks = taskRemoteRepository.loadTask()) { is Result.Success -> { - _todoTask.value = tasks.data.todo - _inProgressTask.value = tasks.data.inProgress - _doneTask.value = tasks.data.done - } - is Result.Error -> { - _error.value = tasks.error + todoItem = tasks.data.todo + _todoTask.value = todoItem + + inProgressItem = tasks.data.inProgress + _inProgressTask.value = inProgressItem + + doneItem = tasks.data.done + _doneTask.value = doneItem } + is Result.Error -> _error.value = tasks.error } } } fun addTask(task: Task) { viewModelScope.launch { - taskRemoteRepository.addTask(task)?.let { - when (it.taskDetailResponse.status) { - Status.TODO -> { - _todoTask.value?.add(it.taskDetailResponse) - } - Status.IN_PROGRESS -> { - _inProgressTask.value?.add(it.taskDetailResponse) - } - Status.DONE -> { - _doneTask.value?.add(it.taskDetailResponse) + when (val tasks = taskRemoteRepository.addTask(task)) { + is Result.Success -> { + when (tasks.data.taskDetailResponse.status) { + Status.TODO -> { + todoItem.add(0, tasks.data.taskDetailResponse) + _todoTask.value = todoItem + } + Status.IN_PROGRESS -> { + inProgressItem.add(0, tasks.data.taskDetailResponse) + _inProgressTask.value = inProgressItem + } + Status.DONE -> { + doneItem.add(0, tasks.data.taskDetailResponse) + _doneTask.value = doneItem + } } } + is Result.Error -> _error.value = tasks.error } } } fun modifyTask(modifyTaskRequest: ModifyTaskRequest) { viewModelScope.launch { - taskRemoteRepository.modifyTask(modifyTaskRequest)?.let { - when (it.status) { - Status.TODO -> { - val originalTask = - _todoTask.value?.find { resources -> modifyTaskRequest.id == resources.id } - val index = _todoTask.value?.indexOf(originalTask) - if (index != null) { - _todoTask.value?.set(index, it) + when (val tasks = taskRemoteRepository.modifyTask(modifyTaskRequest)) { + is Result.Success -> { + when (tasks.data.taskDetailResponse.status) { + Status.TODO -> { + val originalTask = _todoTask.value?.find { resources -> + modifyTaskRequest.id == resources.id + } + _todoTask.value?.indexOf(originalTask)?.let { index -> + todoItem[index] = tasks.data.taskDetailResponse + _todoTask.value = todoItem + } } - } - Status.IN_PROGRESS -> { - val originalTask = - _inProgressTask.value?.find { resources -> modifyTaskRequest.id == resources.id } - val index = _inProgressTask.value?.indexOf(originalTask) - if (index != null) { - _inProgressTask.value?.set(index, it) + Status.IN_PROGRESS -> { + val originalTask = + _inProgressTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + _inProgressTask.value?.indexOf(originalTask)?.let { index -> + inProgressItem[index] = tasks.data.taskDetailResponse + _inProgressTask.value = inProgressItem + } } - } - Status.DONE -> { - val originalTask = - _doneTask.value?.find { resources -> modifyTaskRequest.id == resources.id } - val index = _doneTask.value?.indexOf(originalTask) - if (index != null) { - _doneTask.value?.set(index, it) + Status.DONE -> { + val originalTask = + _doneTask.value?.find { resources -> modifyTaskRequest.id == resources.id } + _doneTask.value?.indexOf(originalTask)?.let { index -> + doneItem[index] = tasks.data.taskDetailResponse + _doneTask.value = doneItem + } } } } @@ -107,21 +122,9 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository fun loadDummyData() {} - fun addTodoTask(task: Task) {} - - fun addInProgressTask(task: Task) {} - - fun addDoneTask(task: Task) {} - fun moveDone(task: TaskDetailResponse) {} fun deleteTask(task: TaskDetailResponse) {} - fun updateTodoTask(task: TaskDetailResponse) {} - - fun updateInProgressTask(task: TaskDetailResponse) {} - - fun updateDoneTask(task: TaskDetailResponse) {} - fun swapTask(currentList: List, fromPosition: Int, toPosition: Int) {} } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt index eee7403a8..df9df53c4 100644 --- a/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt +++ b/android/app/src/main/java/com/example/todolist/ui/UpdateTaskDialogFragment.kt @@ -12,14 +12,12 @@ import android.view.Window import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.example.todolist.databinding.DialogUpdateCardBinding -import com.example.todolist.model.Status -import com.example.todolist.model.Task import com.example.todolist.model.request.ModifyTaskRequest import com.example.todolist.model.response.TaskDetailResponse class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFragment() { private lateinit var binding: DialogUpdateCardBinding - private val viewModel: TaskViewModel by activityViewModels() + private val viewModel: TaskRemoteViewModel by activityViewModels() private var titleFlag = false private var contentsFlag = false @@ -42,18 +40,17 @@ class UpdateTaskDialogFragment(private val task: TaskDetailResponse) : DialogFra binding.etTitle.addTextChangedListener(titleListener) binding.etContents.addTextChangedListener(contentsListener) binding.etTitle.setText(task.title) - binding.etContents.setText(task.content) + binding.etContents.setText(task.contents) binding.btnUpdate.setOnClickListener { - val updateTask = task.copy( - title = binding.etTitle.text.toString(), - content = binding.etContents.text.toString() + val modifyTaskRequest = ModifyTaskRequest( + task.id, + binding.etTitle.text.toString(), + binding.etContents.text.toString(), + "Android", + task.status.toString() ) - when (task.status) { - Status.TODO -> viewModel.updateTodoTask(updateTask) - Status.IN_PROGRESS -> viewModel.updateInProgressTask(updateTask) - else -> viewModel.updateDoneTask(updateTask) - } + viewModel.modifyTask(modifyTaskRequest) dismiss() } } diff --git a/android/app/src/main/res/layout/item_task.xml b/android/app/src/main/res/layout/item_task.xml index 85a836f4f..52298728a 100644 --- a/android/app/src/main/res/layout/item_task.xml +++ b/android/app/src/main/res/layout/item_task.xml @@ -70,7 +70,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="@{task.content}" + android:text="@{task.contents}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_title" From ac8a77568727a1173bc4a2760344d180156080b7 Mon Sep 17 00:00:00 2001 From: stitch Date: Fri, 15 Apr 2022 14:50:24 +0900 Subject: [PATCH 18/18] =?UTF-8?q?feat:=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=EC=95=A4=20=EB=93=9C=EB=A1=AD=20=EC=97=90=EB=9F=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(=EB=A9=94=EB=AA=A8=EB=A6=AC=20=EA=B4=80=EB=A6=AC)-#42?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/todolist/ui/DragListener.kt | 15 +++++++++------ .../example/todolist/ui/TaskRemoteViewModel.kt | 10 ---------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/android/app/src/main/java/com/example/todolist/ui/DragListener.kt b/android/app/src/main/java/com/example/todolist/ui/DragListener.kt index 867bf0e4a..6715bbc47 100644 --- a/android/app/src/main/java/com/example/todolist/ui/DragListener.kt +++ b/android/app/src/main/java/com/example/todolist/ui/DragListener.kt @@ -7,11 +7,9 @@ import com.example.todolist.R class DragListener : View.OnDragListener { - private var isDrop = false override fun onDrag(view: View, event: DragEvent): Boolean { when (event.action) { DragEvent.ACTION_DROP -> { - isDrop = true var positionTarget = -1 val viewSource = event.localState as View? val viewId = view.id @@ -40,11 +38,16 @@ class DragListener : View.OnDragListener { val adapterTarget = target.adapter as TaskAdapter val positionSource = source.getChildAdapterPosition(viewSource) val sourceData = adapterSource.currentList[positionSource] - val listSource = adapterSource.currentList - val listTarget = adapterTarget.currentList - if (adapterSource == adapterTarget) { - if (positionTarget < 0) return true + if (positionTarget < 0) { + adapterSource.remove(positionSource, sourceData) + when (target.id) { + rvTodo -> adapterTarget.add(1, -1, sourceData) + rvInProgress -> adapterTarget.add(2, -1, sourceData) + rvDone -> adapterTarget.add(3, -1, sourceData) + } + return true + } val targetPosition = target.getChildAdapterPosition(view) adapterTarget.onItemMove(positionSource, targetPosition) diff --git a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt index ca8f3d0f7..fc3f23a99 100644 --- a/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt +++ b/android/app/src/main/java/com/example/todolist/ui/TaskRemoteViewModel.kt @@ -1,6 +1,5 @@ package com.example.todolist.ui -import android.util.Log import androidx.lifecycle.LiveData import com.example.todolist.network.Result import androidx.lifecycle.MutableLiveData @@ -230,25 +229,16 @@ class TaskRemoteViewModel(private val taskRemoteRepository: TaskRemoteRepository 1 -> { if(index == -1) todoItem.add(task.copy(status = Status.TODO)) else todoItem.add(index, task.copy(status = Status.TODO)) - Log.d("test", "onCreate: $todoItem") - Log.d("test", "onCreate: $inProgressItem") - Log.d("test", "onCreate: $doneItem") _todoTask.value = todoItem } 2 -> { if(index == -1) inProgressItem.add(task.copy(status = Status.IN_PROGRESS)) else inProgressItem.add(index, task.copy(status = Status.IN_PROGRESS)) - Log.d("test", "onCreate: $todoItem") - Log.d("test", "onCreate: $inProgressItem") - Log.d("test", "onCreate: $doneItem") _inProgressTask.value = inProgressItem } else -> { if(index == -1) doneItem.add(task.copy(status = Status.DONE)) else doneItem.add(index, task.copy(status = Status.DONE)) - Log.d("test", "onCreate: $todoItem") - Log.d("test", "onCreate: $inProgressItem") - Log.d("test", "onCreate: $doneItem") _doneTask.value = doneItem } }