/* * Copyright(c) 2017 lizhaotailang * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.github.marktony.espresso.mvp.packages; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.List; import io.github.marktony.espresso.data.Package; import io.github.marktony.espresso.data.source.PackagesRepository; import io.reactivex.Observable; import io.reactivex.ObservableSource; import io.reactivex.observers.DisposableObserver; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Function; import io.reactivex.functions.Predicate; import io.reactivex.schedulers.Schedulers; /** * Created by lizhaotailang on 2017/2/10. */ public class PackagesPresenter implements PackagesContract.Presenter { @NonNull private final PackagesContract.View view; @NonNull private final PackagesRepository packagesRepository; @NonNull private final CompositeDisposable compositeDisposable; @NonNull private PackageFilterType currentFiltering = PackageFilterType.ALL_PACKAGES; @Nullable private Package mayRemovePackage; public PackagesPresenter(@NonNull PackagesContract.View view, @NonNull PackagesRepository packagesRepository) { this.view = view; this.packagesRepository = packagesRepository; compositeDisposable = new CompositeDisposable(); this.view.setPresenter(this); } @Override public void subscribe() { loadPackages(); } @Override public void unsubscribe() { compositeDisposable.clear(); } /** * Get all the packages from repository and show on view. */ @Override public void loadPackages() { compositeDisposable.clear(); Disposable disposable = packagesRepository .getPackages() .flatMap(new Function<List<Package>, ObservableSource<Package>>() { @Override public ObservableSource<Package> apply(List<Package> list) throws Exception { return Observable.fromIterable(list); } }) .filter(new Predicate<Package>() { @Override public boolean test(Package aPackage) throws Exception { int state = Integer.parseInt(aPackage.getState()); switch (currentFiltering) { case ON_THE_WAY_PACKAGES: return state != Package.STATUS_DELIVERED; case DELIVERED_PACKAGES: return state == Package.STATUS_DELIVERED; case ALL_PACKAGES: return true; default: return true; } } }) .toList() .toObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver<List<Package>>() { @Override public void onNext(List<Package> value) { view.showPackages(value); } @Override public void onError(Throwable e) { view.showEmptyView(true); view.setLoadingIndicator(false); } @Override public void onComplete() { view.setLoadingIndicator(false); } }); compositeDisposable.add(disposable); } /** * Force update the packages data by accessing network. */ @Override public void refreshPackages() { Disposable disposable = packagesRepository .refreshPackages() .observeOn(Schedulers.io()) .subscribeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver<List<Package>>() { @Override public void onNext(List<Package> value) { } @Override public void onError(Throwable e) { view.setLoadingIndicator(false); view.showNetworkError(); } @Override public void onComplete() { view.setLoadingIndicator(false); loadPackages(); } }); compositeDisposable.add(disposable); } /** * Set all the packages unreadable which means data is NOT brand new. */ @Override public void markAllPacksRead() { packagesRepository.setAllPackagesRead(); loadPackages(); } /** * Sets the current package filtering type. * * @param requestType Can be {@link PackageFilterType#ALL_PACKAGES}, * {@link PackageFilterType#ON_THE_WAY_PACKAGES}, or * {@link PackageFilterType#DELIVERED_PACKAGES} */ @Override public void setFiltering(@NonNull PackageFilterType requestType) { currentFiltering = requestType; } /** * Get current package filtering type. * @return Current filtering type. */ @Override public PackageFilterType getFiltering() { return currentFiltering; } /** * Set a specific package's read-status, readable or unreadable, * which means the data is or not brand new. * @param packageId The package number. * @param readable Readable or unreadable(New or dated). */ @Override public void setPackageReadable(@NonNull final String packageId, boolean readable) { packagesRepository.setPackageReadable(packageId, readable); loadPackages(); } /** * Delete a package from the repository. * But this action could revoked. * See {@link PackagesPresenter#recoverPackage()} for more * recovering details * @param position The position of the package which may * be delete completely. */ @Override public void deletePackage(final int position) { if (position < 0) { return; } Disposable disposable = packagesRepository .getPackages() .flatMap(new Function<List<Package>, ObservableSource<Package>>() { @Override public ObservableSource<Package> apply(List<Package> list) throws Exception { return Observable.fromIterable(list); } }) .filter(new Predicate<Package>() { @Override public boolean test(Package aPackage) throws Exception { int state = Integer.parseInt(aPackage.getState()); switch (currentFiltering) { case ON_THE_WAY_PACKAGES: return state != Package.STATUS_DELIVERED; case DELIVERED_PACKAGES: return state == Package.STATUS_DELIVERED; case ALL_PACKAGES: return true; default: return true; } } }) .toList() .toObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver<List<Package>>() { @Override public void onNext(List<Package> value) { mayRemovePackage = value.get(position); packagesRepository.deletePackage(mayRemovePackage.getNumber()); value.remove(position); view.showPackages(value); view.showPackageRemovedMsg(mayRemovePackage.getName()); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } }); compositeDisposable.add(disposable); } /** * Share a package's data. * Just get the wanted package and pass it to view. * @param packageId The package number. */ @Override public void setShareData(@NonNull String packageId) { Disposable disposable = packagesRepository .getPackage(packageId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver<Package>() { @Override public void onNext(Package aPackage) { view.shareTo(aPackage); } @Override public void onError(Throwable throwable) { } @Override public void onComplete() { } }); compositeDisposable.add(disposable); } /** * Revoke package which may be removed from repository. */ @Override public void recoverPackage() { if (mayRemovePackage != null) { packagesRepository.savePackage(mayRemovePackage); } loadPackages(); } }