|
|
@@ -0,0 +1,204 @@
|
|
|
+package com.datarecovery.master.module.videorecover;
|
|
|
+
|
|
|
+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.data.KVUtils;
|
|
|
+import com.atmob.common.runtime.ContextUtil;
|
|
|
+import com.datarecovery.master.R;
|
|
|
+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.annotations.NonNull;
|
|
|
+import atmob.reactivex.rxjava3.disposables.Disposable;
|
|
|
+import atmob.rxjava.utils.RxJavaUtil;
|
|
|
+import dagger.hilt.android.lifecycle.HiltViewModel;
|
|
|
+
|
|
|
+
|
|
|
+@HiltViewModel
|
|
|
+public class VideoRecoverViewModel extends BaseViewModel {
|
|
|
+
|
|
|
+ private final String IS_SHOW_VIDEO_HINT = "isShowVideoHint";
|
|
|
+ private final long SCANNING_COUNTDOWN = 1000 * 60 * 6;
|
|
|
+ private LiveData<String> selectedCountTxt;
|
|
|
+ private final MutableLiveData<Boolean> checkAll = new MutableLiveData<>();
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedVideoList = new MutableLiveData<>();
|
|
|
+ private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>();
|
|
|
+
|
|
|
+ private final SingleLiveEvent<?> detectedFinish = new SingleLiveEvent<>();
|
|
|
+ private final SingleLiveEvent<?> finishEvent = new SingleLiveEvent<>();
|
|
|
+ private final SingleLiveEvent<Boolean> showScanDialogEvent = new SingleLiveEvent<>();
|
|
|
+ private final SingleLiveEvent<Boolean> showLoadingEvent = new SingleLiveEvent<>();
|
|
|
+ private int totalCount = 0;
|
|
|
+ private final MutableLiveData<Integer> totalDetectedCount = new MutableLiveData<>();
|
|
|
+ private final MutableLiveData<Boolean> isShowHint = new MutableLiveData<>();
|
|
|
+ private Disposable scanDisposable;
|
|
|
+
|
|
|
+
|
|
|
+ @Inject
|
|
|
+ public VideoRecoverViewModel() {
|
|
|
+ startVideoScanning();
|
|
|
+ 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());
|
|
|
+ });
|
|
|
+ if (KVUtils.getDefault().getBoolean(IS_SHOW_VIDEO_HINT, true)) {
|
|
|
+ isShowHint.setValue(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Boolean> getIsShowHint() {
|
|
|
+ return isShowHint;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getDetectedVideoList() {
|
|
|
+ return detectedVideoList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<?> getDetectedFinish() {
|
|
|
+ return detectedFinish;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<?> getFinishEvent() {
|
|
|
+ return finishEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Boolean> getShowScanDialogEvent() {
|
|
|
+ return showScanDialogEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Integer> getTotalDetectedCount() {
|
|
|
+ return totalDetectedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<List<FilesSearch.DocumentFile>> getSelectedList() {
|
|
|
+ return selectedList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Boolean> getCheckAll() {
|
|
|
+ return checkAll;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<String> getSelectedCountTxt() {
|
|
|
+ return selectedCountTxt;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onCheckAllClick(boolean isCheck) {
|
|
|
+ if (!scanDisposable.isDisposed()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ checkAll.setValue(isCheck);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveData<Boolean> getShowLoadingEvent() {
|
|
|
+ return showLoadingEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void startVideoScanning() {
|
|
|
+ FilesSearch.search(ContextUtil.getContext(), FilesSearch.DocumentFile.VIDEO)
|
|
|
+ .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) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ totalCount += documentFiles.size();
|
|
|
+ totalDetectedCount.setValue(totalCount);
|
|
|
+ List<FilesSearch.DocumentFile> videoList = detectedVideoList.getValue();
|
|
|
+ if (videoList == null) {
|
|
|
+ videoList = new ArrayList<>();
|
|
|
+ }
|
|
|
+ videoList.addAll(0, documentFiles);
|
|
|
+ detectedVideoList.setValue(videoList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @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 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_VIDEO, item.newInputStream(), FileUtil.getCreateFileName(item.getName(), ".mp4"));
|
|
|
+ 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 void setItemCheck(@NonNull FilesSearch.DocumentFile file) {
|
|
|
+ file.setCheck(!file.isCheck());
|
|
|
+ List<FilesSearch.DocumentFile> list = selectedList.getValue();
|
|
|
+ if (list == null) {
|
|
|
+ list = new ArrayList<>();
|
|
|
+ }
|
|
|
+ if (file.isCheck()) {
|
|
|
+ list.add(file);
|
|
|
+ } else {
|
|
|
+ list.remove(file);
|
|
|
+ }
|
|
|
+ selectedList.setValue(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void closeHintClick() {
|
|
|
+ KVUtils.getDefault().putBoolean(IS_SHOW_VIDEO_HINT, false);
|
|
|
+ isShowHint.setValue(false);
|
|
|
+ }
|
|
|
+}
|