FileRecoverViewModel.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package com.datarecovery.master.module.filerecover;
  2. import androidx.lifecycle.LiveData;
  3. import androidx.lifecycle.MutableLiveData;
  4. import androidx.lifecycle.Transformations;
  5. import com.atmob.app.lib.base.BaseViewModel;
  6. import com.atmob.app.lib.livedata.SingleLiveEvent;
  7. import com.atmob.common.runtime.ContextUtil;
  8. import com.datarecovery.master.R;
  9. import com.datarecovery.master.utils.BoxingUtil;
  10. import com.datarecovery.master.utils.FileUtil;
  11. import com.datarecovery.master.utils.FilesSearch;
  12. import com.datarecovery.master.utils.MediaStoreHelper;
  13. import com.datarecovery.master.utils.ToastUtil;
  14. import org.reactivestreams.Subscriber;
  15. import org.reactivestreams.Subscription;
  16. import java.util.ArrayList;
  17. import java.util.List;
  18. import java.util.concurrent.TimeUnit;
  19. import javax.inject.Inject;
  20. import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
  21. import atmob.reactivex.rxjava3.disposables.Disposable;
  22. import atmob.rxjava.utils.RxJavaUtil;
  23. import dagger.hilt.android.lifecycle.HiltViewModel;
  24. @HiltViewModel
  25. public class FileRecoverViewModel extends BaseViewModel {
  26. private final long SCANNING_COUNTDOWN = 1000 * 60 * 6;
  27. private final int[] tabTitle = {R.string.word, R.string.excel, R.string.ppt, R.string.pdf};
  28. private final List<MutableLiveData<Boolean>> checkList = new ArrayList<>();
  29. private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedWordList = new MutableLiveData<>(new ArrayList<>());
  30. private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedExcelList = new MutableLiveData<>(new ArrayList<>());
  31. private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPPTList = new MutableLiveData<>(new ArrayList<>());
  32. private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedPDFList = new MutableLiveData<>(new ArrayList<>());
  33. private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>(new ArrayList<>());
  34. private final MutableLiveData<Integer> checkPosition = new MutableLiveData<>();
  35. private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
  36. private final SingleLiveEvent<?> detectedFinish = new SingleLiveEvent<>();
  37. private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
  38. private int totalCount = 0;
  39. private final MutableLiveData<Integer> totalDetectedCount = new MutableLiveData<>();
  40. private final LiveData<String> selectedCountTxt;
  41. private Disposable scanDisposable;
  42. @Inject
  43. public FileRecoverViewModel() {
  44. selectedCountTxt = Transformations.map(selectedList, list -> {
  45. if (list == null || list.isEmpty()) {
  46. return ContextUtil.getContext().getString(R.string.export);
  47. }
  48. return ContextUtil.getContext().getString(R.string.export_count, list.size());
  49. });
  50. startFileScanning();
  51. for (int i = 0; i < tabTitle.length; i++) checkList.add(new MutableLiveData<>(false));
  52. }
  53. public LiveData<Integer> getCheckPosition() {
  54. return checkPosition;
  55. }
  56. public int[] getTabTitle() {
  57. return tabTitle;
  58. }
  59. public LiveData<List<FilesSearch.DocumentFile>> getDetectedWordList() {
  60. return detectedWordList;
  61. }
  62. public LiveData<List<FilesSearch.DocumentFile>> getDetectedExcelList() {
  63. return detectedExcelList;
  64. }
  65. public LiveData<List<FilesSearch.DocumentFile>> getDetectedPPTList() {
  66. return detectedPPTList;
  67. }
  68. public LiveData<List<FilesSearch.DocumentFile>> getDetectedPDFList() {
  69. return detectedPDFList;
  70. }
  71. public LiveData<Boolean> getShowLoadingEvent() {
  72. return showLoadingEvent;
  73. }
  74. public LiveData<?> getDetectedFinish() {
  75. return detectedFinish;
  76. }
  77. public LiveData<Integer> getTotalDetectedCount() {
  78. return totalDetectedCount;
  79. }
  80. public LiveData<List<FilesSearch.DocumentFile>> getSelectedList() {
  81. return selectedList;
  82. }
  83. public LiveData<String> getSelectedCountTxt() {
  84. return selectedCountTxt;
  85. }
  86. public LiveData<Boolean> getShowScanDialogEvent() {
  87. return showScanDialogEvent;
  88. }
  89. public void setCheckPosition(int position) {
  90. this.checkPosition.setValue(position);
  91. }
  92. private void startFileScanning() {
  93. FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.WORD, FilesSearch.DocumentFile.EXCEL, FilesSearch.DocumentFile.PPT, FilesSearch.DocumentFile.PDF)
  94. .take(SCANNING_COUNTDOWN, TimeUnit.MILLISECONDS)
  95. .observeOn(AndroidSchedulers.mainThread())
  96. .subscribe(new Subscriber<List<FilesSearch.DocumentFile>>() {
  97. @Override
  98. public void onSubscribe(Subscription s) {
  99. s.request(Integer.MAX_VALUE);
  100. scanDisposable = Disposable.fromSubscription(s);
  101. addDisposable(scanDisposable);
  102. showScanDialogEvent.setValue(true);
  103. totalCount = 0;
  104. totalDetectedCount.setValue(0);
  105. }
  106. @Override
  107. public void onNext(List<FilesSearch.DocumentFile> documentFiles) {
  108. if (documentFiles == null || documentFiles.isEmpty()) {
  109. return;
  110. }
  111. totalCount += documentFiles.size();
  112. totalDetectedCount.setValue(totalCount);
  113. for (FilesSearch.DocumentFile item : documentFiles) {
  114. MutableLiveData<List<FilesSearch.DocumentFile>> liveData = null;
  115. if (item.getCategory() == FilesSearch.DocumentFile.WORD) {
  116. liveData = detectedWordList;
  117. } else if (item.getCategory() == FilesSearch.DocumentFile.EXCEL) {
  118. liveData = detectedExcelList;
  119. } else if (item.getCategory() == FilesSearch.DocumentFile.PPT) {
  120. liveData = detectedPPTList;
  121. } else if (item.getCategory() == FilesSearch.DocumentFile.PDF) {
  122. liveData = detectedPDFList;
  123. }
  124. if (liveData == null) {
  125. continue;
  126. }
  127. List<FilesSearch.DocumentFile> list = getList(liveData);
  128. list.add(0, item);
  129. liveData.setValue(list);
  130. }
  131. }
  132. @Override
  133. public void onError(Throwable t) {
  134. showScanDialogEvent.setValue(false);
  135. }
  136. @Override
  137. public void onComplete() {
  138. detectedFinish.call();
  139. }
  140. });
  141. }
  142. public void cancelScan() {
  143. if (scanDisposable != null) scanDisposable.dispose();
  144. }
  145. private List<FilesSearch.DocumentFile> getList(LiveData<List<FilesSearch.DocumentFile>> liveData) {
  146. List<FilesSearch.DocumentFile> selectList = liveData.getValue();
  147. if (selectList == null) {
  148. selectList = new ArrayList<>();
  149. }
  150. return selectList;
  151. }
  152. public void onCheckAllClick(boolean isCheck) {
  153. int index = BoxingUtil.boxing(checkPosition.getValue());
  154. getCheckAll(index).setValue(isCheck);
  155. int id = tabTitle[index];
  156. MutableLiveData<List<FilesSearch.DocumentFile>> liveData = null;
  157. if (id == R.string.word) {
  158. liveData = detectedWordList;
  159. } else if (id == R.string.excel) {
  160. liveData = detectedExcelList;
  161. } else if (id == R.string.ppt) {
  162. liveData = detectedPPTList;
  163. } else if (id == R.string.pdf) {
  164. liveData = detectedPDFList;
  165. }
  166. if (liveData == null) {
  167. return;
  168. }
  169. List<FilesSearch.DocumentFile> list = getList(liveData);
  170. if (list.isEmpty()) {
  171. return;
  172. }
  173. List<FilesSearch.DocumentFile> selectedList = getList(this.selectedList);
  174. for (FilesSearch.DocumentFile item : list) {
  175. if (item.isCheck() != isCheck) {
  176. if (isCheck) {
  177. selectedList.add(item);
  178. } else {
  179. selectedList.remove(item);
  180. }
  181. }
  182. item.setCheck(isCheck);
  183. }
  184. this.selectedList.setValue(selectedList);
  185. }
  186. public MutableLiveData<Boolean> getCheckAll(int position) {
  187. return checkList.get(position);
  188. }
  189. public void onExportClick() {
  190. List<FilesSearch.DocumentFile> list = selectedList.getValue();
  191. if (list == null || list.size() == 0) {
  192. return;
  193. }
  194. //TODO 判断是否有会员
  195. showLoadingEvent.setValue(true);
  196. RxJavaUtil.doInBackground(() -> {
  197. for (FilesSearch.DocumentFile item : list) {
  198. MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_FILES, item.newInputStream(), FileUtil.getCreateFileName(item.getName(), ""));
  199. item.setCheck(false);
  200. }
  201. return true;
  202. }, o -> {
  203. getCheckAll(BoxingUtil.boxing(checkPosition.getValue())).setValue(false);
  204. showLoadingEvent.setValue(false);
  205. ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
  206. list.clear();
  207. selectedList.setValue(list);
  208. }, throwable -> {
  209. showLoadingEvent.setValue(false);
  210. ToastUtil.show(R.string.export_fail, ToastUtil.LENGTH_SHORT);
  211. });
  212. }
  213. public void itemClick(FilesSearch.DocumentFile documentFile) {
  214. if (documentFile == null) {
  215. return;
  216. }
  217. documentFile.setCheck(!documentFile.isCheck());
  218. List<FilesSearch.DocumentFile> list = getList(selectedList);
  219. if (documentFile.isCheck()) {
  220. list.add(documentFile);
  221. } else {
  222. list.remove(documentFile);
  223. }
  224. this.selectedList.setValue(list);
  225. }
  226. }