package com.datarecovery.master.module.imgrecover; import android.annotation.SuppressLint; import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import androidx.activity.result.ActivityResult; import androidx.activity.result.IntentSenderRequest; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.ConcatAdapter; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.atmob.app.lib.base.BaseActivity; import com.atmob.common.logging.AtmobLog; import com.atmob.common.runtime.ActivityUtil; import com.atmob.common.runtime.ContextUtil; import com.datarecovery.master.R; import com.datarecovery.master.data.consts.EventId; import com.datarecovery.master.databinding.ActivityImageRecoverBinding; import com.datarecovery.master.databinding.ItemTabImageRecoverBinding; import com.datarecovery.master.dialog.CommonLoadingDialog; import com.datarecovery.master.dialog.CommonSureDialog; import com.datarecovery.master.dialog.ScanFileDialog; import com.datarecovery.master.dialog.ScanProgressDialog; import com.datarecovery.master.handler.EventHelper; import com.datarecovery.master.module.member.MemberType; import com.datarecovery.master.module.preview.PreviewActivity; import com.datarecovery.master.utils.ActivityForResultUtil; import com.datarecovery.master.utils.BoxingUtil; import com.datarecovery.master.utils.FilePermissionHelper; import com.datarecovery.master.utils.GridRecoverItemDecoration; import com.datarecovery.master.utils.ImageDeepDetector; import com.datarecovery.master.utils.Maps; import com.datarecovery.master.utils.ReportUtil; import com.datarecovery.master.utils.ToastUtil; import com.google.android.material.tabs.TabLayout; import com.gyf.immersionbar.ImmersionBar; import java.util.List; import java.util.Objects; import dagger.hilt.android.AndroidEntryPoint; @AndroidEntryPoint public class ImageRecoverActivity extends BaseActivity implements ImageItemAdapter.onItemClick { private ConcatAdapter concatAdapter; private static final String TYPE = "type"; private static final String IS_TRIAL = "is_trial"; ImageRecoverViewModel imageRecoverViewModel; private final int[] tabTitle = {R.string.photo, R.string.wx, R.string.qq, R.string.other}; private CommonSureDialog backDialog; private CommonSureDialog clearDialog; private CommonSureDialog showTrialExportFailDialog; private CommonSureDialog showTrialFinishDialog; private CommonLoadingDialog loadingDialog; private ScanFileDialog scanFileDialog; private ImageItemAdapter photoAdapter; private ImageItemAdapter wxAdapter; private ImageItemAdapter qqAdapter; private ImageItemAdapter otherAdapter; private GridLayoutManager gridLayoutManager; public static void start(Context context, @MemberType String type) { start(context, type, false); } public static void start(Context context, @MemberType String type, boolean isTrial) { Intent intent = new Intent(context, ImageRecoverActivity.class); if (!(context instanceof Activity)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } intent.putExtra(TYPE, type); intent.putExtra(IS_TRIAL, isTrial); context.startActivity(intent); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initData(); initView(); initObserver(); initPermission(); } private void initPermission() { new FilePermissionHelper().requestDataFilePermission(this, imageRecoverViewModel.getType(), imageRecoverViewModel.isTrial(), new FilePermissionHelper.NextStepCallback() { @Override public void onNextStep() { imageRecoverViewModel.startImageScanning(); } @Override public void onCancel() { finish(); } }); } private void initData() { Intent intent = getIntent(); if (intent != null) { imageRecoverViewModel.setType(intent.getStringExtra(TYPE)); imageRecoverViewModel.setIsTrial(intent.getBooleanExtra(IS_TRIAL, false)); } } private void initView() { binding.toolBar.setNavigationOnClickListener(v -> onBackPressed()); addTopStatusBarHeight(binding.toolBar); initRecycleView(); initTabLayout(); } private void initRecycleView() { ImageTitleAdapter photoTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedPhotoTitle()); photoAdapter = new ImageItemAdapter(imageRecoverViewModel.getType(), this); photoAdapter.setOnItemClick(this); ImageTitleAdapter wxTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedWxTitle()); wxAdapter = new ImageItemAdapter(imageRecoverViewModel.getType(), this); wxAdapter.setOnItemClick(this); ImageTitleAdapter qqTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedQQTitle()); qqAdapter = new ImageItemAdapter(imageRecoverViewModel.getType(), this); qqAdapter.setOnItemClick(this); ImageTitleAdapter otherTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedOtherTitle()); otherAdapter = new ImageItemAdapter(imageRecoverViewModel.getType(), this); otherAdapter.setOnItemClick(this); concatAdapter = new ConcatAdapter( photoTitleAdapter, photoAdapter, wxTitleAdapter, wxAdapter, qqTitleAdapter, qqAdapter, otherTitleAdapter, otherAdapter ); binding.ryImageRecover.setAdapter(concatAdapter); gridLayoutManager = new GridLayoutManager(this, 3); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position == getPhotoPosition() || position == getWxPosition() || position == getQQPosition() || position == getOtherPosition()) { return 3; } return 1; } }); binding.ryImageRecover.addItemDecoration(new GridRecoverItemDecoration(3, 0.0282222222222222f, 0.0202222222222222f)); binding.ryImageRecover.setLayoutManager(gridLayoutManager); RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { int firstVisibleItem = gridLayoutManager.findFirstVisibleItemPosition(); int lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition(); if (imageRecoverViewModel.isTrial()) { imageRecoverViewModel.scrollPosition(gridLayoutManager.findLastCompletelyVisibleItemPosition(), gridLayoutManager.getItemCount()); } int photoPosition = getPhotoPosition(); int wxPosition = getWxPosition(); int qqPosition = getQQPosition(); int otherPosition = getOtherPosition(); if (firstVisibleItem == photoPosition || (firstVisibleItem >= photoPosition && lastVisibleItem < wxPosition)) { binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0)); } else if (firstVisibleItem == wxPosition || (firstVisibleItem >= wxPosition && lastVisibleItem < qqPosition)) { binding.tabLayout.selectTab(binding.tabLayout.getTabAt(1)); } else if (firstVisibleItem == qqPosition || (firstVisibleItem >= qqPosition && lastVisibleItem < otherPosition)) { binding.tabLayout.selectTab(binding.tabLayout.getTabAt(2)); } else if (firstVisibleItem >= otherPosition) { binding.tabLayout.selectTab(binding.tabLayout.getTabAt(3)); } } }; if (imageRecoverViewModel.isTrial()) { binding.ryImageRecover.setOnFlingListener(new RecyclerView.OnFlingListener() { @Override public boolean onFling(int velocityX, int velocityY) { if (gridLayoutManager.findFirstCompletelyVisibleItemPosition() == 0 && gridLayoutManager.findLastCompletelyVisibleItemPosition() == gridLayoutManager.getItemCount() - 1 && velocityY > 0) { showTrialFinishDialog(); return true; } return false; } }); } binding.ryImageRecover.addOnScrollListener(onScrollListener); } public int getPhotoPosition() { return 0; } public int getWxPosition() { return getPhotoPosition() + photoAdapter.getItemCount() + 1; } public int getQQPosition() { return getWxPosition() + wxAdapter.getItemCount() + 1; } public int getOtherPosition() { return getQQPosition() + qqAdapter.getItemCount() + 1; } @Override public void onCheck(ImageDeepDetector.ImageFile imageFile) { if (imageFile == null) { return; } imageRecoverViewModel.setItemCheck(imageFile); } @Override public void onImgItemClick(ImageDeepDetector.ImageFile imageFile) { if (imageFile == null) { return; } // ToastUtil.show(imageFile.getPath(), ToastUtil.LENGTH_SHORT); if (Objects.equals(imageRecoverViewModel.getType(), MemberType.APP_IMAGE_CLEAN)) { imageRecoverViewModel.setItemCheck(imageFile); } else { imageRecoverViewModel.checkPreview(imageFile); } } private void initTabLayout() { binding.tabLayout.removeAllTabs(); binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @SuppressLint("UseCompatLoadingForDrawables") @Override public void onTabSelected(TabLayout.Tab tab) { if (tab.getCustomView() == null) { return; } ItemTabImageRecoverBinding itemBinding = ItemTabImageRecoverBinding.bind(tab.getCustomView()); itemBinding.tabTitle.setTextColor(getResources().getColor(com.atmob.app.base.R.color.white)); itemBinding.tabTitle.setBackground(getResources().getDrawable(R.drawable.bg_tab_selected)); } @Override public void onTabUnselected(TabLayout.Tab tab) { if (tab.getCustomView() == null) { return; } ItemTabImageRecoverBinding itemBinding = ItemTabImageRecoverBinding.bind(tab.getCustomView()); itemBinding.tabTitle.setTextColor(getResources().getColor(R.color.tab_un_select_text_color)); itemBinding.tabTitle.setBackground(null); } @Override public void onTabReselected(TabLayout.Tab tab) { } }); for (int i = 0; i < tabTitle.length; i++) { TabLayout.Tab tab = binding.tabLayout.newTab(); ItemTabImageRecoverBinding tabLayoutBinding = ItemTabImageRecoverBinding.inflate(getLayoutInflater()); int finalI = i; tabLayoutBinding.getRoot().setOnClickListener(v -> { switch (finalI) { case 0: gridLayoutManager.scrollToPositionWithOffset(getPhotoPosition(), 0); break; case 1: gridLayoutManager.scrollToPositionWithOffset(getWxPosition(), 0); break; case 2: gridLayoutManager.scrollToPositionWithOffset(getQQPosition(), 0); break; case 3: gridLayoutManager.scrollToPositionWithOffset(getOtherPosition(), 0); break; } binding.tabLayout.selectTab(binding.tabLayout.getTabAt(finalI)); }); tabLayoutBinding.tabTitle.setText(tabTitle[i]); tab.setCustomView(tabLayoutBinding.getRoot()); binding.tabLayout.addTab(tab); } } @SuppressLint("NotifyDataSetChanged") private void initObserver() { imageRecoverViewModel.getScrollTop().observe(this, o -> binding.ryImageRecover.scrollToPosition(0)); imageRecoverViewModel.getShowTrialFinishDialog().observe(this, o -> showTrialFinishDialog()); imageRecoverViewModel.getShowTrialExportFailDialog().observe(this, o -> showTrialExportFailDialog()); imageRecoverViewModel.getDeleteUriListSdk11().observe(this, list -> { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { PendingIntent pi = MediaStore.createDeleteRequest(getBaseContext().getContentResolver(), list); IntentSenderRequest request = new IntentSenderRequest.Builder(pi.getIntentSender()).build(); new ActivityForResultUtil().startActivityForResult(this, new ActivityResultContracts.StartIntentSenderForResult(), request, result -> { imageRecoverViewModel.callDealComplete(result.getResultCode() == Activity.RESULT_OK); }); } }); imageRecoverViewModel.getNotifyList().observe(this, o -> { photoAdapter.notifyDataSetChanged(); wxAdapter.notifyDataSetChanged(); qqAdapter.notifyDataSetChanged(); otherAdapter.notifyDataSetChanged(); }); imageRecoverViewModel.getShowScanDialogEvent().observe(this, this::showScanProgressDialog); imageRecoverViewModel.getDetectedPhotoImg().observe(this, list -> photoAdapter.submit(list)); imageRecoverViewModel.getDetectedWxImg().observe(this, list -> wxAdapter.submit(list)); imageRecoverViewModel.getDetectedQQImg().observe(this, list -> qqAdapter.submit(list)); imageRecoverViewModel.getDetectedOtherImg().observe(this, list -> otherAdapter.submit(list)); imageRecoverViewModel.getPreviewEvent().observe(this, pair -> PreviewActivity.startImagePreView(this, pair.first, pair.second, imageRecoverViewModel.isTrial())); imageRecoverViewModel.getShowLoadingEvent().observe(this, this::showLoadingDialog); imageRecoverViewModel.getShowClearDialog().observe(this, o -> showClearDialog()); } private void showTrialExportFailDialog() { if (showTrialExportFailDialog == null) { showTrialExportFailDialog = new CommonSureDialog(this); showTrialExportFailDialog.setDialogTitle(R.string.trial_export_fail_title) .setDialogContent(R.string.trial_export_fail_content).setSureText(R.string.dialog_trial_recover); showTrialExportFailDialog.setOnDialogClickListener(() -> { imageRecoverViewModel.onTrialRecoverClick(); EventHelper.report(EventId.hf1001123, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER))); }); showTrialExportFailDialog.setOnDismissListener(dialog -> EventHelper.report(EventId.hf1001124, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER)))); } if (!showTrialExportFailDialog.isShowing()) { showTrialExportFailDialog.show(); EventHelper.report(EventId.hf1001120, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER))); } } private void showTrialFinishDialog() { if (showTrialFinishDialog == null) { showTrialFinishDialog = new CommonSureDialog(this); showTrialFinishDialog.setDialogTitle(getString(R.string.scanning_progress, 13)) .setDialogContent(getString(R.string.trial_scanning_finish_content, 13)).setSureText(R.string.dialog_trial_recover); showTrialFinishDialog.setOnDialogClickListener(() -> { imageRecoverViewModel.onTrialRecoverClick(); EventHelper.report(EventId.hf1001121, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER))); }); showTrialFinishDialog.setOnDismissListener(dialog -> EventHelper.report(EventId.hf1001122, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER)))); } if (!showTrialFinishDialog.isShowing()) { showTrialFinishDialog.show(); EventHelper.report(EventId.hf1001118, Maps.asMap(EventId.EVENT_ID, ReportUtil.getReportId(MemberType.APP_IMAGE_RECOVER))); } } private void showClearDialog() { if (clearDialog == null) { clearDialog = new CommonSureDialog(this); clearDialog.setDialogTitle(R.string.img_clear_sure_title).setDialogContent(R.string.img_clear_sure_content); clearDialog.setOnDialogClickListener(() -> imageRecoverViewModel.executeImageDelete()); } clearDialog.show(); } private void showBackDialog() { if (backDialog == null) { backDialog = new CommonSureDialog(this); backDialog.setDialogTitle(R.string.img_recovery_back_title) .setDialogContent(R.string.img_recovery_back_content) .setOnDialogClickListener(this::finish); } backDialog.show(); } @Override protected void configImmersion(@NonNull ImmersionBar immersionBar) { immersionBar.statusBarDarkFont(true); } public void showScanProgressDialog(Boolean show) { if (BoxingUtil.boxing(show)) { if (scanFileDialog == null) { scanFileDialog = new ScanFileDialog(this, imageRecoverViewModel.getDetectedLastFileName()); scanFileDialog.setOnCancelListener(() -> imageRecoverViewModel.cancelScan()); } scanFileDialog.show(); } else { if (scanFileDialog != null) { scanFileDialog.dismiss(); } } } public void showLoadingDialog(Boolean show) { if (BoxingUtil.boxing(show)) { if (loadingDialog == null) { loadingDialog = new CommonLoadingDialog(this); loadingDialog.setMessage(Objects.equals(imageRecoverViewModel.getType(), MemberType.APP_IMAGE_CLEAN) ? R.string.deleting : R.string.exporting); } loadingDialog.show(); } else { if (loadingDialog != null) { loadingDialog.dismiss(); } } } @Override public void onBackPressed() { showBackDialog(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { onBackPressed(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onDestroy() { super.onDestroy(); binding.tabLayout.clearOnTabSelectedListeners(); } @Override protected boolean shouldImmersion() { return true; } @Override protected void initViewModel() { super.initViewModel(); imageRecoverViewModel = getViewModelProvider().get(ImageRecoverViewModel.class); binding.setImageRecoverViewModel(imageRecoverViewModel); } }