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 @@ -76,6 +76,8 @@ dependencies {
// acc
implementation "android.arch.lifecycle:extensions:1.1.0"
implementation "android.arch.lifecycle:viewmodel:1.1.0"
implementation "android.arch.lifecycle:livedata:1.1.0"
implementation "android.arch.lifecycle:reactivestreams:1.1.0"
kapt "android.arch.lifecycle:compiler:1.1.0"

// rx
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/enixma/sample/charity/domain/UseCase.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.enixma.sample.charity.domain

import io.reactivex.Observable
import io.reactivex.Flowable

interface UseCase<in P : UseCase.Request, Q : UseCase.Result> {

fun execute(request: P): Observable<Q>
fun execute(request: P): Flowable<Q>

interface Request

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ package com.enixma.sample.charity.domain.createdonation

import com.enixma.sample.charity.data.repository.ICharityRepository
import com.enixma.sample.charity.domain.UseCase
import io.reactivex.Observable
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import javax.inject.Inject

class CreateDonationUseCase @Inject constructor(private val charityRepository: ICharityRepository) : UseCase<CreateDonationUseCaseRequest, CreateDonationUseCaseResult> {

enum class STATUS {
LOADING,
SUCCESS,
FAIL
}

override fun execute(request: CreateDonationUseCaseRequest): Observable<CreateDonationUseCaseResult> {
return charityRepository.createDonation(request.donationEntity)
.flatMap {
val result = it.let {
val status = if (it.statusCode == 201 && it.isSuccess) STATUS.SUCCESS else STATUS.FAIL
CreateDonationUseCaseResult(status).apply {
if (this.status == STATUS.FAIL) this.errorMessage = it.errorMessage
}
}
Observable.just(result)
}

override fun execute(request: CreateDonationUseCaseRequest): Flowable<CreateDonationUseCaseResult> {
return Flowable.just(CreateDonationUseCaseResult(STATUS.LOADING)).concatWith(
charityRepository.createDonation(request.donationEntity)
.toFlowable(BackpressureStrategy.LATEST)
.flatMap {
val result = it.let {
val status = if (it.statusCode == 201 && it.isSuccess) STATUS.SUCCESS else STATUS.FAIL
CreateDonationUseCaseResult(status).apply {
if (this.status == STATUS.FAIL) this.errorMessage = it.errorMessage
}
}
Flowable.just(result)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ package com.enixma.sample.charity.domain.getcharitylist

import com.enixma.sample.charity.data.repository.ICharityRepository
import com.enixma.sample.charity.domain.UseCase
import io.reactivex.Observable
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import javax.inject.Inject

class GetCharityListUseCase @Inject constructor(private val charityRepository: ICharityRepository) : UseCase<GetCharityListUseCaseRequest, GetCharityListUseCaseResult> {

enum class STATUS {
LOADING,
SUCCESS,
NO_DATA_FOUND
}

override fun execute(request: GetCharityListUseCaseRequest): Observable<GetCharityListUseCaseResult> {
return charityRepository.getCharityList()
.flatMap {
val result = it.let {
val status = if (it.total <= 0) STATUS.NO_DATA_FOUND else STATUS.SUCCESS
val charityList = it.data
GetCharityListUseCaseResult(status, charityList)
}
Observable.just(result)
}
override fun execute(request: GetCharityListUseCaseRequest): Flowable<GetCharityListUseCaseResult> {
return Flowable.just(GetCharityListUseCaseResult(STATUS.LOADING, mutableListOf())).concatWith(
charityRepository.getCharityList()
.toFlowable(BackpressureStrategy.LATEST)
.flatMap {
val result = it.let {
val status = if (it.total <= 0) STATUS.NO_DATA_FOUND else STATUS.SUCCESS
val charityList = it.data
GetCharityListUseCaseResult(status, charityList)
}
Flowable.just(result)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.enixma.sample.charity.domain.validatecreditcard

import co.omise.android.CardNumber
import com.enixma.sample.charity.domain.UseCase
import io.reactivex.Flowable
import io.reactivex.Observable

class ValidateCreditCardUseCase : UseCase<ValidateCreditCardUseCaseRequest, ValidateCreditCardUseCaseResult> {
Expand All @@ -18,7 +19,7 @@ class ValidateCreditCardUseCase : UseCase<ValidateCreditCardUseCaseRequest, Vali
INVALID_LUHN
}

override fun execute(request: ValidateCreditCardUseCaseRequest): Observable<ValidateCreditCardUseCaseResult> {
override fun execute(request: ValidateCreditCardUseCaseRequest): Flowable<ValidateCreditCardUseCaseResult> {

val errorList = ArrayList<ERROR>()
validateCard(request.cardNumber, errorList)
Expand All @@ -27,7 +28,7 @@ class ValidateCreditCardUseCase : UseCase<ValidateCreditCardUseCaseRequest, Vali

return errorList.let {
val status = if (it.isEmpty()) STATUS.VALID else STATUS.INVALID
Observable.just(ValidateCreditCardUseCaseResult(status).apply { this.errorList = it })
Flowable.just(ValidateCreditCardUseCaseResult(status).apply { this.errorList = it })
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class CharityListFragment : Fragment(), CharityListContract.View {
DaggerCharityListComponent.builder()
.serviceFactoryModule(ServiceFactoryModule(activity))
.charityDataModule(CharityDataModule(activity))
.charityListModule(CharityListModule(this))
.charityListModule(CharityListModule(this, this))
.build().inject(this)
}

Expand All @@ -54,7 +54,6 @@ class CharityListFragment : Fragment(), CharityListContract.View {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)

lifecycle.addObserver(presenter as CharityListPresenter)
binding.swipe.setOnRefreshListener { presenter.getCharityList() }
binding.swipe.isRefreshing = true
presenter.getCharityList()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
package com.enixma.sample.charity.presentation.charitylist

import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.OnLifecycleEvent
import android.arch.lifecycle.*
import android.util.Log
import android.widget.Toast
import com.enixma.sample.charity.domain.getcharitylist.GetCharityListUseCase
import com.enixma.sample.charity.domain.getcharitylist.GetCharityListUseCaseRequest
import com.enixma.sample.charity.domain.getcharitylist.GetCharityListUseCaseResult
import io.reactivex.disposables.Disposable

class CharityListPresenter(private val view: CharityListContract.View,
private val getCharityListUseCase: GetCharityListUseCase) : CharityListContract.Action, LifecycleObserver {
private val lifecycleOwner: LifecycleOwner,
private val getCharityListUseCase: GetCharityListUseCase) : CharityListContract.Action {

private var getCharityListDisposable: Disposable? = null
private var isLoading: Boolean = false
private var result: LiveData<GetCharityListUseCaseResult> = MutableLiveData()
private var resultObserver: Observer<GetCharityListUseCaseResult>

init {
resultObserver = Observer<GetCharityListUseCaseResult> { result ->
processGetCharityListResult(result)
}
}

override fun getCharityList() {

if (isLoading) {
if (result.value?.status == GetCharityListUseCase.STATUS.LOADING) {
return
}

isLoading = true
getCharityListDisposable = getCharityListUseCase.execute(GetCharityListUseCaseRequest())
.doOnNext { result -> processGetCharityListResult(result) }
.subscribe()
result = LiveDataReactiveStreams.fromPublisher(getCharityListUseCase.execute(GetCharityListUseCaseRequest()))
result.observe(lifecycleOwner, resultObserver)
}

private fun processGetCharityListResult(result: GetCharityListUseCaseResult) {
isLoading = false
if (result.status == GetCharityListUseCase.STATUS.SUCCESS) {
view.populateList(result.charityList)
} else {
view.displayNoData()
private fun processGetCharityListResult(result: GetCharityListUseCaseResult?) {
result?.let {
when (it.status) {
GetCharityListUseCase.STATUS.LOADING -> {
// do nothing
}
GetCharityListUseCase.STATUS.SUCCESS -> {
view.populateList(it.charityList)
}
else -> {
view.displayNoData()
}
}
}
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onPresenterDestroy() {
getCharityListDisposable?.dispose()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.enixma.sample.charity.presentation.charitylist.di

import android.arch.lifecycle.LifecycleOwner
import com.enixma.sample.charity.domain.getcharitylist.GetCharityListUseCase
import com.enixma.sample.charity.presentation.charitylist.CharityListContract
import com.enixma.sample.charity.presentation.charitylist.CharityListPresenter
Expand All @@ -8,10 +9,10 @@ import dagger.Provides
import javax.inject.Inject

@Module
class CharityListModule(private val view: CharityListContract.View) {
class CharityListModule(private val view: CharityListContract.View, private val lifecycleOwner: LifecycleOwner) {
@Provides
@Inject
fun provideCharityListPresenter(getCharityListUseCase: GetCharityListUseCase): CharityListContract.Action {
return CharityListPresenter(view, getCharityListUseCase)
return CharityListPresenter(view, lifecycleOwner, getCharityListUseCase)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import co.omise.android.models.Token
interface DonationContract {
interface View {
fun displayError(errorMessage: String)

fun displayLoading()
fun dismissLoading()
fun goToSuccessScreen()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import android.view.View
import android.view.ViewGroup
import co.omise.android.models.Token
import com.bumptech.glide.Glide
import com.enixma.sample.charity.BuildConfig
import com.enixma.sample.charity.R
import com.enixma.sample.charity.data.di.ServiceFactoryModule
import com.enixma.sample.charity.data.di.CharityDataModule
Expand All @@ -21,6 +22,7 @@ import com.enixma.sample.charity.presentation.creditcard.AddCreditCardActivity
import com.enixma.sample.charity.presentation.donation.di.DaggerDonationComponent
import com.enixma.sample.charity.presentation.donation.di.DonationModule
import com.enixma.sample.charity.presentation.success.SuccessActivity
import org.json.JSONObject
import javax.inject.Inject


Expand Down Expand Up @@ -61,7 +63,7 @@ class DonationFragment : Fragment(), DonationContract.View {
DaggerDonationComponent.builder()
.serviceFactoryModule(ServiceFactoryModule(activity))
.charityDataModule(CharityDataModule(activity))
.donationModule(DonationModule(this, viewModel))
.donationModule(DonationModule(this, this, viewModel))
.build().inject(this)
}

Expand All @@ -74,18 +76,31 @@ class DonationFragment : Fragment(), DonationContract.View {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)

lifecycle.addObserver(presenter as DonationPresenter)
initProgressDialog()
initDonationAmountSelection()
populateImage()
binding.editAmount.setOnClickListener {
displayAmountSelectionDialog()
}
binding.buttonDonate.setOnClickListener {
displayConfirmDialog()
if(!BuildConfig.DEBUG){
displayConfirmDialog()
} else {
// skip add credit card
presenter.donate(Token(JSONObject()))
progressDialog.show()
}
}
}

override fun displayLoading() {
progressDialog.show()
}

override fun dismissLoading() {
progressDialog.dismiss()
}

private fun initProgressDialog() {
progressDialog = ProgressDialog(activity)
progressDialog.setMessage(getString(R.string.alert_message_submit_donation))
Expand Down Expand Up @@ -141,12 +156,10 @@ class DonationFragment : Fragment(), DonationContract.View {
}

override fun goToSuccessScreen() {
progressDialog.dismiss()
startActivityForResult(SuccessActivity.getIntent(activity, viewModel.name, viewModel.amount.get()), REQUEST_FINAL)
}

override fun displayError(errorMessage: String) {
progressDialog.dismiss()
alertDialog = AlertDialog.Builder(activity).apply {
var message = if (errorMessage.isNullOrBlank()) getString(R.string.alert_message_communication_error) else errorMessage
this.setTitle(R.string.alert_title_error)
Expand Down
Loading