Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ dependencies {
//Splash
implementation "androidx.core:core-splashscreen:1.0.0"

implementation "io.reactivex.rxjava3:rxjava:3.1.6"
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ package com.red_velvet_cake.dailytodo.data.remote.auth

import com.red_velvet_cake.dailytodo.data.model.LoginResponse
import com.red_velvet_cake.dailytodo.data.model.RegisterAccountResponse
import io.reactivex.rxjava3.core.Single

interface AuthenticationService {
fun loginAccount(
username: String,
password: String,
onSuccess: (response: LoginResponse) -> Unit,
onFailure: (exception: Exception) -> Unit,
)
password: String
): Single<LoginResponse>

fun registerAccount(
username: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.red_velvet_cake.dailytodo.data.remote.util.HttpMethod
import com.red_velvet_cake.dailytodo.data.remote.util.buildRequest
import com.red_velvet_cake.dailytodo.utils.Constants.HOST_NAME
import com.red_velvet_cake.dailytodo.utils.Constants.SCHEME
import io.reactivex.rxjava3.core.Single
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Credentials
Expand All @@ -30,12 +31,7 @@ class AuthenticationServiceImpl : AuthenticationService {
.addInterceptor(loggingInterceptor)
.build()

override fun loginAccount(
username: String,
password: String,
onSuccess: (response: LoginResponse) -> Unit,
onFailure: (exception: Exception) -> Unit
) {
override fun loginAccount(username: String, password: String): Single<LoginResponse> {
val url = HttpUrl.Builder()
.scheme(SCHEME)
.host(HOST_NAME)
Expand All @@ -49,22 +45,14 @@ class AuthenticationServiceImpl : AuthenticationService {
.header(AUTHORIZATION_HEADER, authHeaderValue)
.build()

client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, ioException: IOException) {
onFailure(ioException)
}

override fun onResponse(call: Call, response: Response) {
try {
response.body?.string()?.let { responseBody ->
val loginResponse = Gson().fromJson(responseBody, LoginResponse::class.java)
onSuccess(loginResponse)
}
} catch (exception: Exception) {
onFailure(exception)
}
return Single.fromCallable {
val response = client.newCall(request).execute()
if (response.isSuccessful){
gson.fromJson(response.body?.string(), LoginResponse::class.java)
} else {
throw IOException("Request failed with code: ${response.code}")
}
})
}
}

override fun registerAccount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,9 @@ class LoginFragment : BaseFragment<FragmentLoginBinding>(), LoginView {
private fun runOnUiThread(runnable: Runnable) {
requireActivity().runOnUiThread(runnable)
}

override fun onDestroy() {
super.onDestroy()
loginPresenter.onDestroy()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,29 @@ package com.red_velvet_cake.dailytodo.ui.login
import com.red_velvet_cake.dailytodo.data.local.LocalDataImpl
import com.red_velvet_cake.dailytodo.data.model.LoginResponse
import com.red_velvet_cake.dailytodo.data.remote.auth.AuthenticationServiceImpl
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers

class LoginPresenter(private val view: LoginView) {
private val authService = AuthenticationServiceImpl()
private val localDataImpl = LocalDataImpl()

private val compositeDisposable = CompositeDisposable()

fun loginUser(username: String, password: String) {
view.showLoadingState()
localDataImpl.saveUserName(username)
authService.loginAccount(
username,
password,
this::onLoginSuccess,
this::onLoginFailure
)
}

val disposable = authService.loginAccount(username, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ loginResponse -> onLoginSuccess(loginResponse) },
{ exception -> onLoginFailure(exception as Exception) }
)

compositeDisposable.add(disposable)
}
private fun onLoginSuccess(loginResponse: LoginResponse) {
view.hideLoadingState()
if (loginResponse.isSuccess) {
Expand Down Expand Up @@ -57,4 +64,7 @@ class LoginPresenter(private val view: LoginView) {
fun navigateToRegister() {
view.navigateToRegister()
}
fun onDestroy() {
compositeDisposable.clear()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.ItemTouchHelper
import com.red_velvet_cake.dailytodo.R
import com.red_velvet_cake.dailytodo.data.model.PersonalTodo
Expand Down Expand Up @@ -31,6 +32,25 @@ class PersonalTodoFragment : BaseFragment<FragmentPersonalTodoBinding>(), Person
binding.chipTodo.isChecked = true
binding.chipDone.setChipBackgroundColorResource(R.color.white)
binding.chipInProgress.setChipBackgroundColorResource(R.color.white)

searchView()
}

private fun searchView() {
val toolbar = binding.appBar
toolbar.inflateMenu(R.menu.menu_search)
val searchItem = toolbar.menu.findItem(R.id.action_search)
val searchView = searchItem.actionView as? SearchView
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}

override fun onQueryTextChange(newText: String?): Boolean {
newText?.let { personalTodoPresenter.searchTodos(it) }
return true
}
})
}

override fun addCallBacks() {
Expand Down Expand Up @@ -141,6 +161,10 @@ class PersonalTodoFragment : BaseFragment<FragmentPersonalTodoBinding>(), Person
}
}

override fun getDisplayedTodoList(): List<PersonalTodo> {
return filteredList
}

override fun showTodoList(todoList: List<PersonalTodo>) {
val itemTouchHelperCallback = ItemPersonalTodoTouchHelperCallback(personalToDoAdapter)
val itemTouchHelper = ItemTouchHelper(itemTouchHelperCallback)
Expand All @@ -161,6 +185,11 @@ class PersonalTodoFragment : BaseFragment<FragmentPersonalTodoBinding>(), Person
}
}

override fun onDestroy() {
super.onDestroy()
personalTodoPresenter.onDestroy()
}

companion object {
private const val CHIP_TODO_VALUE = 0
private const val CHIP_IN_PROGRESS_VALUE = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ import com.red_velvet_cake.dailytodo.data.model.GetAllPersonalTodosResponse
import com.red_velvet_cake.dailytodo.data.model.PersonalTodo
import com.red_velvet_cake.dailytodo.data.remote.todo_service.TodoServiceImpl
import com.red_velvet_cake.dailytodo.data.remote.util.CustomException
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.concurrent.TimeUnit

class PersonalTodoPresenter(private val view: PersonalTodoView) {

private val todoServiceImpl = TodoServiceImpl()
private val compositeDisposable = CompositeDisposable()

fun updateTeamTodoStatus(
todoId: String,
Expand Down Expand Up @@ -60,4 +66,31 @@ class PersonalTodoPresenter(private val view: PersonalTodoView) {
fun navigateToTodoDetails(personalTodo: PersonalTodo) {
view.navigateToTodoDetails(personalTodo)
}

fun searchTodos(searchQuery: String) {
compositeDisposable.clear()

if (searchQuery.isBlank()) {
getAllTeamTodos()
} else {
val disposable = Observable.just(searchQuery)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.map { query ->
view.getDisplayedTodoList().filter {
it.title.contains(query, ignoreCase = true) ||
it.description.contains(query, ignoreCase = true)
}
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe { filteredList ->
view.showTodoList(filteredList)
}
compositeDisposable.add(disposable)
}
}

fun onDestroy() {
compositeDisposable.dispose()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ interface PersonalTodoView {
fun navigateBack()
fun showLoadStatus()
fun disableLoadStatus()
fun getDisplayedTodoList(): List<PersonalTodo>
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class RegisterFragment : BaseFragment<FragmentRegisterBinding>(), RegisterView {
activity?.runOnUiThread(runnable)
}

override fun onDestroy() {
super.onDestroy()
presenter.onDestroy()
}

companion object {
fun newInstance(): RegisterFragment = RegisterFragment()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import com.red_velvet_cake.dailytodo.data.local.LocalDataImpl
import com.red_velvet_cake.dailytodo.data.model.LoginResponse
import com.red_velvet_cake.dailytodo.data.model.RegisterAccountResponse
import com.red_velvet_cake.dailytodo.data.remote.auth.AuthenticationServiceImpl
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.schedulers.Schedulers

class RegisterPresenter(
private val view: RegisterView,
Expand All @@ -13,7 +16,7 @@ class RegisterPresenter(
private val localDataImpl = LocalDataImpl()
private var username: String = ""
private var password: String = ""

private val compositeDisposable = CompositeDisposable()
private fun registerAccount(username: String, password: String, teamId: String) {
this.username = username
this.password = password
Expand Down Expand Up @@ -85,12 +88,18 @@ class RegisterPresenter(

private fun loginUsingCredentials(username: String, password: String) {
localDataImpl.saveUserName(username)
authService.loginAccount(
username,
password,
::onLoginAccountSuccess,
::onLoginAccountFailure
)
val disposable = authService.loginAccount(username, password)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ loginResponse ->
onLoginAccountSuccess(loginResponse)
},
{ error ->
onLoginAccountFailure(error as Exception)
}
)
compositeDisposable.add(disposable)
}

private fun onLoginAccountSuccess(loginResponse: LoginResponse) {
Expand All @@ -111,4 +120,7 @@ class RegisterPresenter(
view.navigateToLogin()
}

fun onDestroy() {
compositeDisposable.dispose()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.ItemTouchHelper
import com.google.android.material.chip.Chip
import com.red_velvet_cake.dailytodo.R
Expand Down Expand Up @@ -32,6 +33,24 @@ class TeamTodoFragment : BaseFragment<FragmentTeamTodoBinding>(), TeamTodoView {
binding.chipTodo.isChecked = true
binding.chipDone.setChipBackgroundColorResource(R.color.white)
binding.chipInProgress.setChipBackgroundColorResource(R.color.white)
searchView()
}

private fun searchView(){
val toolbar = binding.appBar
toolbar.inflateMenu(R.menu.menu_search)
val searchItem = toolbar.menu.findItem(R.id.action_search)
val searchView = searchItem.actionView as? SearchView
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}

override fun onQueryTextChange(newText: String?): Boolean {
newText?.let { teamTodoPresenter.searchTodos(it) }
return true
}
})
}

override fun addCallBacks() {
Expand Down Expand Up @@ -111,6 +130,10 @@ class TeamTodoFragment : BaseFragment<FragmentTeamTodoBinding>(), TeamTodoView {
binding.progressBarLoadState.visibility = View.VISIBLE
}

override fun getDisplayedTodoList(): List<TeamTodo> {
return filteredList
}

override fun showTodoList(todoList: List<TeamTodo>) {
val itemTouchHelperCallback = ItemTeamTodoTouchHelperCallback(teamToDoAdapter)
val itemTouchHelper = ItemTouchHelper(itemTouchHelperCallback)
Expand Down Expand Up @@ -148,6 +171,10 @@ class TeamTodoFragment : BaseFragment<FragmentTeamTodoBinding>(), TeamTodoView {
private fun onTodoClicked(todo: TeamTodo) {
teamTodoPresenter.navigateToTodoDetails(todo)
}
override fun onDestroy() {
super.onDestroy()
teamTodoPresenter.onDestroy()
}

companion object {
private const val CHIP_TODO_VALUE = 0
Expand Down
Loading