package com.datarecovery.master.module.imgrecover; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Transformations; import com.atmob.app.lib.base.BaseViewModel; import com.atmob.app.lib.livedata.SingleLiveEvent; import com.atmob.common.runtime.ContextUtil; import com.datarecovery.master.R; import com.datarecovery.master.utils.FileUtil; import com.datarecovery.master.utils.ImageDeepDetector; import com.datarecovery.master.utils.MediaStoreHelper; import com.datarecovery.master.utils.ToastUtil; import org.reactivestreams.Subscription; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import atmob.reactivex.rxjava3.annotations.NonNull; import atmob.reactivex.rxjava3.core.FlowableSubscriber; import atmob.reactivex.rxjava3.disposables.Disposable; import atmob.rxjava.utils.RxJavaUtil; import dagger.hilt.android.lifecycle.HiltViewModel; @HiltViewModel public class ImageRecoverViewModel extends BaseViewModel { private final long SCANNING_COUNTDOWN = 1000 * 60 * 6; private final MutableLiveData> detectedPhotoImg = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> detectedWxImg = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> detectedQQImg = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> detectedOtherImg = new MutableLiveData<>(new ArrayList<>()); private LiveData detectedPhotoTitle; private LiveData detectedWxTitle; private LiveData detectedQQTitle; private LiveData detectedOtherTitle; private final SingleLiveEvent previewEvent = new SingleLiveEvent<>(); private final SingleLiveEvent detectedFinish = new SingleLiveEvent<>(); private final SingleLiveEvent showClearDialog = new SingleLiveEvent<>(); private final SingleLiveEvent showScanDialogEvent = new SingleLiveEvent<>(); private final SingleLiveEvent showLoadingEvent = new SingleLiveEvent<>(); private final SingleLiveEvent notifyList = new SingleLiveEvent<>(); private final MutableLiveData barTitle = new MutableLiveData<>(); private final MutableLiveData checkAll = new MutableLiveData<>(false); //总探测到的图片数量 private int totalCount = 0; private final MutableLiveData totalDetectedCount = new MutableLiveData<>(); private final MutableLiveData> selectedList = new MutableLiveData<>(new ArrayList<>()); private LiveData selectedCountTxt; private Disposable scanDisposable; private int type; @Inject public ImageRecoverViewModel() { barTitle.setValue(ContextUtil.getContext().getString(R.string.iamge_recover_all)); startImageScanning(); initLiveData(); } public LiveData getShowClearDialog() { return showClearDialog; } public LiveData getNotifyList() { return notifyList; } public LiveData getShowLoadingEvent() { return showLoadingEvent; } public LiveData getPreviewEvent() { return previewEvent; } public LiveData getDetectedFinish() { return detectedFinish; } public LiveData getTotalDetectedCount() { return totalDetectedCount; } public LiveData getSelectedCountTxt() { return selectedCountTxt; } public LiveData> getSelectedList() { return selectedList; } public LiveData> getDetectedPhotoImg() { return detectedPhotoImg; } public LiveData> getDetectedWxImg() { return detectedWxImg; } public LiveData> getDetectedQQImg() { return detectedQQImg; } public LiveData> getDetectedOtherImg() { return detectedOtherImg; } public LiveData getDetectedPhotoTitle() { return detectedPhotoTitle; } public LiveData getDetectedWxTitle() { return detectedWxTitle; } public LiveData getDetectedQQTitle() { return detectedQQTitle; } public LiveData getDetectedOtherTitle() { return detectedOtherTitle; } public LiveData getShowScanDialogEvent() { return showScanDialogEvent; } public LiveData getCheckAll() { return checkAll; } public LiveData getBarTitle() { return barTitle; } public int getType() { return type; } private void initLiveData() { detectedPhotoTitle = Transformations.map(detectedPhotoImg, list -> ContextUtil.getContext().getString(R.string.photo_count, (list == null || list.isEmpty()) ? 0 : list.size())); detectedWxTitle = Transformations.map(detectedWxImg, list -> ContextUtil.getContext().getString(R.string.wx_count, (list == null || list.isEmpty()) ? 0 : list.size())); detectedQQTitle = Transformations.map(detectedQQImg, list -> ContextUtil.getContext().getString(R.string.qq_count, (list == null || list.isEmpty()) ? 0 : list.size())); detectedOtherTitle = Transformations.map(detectedOtherImg, list -> ContextUtil.getContext().getString(R.string.other_count, (list == null || list.isEmpty()) ? 0 : list.size())); } public void onCheckAllClick(boolean isCheck) { checkAll.setValue(isCheck); List selectList = getList(selectedList); setListCheck(detectedPhotoImg.getValue(), isCheck); setListCheck(detectedWxImg.getValue(), isCheck); setListCheck(detectedQQImg.getValue(), isCheck); setListCheck(detectedOtherImg.getValue(), isCheck); if (isCheck) { selectList.clear(); selectList.addAll(getList(detectedPhotoImg)); selectList.addAll(getList(detectedWxImg)); selectList.addAll(getList(detectedQQImg)); selectList.addAll(getList(detectedOtherImg)); } else { selectList.clear(); } selectedList.setValue(selectList); } private void setListCheck(List list, boolean isCheck) { if (list == null || list.isEmpty()) { return; } for (ImageDeepDetector.ImageFile imageFile : list) { imageFile.setCheck(isCheck); } } private List getList(LiveData> liveData) { List selectList = liveData.getValue(); if (selectList == null) { selectList = new ArrayList<>(); } return selectList; } private void startImageScanning() { ImageDeepDetector.detect(ContextUtil.getContext()) .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new FlowableSubscriber>() { @Override public void onSubscribe(@NonNull Subscription s) { s.request(Integer.MAX_VALUE); scanDisposable = Disposable.fromSubscription(s); addDisposable(scanDisposable); showScanDialogEvent.setValue(true); checkAll.setValue(false); totalCount = 0; totalDetectedCount.setValue(0); } @Override public void onNext(List imageFiles) { if (imageFiles == null) { return; } totalCount += imageFiles.size(); totalDetectedCount.setValue(totalCount); for (ImageDeepDetector.ImageFile imageFile : imageFiles) { MutableLiveData> liveData; if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) { liveData = detectedPhotoImg; } else if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) { liveData = detectedWxImg; } else if (imageFile.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) { liveData = detectedQQImg; } else { liveData = detectedOtherImg; } List list = getList(liveData); list.add(0, imageFile); liveData.setValue(list); } } @Override public void onError(Throwable t) { showScanDialogEvent.setValue(false); } @Override public void onComplete() { detectedFinish.call(); } }); } public void cancelScan() { if (scanDisposable != null) scanDisposable.dispose(); } public void setItemCheck(@NonNull ImageDeepDetector.ImageFile imageFile) { imageFile.setCheck(!imageFile.isCheck()); List list = getList(this.selectedList); if (imageFile.isCheck()) { list.add(imageFile); } else { list.remove(imageFile); } selectedList.setValue(list); } public void checkPreview(@NonNull ImageDeepDetector.ImageFile imageFile) { if (type == ImageRecoverActivity.Type.DELETE) { return; } //TODO 判断是否有会员 previewEvent.setValue(imageFile); } public void onOperationClick() { if (type == ImageRecoverActivity.Type.DELETE) { showClearDialog.call(); } else { onExportClick(); } } public void executeImageDelete() { List list = getList(selectedList); if (list.size() == 0) { return; } showLoadingEvent.setValue(true); RxJavaUtil.doInBackground(() -> { for (ImageDeepDetector.ImageFile item : list) { item.delete(); MutableLiveData> liveData; if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_GALLERY) { liveData = detectedPhotoImg; } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_WECHAT) { liveData = detectedWxImg; } else if (item.getCategory() == ImageDeepDetector.ImageFile.CATEGORY_QQ) { liveData = detectedQQImg; } else { liveData = detectedOtherImg; } List itemList = getList(liveData); itemList.remove(item); } return true; }, o -> { checkAll.setValue(false); showLoadingEvent.setValue(false); ToastUtil.show(R.string.delete_success, ToastUtil.LENGTH_SHORT); list.clear(); selectedList.setValue(list); notifyList.call(); }, throwable -> { showLoadingEvent.setValue(false); ToastUtil.show(R.string.delete_fail, ToastUtil.LENGTH_SHORT); }); } public void onExportClick() { List list = getList(selectedList); if (list.size() == 0) { return; } //TODO 判断是否有会员 showLoadingEvent.setValue(true); RxJavaUtil.doInBackground(() -> { for (ImageDeepDetector.ImageFile item : list) { MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_IMAGE, item.newInputStream(), FileUtil.getExportImageFileName(item.getName())); item.setCheck(false); } return true; }, o -> { checkAll.setValue(false); showLoadingEvent.setValue(false); ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT); list.clear(); selectedList.setValue(list); }, throwable -> { showLoadingEvent.setValue(false); ToastUtil.show(R.string.export_fail, ToastUtil.LENGTH_SHORT); }); } public List getAllDetectedList() { ArrayList allList = new ArrayList<>(); allList.addAll(getList(detectedPhotoImg)); allList.addAll(getList(detectedWxImg)); allList.addAll(getList(detectedQQImg)); allList.addAll(getList(detectedOtherImg)); return allList; } public int getPosition(@NonNull List list, ImageDeepDetector.ImageFile target) { return list.indexOf(target); } public void setOperationType(@ImageRecoverActivity.Type int type) { this.type = type; switch (type) { case ImageRecoverActivity.Type.DELETE: selectedCountTxt = Transformations.map(selectedList, list -> { if (list == null || list.isEmpty()) { return ContextUtil.getContext().getString(R.string.delete); } return ContextUtil.getContext().getString(R.string.delete_count, list.size()); }); break; case ImageRecoverActivity.Type.RECOVER: selectedCountTxt = Transformations.map(selectedList, list -> { if (list == null || list.isEmpty()) { return ContextUtil.getContext().getString(R.string.export); } return ContextUtil.getContext().getString(R.string.export_count, list.size()); }); break; } } }