ImageRecoverActivity.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package com.datarecovery.master.module.imgrecover;
  2. import android.annotation.SuppressLint;
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.os.Bundle;
  7. import android.view.KeyEvent;
  8. import androidx.annotation.NonNull;
  9. import androidx.annotation.Nullable;
  10. import androidx.recyclerview.widget.ConcatAdapter;
  11. import androidx.recyclerview.widget.GridLayoutManager;
  12. import androidx.recyclerview.widget.RecyclerView;
  13. import com.atmob.app.lib.base.BaseActivity;
  14. import com.datarecovery.master.R;
  15. import com.datarecovery.master.databinding.ActivityImageRecoverBinding;
  16. import com.datarecovery.master.databinding.ItemTabImageRecoverBinding;
  17. import com.datarecovery.master.dialog.CommonLoadingDialog;
  18. import com.datarecovery.master.dialog.CommonSureDialog;
  19. import com.datarecovery.master.dialog.ScanProgressDialog;
  20. import com.datarecovery.master.module.member.MemberType;
  21. import com.datarecovery.master.module.preview.PreviewActivity;
  22. import com.datarecovery.master.utils.BoxingUtil;
  23. import com.datarecovery.master.utils.FilePermissionHelper;
  24. import com.datarecovery.master.utils.GridRecoverItemDecoration;
  25. import com.datarecovery.master.utils.ImageDeepDetector;
  26. import com.google.android.material.tabs.TabLayout;
  27. import com.gyf.immersionbar.ImmersionBar;
  28. import java.util.List;
  29. import java.util.Objects;
  30. import dagger.hilt.android.AndroidEntryPoint;
  31. @AndroidEntryPoint
  32. public class ImageRecoverActivity extends BaseActivity<ActivityImageRecoverBinding> implements ImageItemAdapter.onItemClick {
  33. private ConcatAdapter concatAdapter;
  34. private static final String TYPE = "type";
  35. ImageRecoverViewModel imageRecoverViewModel;
  36. private final int[] tabTitle = {R.string.photo, R.string.wx, R.string.qq, R.string.other};
  37. private CommonSureDialog backDialog;
  38. private CommonSureDialog clearDialog;
  39. private CommonLoadingDialog loadingDialog;
  40. private ScanProgressDialog scanProgressDialog;
  41. private ImageItemAdapter photoAdapter;
  42. private ImageItemAdapter wxAdapter;
  43. private ImageItemAdapter qqAdapter;
  44. private ImageItemAdapter otherAdapter;
  45. private GridLayoutManager gridLayoutManager;
  46. public static void start(Context context, @MemberType String type) {
  47. Intent intent = new Intent(context, ImageRecoverActivity.class);
  48. if (!(context instanceof Activity)) {
  49. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  50. }
  51. intent.putExtra(TYPE, type);
  52. context.startActivity(intent);
  53. }
  54. @Override
  55. protected void onCreate(@Nullable Bundle savedInstanceState) {
  56. super.onCreate(savedInstanceState);
  57. initData();
  58. initView();
  59. initObserver();
  60. initPermission();
  61. }
  62. private void initPermission() {
  63. new FilePermissionHelper().requestDataFilePermission(this, imageRecoverViewModel.getType(), new FilePermissionHelper.NextStepCallback() {
  64. @Override
  65. public void onNextStep() {
  66. imageRecoverViewModel.startImageScanning();
  67. }
  68. @Override
  69. public void onCancel() {
  70. finish();
  71. }
  72. });
  73. }
  74. private void initData() {
  75. Intent intent = getIntent();
  76. if (intent != null) {
  77. imageRecoverViewModel.setType(intent.getStringExtra(TYPE));
  78. }
  79. }
  80. private void initView() {
  81. binding.toolBar.setNavigationOnClickListener(v -> onBackPressed());
  82. addTopStatusBarHeight(binding.toolBar);
  83. initRecycleView();
  84. initTabLayout();
  85. }
  86. private void initRecycleView() {
  87. ImageTitleAdapter photoTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedPhotoTitle());
  88. photoAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_GALLERY, this);
  89. photoAdapter.setOnItemClick(this);
  90. ImageTitleAdapter wxTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedWxTitle());
  91. wxAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_WECHAT, this);
  92. wxAdapter.setOnItemClick(this);
  93. ImageTitleAdapter qqTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedQQTitle());
  94. qqAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_QQ, this);
  95. qqAdapter.setOnItemClick(this);
  96. ImageTitleAdapter otherTitleAdapter = new ImageTitleAdapter(this, imageRecoverViewModel.getDetectedOtherTitle());
  97. otherAdapter = new ImageItemAdapter(ImageDeepDetector.ImageFile.CATEGORY_OTHER, this);
  98. otherAdapter.setOnItemClick(this);
  99. concatAdapter = new ConcatAdapter(
  100. photoTitleAdapter,
  101. photoAdapter,
  102. wxTitleAdapter,
  103. wxAdapter,
  104. qqTitleAdapter,
  105. qqAdapter,
  106. otherTitleAdapter,
  107. otherAdapter
  108. );
  109. binding.ryImageRecover.setAdapter(concatAdapter);
  110. gridLayoutManager = new GridLayoutManager(this, 3);
  111. gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
  112. @Override
  113. public int getSpanSize(int position) {
  114. if (position == getPhotoPosition() || position == getWxPosition() || position == getQQPosition() || position == getOtherPosition()) {
  115. return 3;
  116. }
  117. return 1;
  118. }
  119. });
  120. binding.ryImageRecover.addItemDecoration(new GridRecoverItemDecoration(3, 0.0282222222222222f, 0.0202222222222222f));
  121. binding.ryImageRecover.setLayoutManager(gridLayoutManager);
  122. RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
  123. @Override
  124. public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
  125. int firstVisibleItem = gridLayoutManager.findFirstVisibleItemPosition();
  126. int lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition();
  127. int photoPosition = getPhotoPosition();
  128. int wxPosition = getWxPosition();
  129. int qqPosition = getQQPosition();
  130. int otherPosition = getOtherPosition();
  131. if (firstVisibleItem == photoPosition || (firstVisibleItem >= photoPosition && lastVisibleItem < wxPosition)) {
  132. binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0));
  133. } else if (firstVisibleItem == wxPosition || (firstVisibleItem >= wxPosition && lastVisibleItem < qqPosition)) {
  134. binding.tabLayout.selectTab(binding.tabLayout.getTabAt(1));
  135. } else if (firstVisibleItem == qqPosition || (firstVisibleItem >= qqPosition && lastVisibleItem < otherPosition)) {
  136. binding.tabLayout.selectTab(binding.tabLayout.getTabAt(2));
  137. } else if (firstVisibleItem >= otherPosition) {
  138. binding.tabLayout.selectTab(binding.tabLayout.getTabAt(3));
  139. }
  140. }
  141. };
  142. binding.ryImageRecover.addOnScrollListener(onScrollListener);
  143. }
  144. public int getPhotoPosition() {
  145. return 0;
  146. }
  147. public int getWxPosition() {
  148. return getPhotoPosition() + photoAdapter.getItemCount() + 1;
  149. }
  150. public int getQQPosition() {
  151. return getWxPosition() + wxAdapter.getItemCount() + 1;
  152. }
  153. public int getOtherPosition() {
  154. return getQQPosition() + qqAdapter.getItemCount() + 1;
  155. }
  156. @Override
  157. public void onCheck(ImageDeepDetector.ImageFile imageFile) {
  158. if (imageFile == null) {
  159. return;
  160. }
  161. imageRecoverViewModel.setItemCheck(imageFile);
  162. }
  163. @Override
  164. public void onItemClick(ImageDeepDetector.ImageFile imageFile) {
  165. if (imageFile == null) {
  166. return;
  167. }
  168. if (Objects.equals(imageRecoverViewModel.getType(), MemberType.APP_IMAGE_CLEAN)) {
  169. imageRecoverViewModel.setItemCheck(imageFile);
  170. } else {
  171. imageRecoverViewModel.checkPreview(imageFile);
  172. }
  173. }
  174. private void initTabLayout() {
  175. binding.tabLayout.removeAllTabs();
  176. binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
  177. @SuppressLint("UseCompatLoadingForDrawables")
  178. @Override
  179. public void onTabSelected(TabLayout.Tab tab) {
  180. if (tab.getCustomView() == null) {
  181. return;
  182. }
  183. ItemTabImageRecoverBinding itemBinding = ItemTabImageRecoverBinding.bind(tab.getCustomView());
  184. itemBinding.tabTitle.setTextColor(getResources().getColor(com.atmob.app.base.R.color.white));
  185. itemBinding.tabTitle.setBackground(getResources().getDrawable(R.drawable.bg_tab_selected));
  186. }
  187. @Override
  188. public void onTabUnselected(TabLayout.Tab tab) {
  189. if (tab.getCustomView() == null) {
  190. return;
  191. }
  192. ItemTabImageRecoverBinding itemBinding = ItemTabImageRecoverBinding.bind(tab.getCustomView());
  193. itemBinding.tabTitle.setTextColor(getResources().getColor(R.color.tab_un_select_text_color));
  194. itemBinding.tabTitle.setBackground(null);
  195. }
  196. @Override
  197. public void onTabReselected(TabLayout.Tab tab) {
  198. }
  199. });
  200. for (int i = 0; i < tabTitle.length; i++) {
  201. TabLayout.Tab tab = binding.tabLayout.newTab();
  202. ItemTabImageRecoverBinding tabLayoutBinding = ItemTabImageRecoverBinding.inflate(getLayoutInflater());
  203. int finalI = i;
  204. tabLayoutBinding.getRoot().setOnClickListener(v -> {
  205. switch (finalI) {
  206. case 0:
  207. gridLayoutManager.scrollToPositionWithOffset(getPhotoPosition(), 0);
  208. break;
  209. case 1:
  210. gridLayoutManager.scrollToPositionWithOffset(getWxPosition(), 0);
  211. break;
  212. case 2:
  213. gridLayoutManager.scrollToPositionWithOffset(getQQPosition(), 0);
  214. break;
  215. case 3:
  216. gridLayoutManager.scrollToPositionWithOffset(getOtherPosition(), 0);
  217. break;
  218. }
  219. binding.tabLayout.selectTab(binding.tabLayout.getTabAt(finalI));
  220. });
  221. tabLayoutBinding.tabTitle.setText(tabTitle[i]);
  222. tab.setCustomView(tabLayoutBinding.getRoot());
  223. binding.tabLayout.addTab(tab);
  224. }
  225. }
  226. @SuppressLint("NotifyDataSetChanged")
  227. private void initObserver() {
  228. imageRecoverViewModel.getNotifyList().observe(this, o -> {
  229. photoAdapter.notifyDataSetChanged();
  230. wxAdapter.notifyDataSetChanged();
  231. qqAdapter.notifyDataSetChanged();
  232. otherAdapter.notifyDataSetChanged();
  233. });
  234. imageRecoverViewModel.getShowScanDialogEvent().observe(this, this::showScanProgressDialog);
  235. imageRecoverViewModel.getDetectedPhotoImg().observe(this, list -> photoAdapter.submit(list));
  236. imageRecoverViewModel.getDetectedWxImg().observe(this, list -> wxAdapter.submit(list));
  237. imageRecoverViewModel.getDetectedQQImg().observe(this, list -> qqAdapter.submit(list));
  238. imageRecoverViewModel.getDetectedOtherImg().observe(this, list -> otherAdapter.submit(list));
  239. imageRecoverViewModel.getDetectedFinish().observe(this, o -> scanProgressDialog.detectedFinish());
  240. imageRecoverViewModel.getPreviewEvent().observe(this, imageFile -> {
  241. List<ImageDeepDetector.ImageFile> allDetectedList = imageRecoverViewModel.getAllDetectedList();
  242. int position = imageRecoverViewModel.getPosition(allDetectedList, imageFile);
  243. PreviewActivity.startImagePreView(this, allDetectedList, position);
  244. });
  245. imageRecoverViewModel.getShowLoadingEvent().observe(this, this::showLoadingDialog);
  246. imageRecoverViewModel.getShowClearDialog().observe(this, o -> showClearDialog());
  247. }
  248. private void showClearDialog() {
  249. if (clearDialog == null) {
  250. clearDialog = new CommonSureDialog(this);
  251. clearDialog.setDialogTitle(R.string.img_clear_sure_title).setDialogContent(R.string.img_clear_sure_content);
  252. clearDialog.setOnDialogClickListener(() -> imageRecoverViewModel.executeImageDelete());
  253. }
  254. clearDialog.show();
  255. }
  256. private void showBackDialog() {
  257. if (backDialog == null) {
  258. backDialog = new CommonSureDialog(this);
  259. backDialog.setDialogTitle(R.string.img_recovery_back_title)
  260. .setDialogContent(R.string.img_recovery_back_content)
  261. .setOnDialogClickListener(this::finish);
  262. }
  263. backDialog.show();
  264. }
  265. @Override
  266. protected void configImmersion(@NonNull ImmersionBar immersionBar) {
  267. immersionBar.statusBarDarkFont(true);
  268. }
  269. public void showScanProgressDialog(Boolean show) {
  270. if (BoxingUtil.boxing(show)) {
  271. if (scanProgressDialog == null) {
  272. scanProgressDialog = new ScanProgressDialog(this, imageRecoverViewModel.getTotalDetectedCount());
  273. scanProgressDialog.setOnCancelListener(() -> imageRecoverViewModel.cancelScan());
  274. }
  275. scanProgressDialog.show();
  276. } else {
  277. if (scanProgressDialog != null) {
  278. scanProgressDialog.dismiss();
  279. }
  280. }
  281. }
  282. public void showLoadingDialog(Boolean show) {
  283. if (BoxingUtil.boxing(show)) {
  284. if (loadingDialog == null) {
  285. loadingDialog = new CommonLoadingDialog(this);
  286. loadingDialog.setMessage(Objects.equals(imageRecoverViewModel.getType(), MemberType.APP_IMAGE_CLEAN) ? R.string.deleting : R.string.exporting);
  287. }
  288. loadingDialog.show();
  289. } else {
  290. if (loadingDialog != null) {
  291. loadingDialog.dismiss();
  292. }
  293. }
  294. }
  295. @Override
  296. public void onBackPressed() {
  297. showBackDialog();
  298. }
  299. @Override
  300. public boolean onKeyDown(int keyCode, KeyEvent event) {
  301. if (keyCode == KeyEvent.KEYCODE_BACK) {
  302. onBackPressed();
  303. return true;
  304. }
  305. return super.onKeyDown(keyCode, event);
  306. }
  307. @Override
  308. protected void onDestroy() {
  309. super.onDestroy();
  310. binding.tabLayout.clearOnTabSelectedListeners();
  311. }
  312. @Override
  313. protected boolean shouldImmersion() {
  314. return true;
  315. }
  316. @Override
  317. protected void initViewModel() {
  318. super.initViewModel();
  319. imageRecoverViewModel = getViewModelProvider().get(ImageRecoverViewModel.class);
  320. binding.setImageRecoverViewModel(imageRecoverViewModel);
  321. }
  322. }