|
|
@@ -0,0 +1,269 @@
|
|
|
+package com.datarecovery.master.module.filerecover;
|
|
|
+
|
|
|
+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.BoxingUtil;
|
|
|
+import com.datarecovery.master.utils.FileUtil;
|
|
|
+import com.datarecovery.master.utils.FilesSearch;
|
|
|
+import com.datarecovery.master.utils.MediaStoreHelper;
|
|
|
+import com.datarecovery.master.utils.ToastUtil;
|
|
|
+
|
|
|
+import org.reactivestreams.Subscriber;
|
|
|
+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.disposables.Disposable;
|
|
|
+import atmob.rxjava.utils.RxJavaUtil;
|
|
|
+import dagger.hilt.android.lifecycle.HiltViewModel;
|
|
|
+
|
|
|
+
|
|
|
+@HiltViewModel
|
|
|
+public class FileRecoverViewModel extends BaseViewModel {
|
|
|
+
|
|
|
+ private final long SCANNING_COUNTDOWN = 1000 * 60 * 6;
|
|
|
+
|
|
|
+ private final int[] tabTitle = {R.string.word, R.string.excel, R.string.ppt, R.string.pdf};
|
|
|
+
|
|
|
+ private final List<MutableLiveData<Boolean>> checkList = new ArrayList<>();
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedWordList = new MutableLiveData<>(new ArrayList<>());
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedExcelList = new MutableLiveData<>(new ArrayList<>());
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPPTList = new MutableLiveData<>(new ArrayList<>());
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPDFList = new MutableLiveData<>(new ArrayList<>());
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>(new ArrayList<>());
|
|
|
+
|
|
|
+ private final MutableLiveData<Integer> checkPosition = new MutableLiveData<>();
|
|
|
+ private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
|
|
|
+ private final SingleLiveEvent<?> detectedFinish = new SingleLiveEvent<>();
|
|
|
+ private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
|
|
|
+ private int totalCount = 0;
|
|
|
+ private final MutableLiveData<Integer> totalDetectedCount = new MutableLiveData<>();
|
|
|
+ private final LiveData<String> selectedCountTxt;
|
|
|
+ private Disposable scanDisposable;
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ public FileRecoverViewModel() {
|
|
|
+ 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());
|
|
|
+ });
|
|
|
+ startFileScanning();
|
|
|
+ for (int i = 0; i < tabTitle.length; i++) checkList.add(new MutableLiveData<>(false));
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Integer> getCheckPosition() {
|
|
|
+ return checkPosition;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int[] getTabTitle() {
|
|
|
+ return tabTitle;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getDetectedWordList() {
|
|
|
+ return detectedWordList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getDetectedExcelList() {
|
|
|
+ return detectedExcelList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getDetectedPPTList() {
|
|
|
+ return detectedPPTList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getDetectedPDFList() {
|
|
|
+ return detectedPDFList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public LiveData<Boolean> getShowLoadingEvent() {
|
|
|
+ return showLoadingEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<?> getDetectedFinish() {
|
|
|
+ return detectedFinish;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Integer> getTotalDetectedCount() {
|
|
|
+ return totalDetectedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getSelectedList() {
|
|
|
+ return selectedList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<String> getSelectedCountTxt() {
|
|
|
+ return selectedCountTxt;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public LiveData<Boolean> getShowScanDialogEvent() {
|
|
|
+ return showScanDialogEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void setCheckPosition(int position) {
|
|
|
+ this.checkPosition.setValue(position);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void startFileScanning() {
|
|
|
+ FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.WORD, FilesSearch.DocumentFile.EXCEL, FilesSearch.DocumentFile.PPT, FilesSearch.DocumentFile.PDF)
|
|
|
+ .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .subscribe(new Subscriber<List<FilesSearch.DocumentFile>>() {
|
|
|
+ @Override
|
|
|
+ public void onSubscribe(Subscription s) {
|
|
|
+ s.request(Integer.MAX_VALUE);
|
|
|
+ scanDisposable = Disposable.fromSubscription(s);
|
|
|
+ addDisposable(scanDisposable);
|
|
|
+ showScanDialogEvent.setValue(true);
|
|
|
+ totalCount = 0;
|
|
|
+ totalDetectedCount.setValue(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(List<FilesSearch.DocumentFile> documentFiles) {
|
|
|
+ if (documentFiles == null || documentFiles.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ totalCount += documentFiles.size();
|
|
|
+ totalDetectedCount.setValue(totalCount);
|
|
|
+ for (FilesSearch.DocumentFile item : documentFiles) {
|
|
|
+ MutableLiveData<List<FilesSearch.DocumentFile>> liveData = null;
|
|
|
+ if (item.getCategory() == FilesSearch.DocumentFile.WORD) {
|
|
|
+ liveData = detectedWordList;
|
|
|
+ } else if (item.getCategory() == FilesSearch.DocumentFile.EXCEL) {
|
|
|
+ liveData = detectedExcelList;
|
|
|
+ } else if (item.getCategory() == FilesSearch.DocumentFile.PPT) {
|
|
|
+ liveData = detectedPPTList;
|
|
|
+ } else if (item.getCategory() == FilesSearch.DocumentFile.PDF) {
|
|
|
+ liveData = detectedPDFList;
|
|
|
+ }
|
|
|
+ if (liveData == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ List<FilesSearch.DocumentFile> list = getList(liveData);
|
|
|
+ list.add(0, item);
|
|
|
+ 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();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private List<FilesSearch.DocumentFile> getList(LiveData<List<FilesSearch.DocumentFile>> liveData) {
|
|
|
+ List<FilesSearch.DocumentFile> selectList = liveData.getValue();
|
|
|
+ if (selectList == null) {
|
|
|
+ selectList = new ArrayList<>();
|
|
|
+ }
|
|
|
+ return selectList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onCheckAllClick(boolean isCheck) {
|
|
|
+ if (!scanDisposable.isDisposed()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int index = BoxingUtil.boxing(checkPosition.getValue());
|
|
|
+ getCheckAll(index).setValue(isCheck);
|
|
|
+ int id = tabTitle[index];
|
|
|
+ MutableLiveData<List<FilesSearch.DocumentFile>> liveData = null;
|
|
|
+ if (id == R.string.word) {
|
|
|
+ liveData = detectedWordList;
|
|
|
+ } else if (id == R.string.excel) {
|
|
|
+ liveData = detectedExcelList;
|
|
|
+ } else if (id == R.string.ppt) {
|
|
|
+ liveData = detectedPPTList;
|
|
|
+ } else if (id == R.string.pdf) {
|
|
|
+ liveData = detectedPDFList;
|
|
|
+ }
|
|
|
+ if (liveData == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<FilesSearch.DocumentFile> list = getList(liveData);
|
|
|
+ if (list.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<FilesSearch.DocumentFile> selectedList = getList(this.selectedList);
|
|
|
+ for (FilesSearch.DocumentFile item : list) {
|
|
|
+ if (item.isCheck() != isCheck) {
|
|
|
+ if (isCheck) {
|
|
|
+ selectedList.add(item);
|
|
|
+ } else {
|
|
|
+ selectedList.remove(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ item.setCheck(isCheck);
|
|
|
+ }
|
|
|
+ this.selectedList.setValue(selectedList);
|
|
|
+ }
|
|
|
+
|
|
|
+ public MutableLiveData<Boolean> getCheckAll(int position) {
|
|
|
+ return checkList.get(position);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onExportClick() {
|
|
|
+ List<FilesSearch.DocumentFile> list = selectedList.getValue();
|
|
|
+ if (list == null || list.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //TODO 判断是否有会员
|
|
|
+ showLoadingEvent.setValue(true);
|
|
|
+ RxJavaUtil.doInBackground(() -> {
|
|
|
+ for (FilesSearch.DocumentFile item : list) {
|
|
|
+ MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_FILES, item.newInputStream(), FileUtil.getCreateFileName(item.getName(), ""));
|
|
|
+ item.setCheck(false);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }, o -> {
|
|
|
+ getCheckAll(BoxingUtil.boxing(checkPosition.getValue())).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 void itemClick(FilesSearch.DocumentFile documentFile) {
|
|
|
+ if (documentFile == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ documentFile.setCheck(!documentFile.isCheck());
|
|
|
+ List<FilesSearch.DocumentFile> list = getList(selectedList);
|
|
|
+ if (documentFile.isCheck()) {
|
|
|
+ list.add(documentFile);
|
|
|
+ } else {
|
|
|
+ list.remove(documentFile);
|
|
|
+ }
|
|
|
+ this.selectedList.setValue(list);
|
|
|
+ }
|
|
|
+}
|