diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 8420e343b..aaf7826ef 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; +import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -35,6 +36,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.Adapter; import androidx.recyclerview.widget.RecyclerView.ViewHolder; +import com.google.android.material.snackbar.Snackbar; + import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.NewPipe; @@ -46,6 +49,7 @@ import java.io.File; import java.lang.ref.WeakReference; import java.net.URI; import java.util.ArrayList; +import java.util.Iterator; import us.shandian.giga.get.DownloadMission; import us.shandian.giga.get.FinishedMission; @@ -104,8 +108,12 @@ public class MissionAdapter extends Adapter implements Handler.Callb private MenuItem mPauseButton; private View mEmptyMessage; private RecoverHelper mRecover; + private View mView; + private ArrayList mHidden; + private Snackbar mSnackbar; private final Runnable rUpdater = this::updater; + private final Runnable rDelete = this::deleteFinishedDownloads; public MissionAdapter(Context context, @NonNull DownloadManager downloadManager, View emptyMessage, View root) { mContext = context; @@ -122,6 +130,10 @@ public class MissionAdapter extends Adapter implements Handler.Callb mDeleter = new Deleter(root, mContext, this, mDownloadManager, mIterator, mHandler); + mView = root; + + mHidden = new ArrayList<>(); + checkEmptyMessageVisibility(); onResume(); } @@ -557,9 +569,50 @@ public class MissionAdapter extends Adapter implements Handler.Callb ); } - public void clearFinishedDownloads() { - mDownloadManager.forgetFinishedDownloads(); - applyChanges(); + public void clearFinishedDownloads(boolean delete) { + if (delete && mIterator.hasFinishedMissions() && mHidden.isEmpty()) { + for (int i = 0; i < mIterator.getOldListSize(); i++) { + FinishedMission mission = mIterator.getItem(i).mission instanceof FinishedMission ? (FinishedMission) mIterator.getItem(i).mission : null; + if (mission != null) { + mIterator.hide(mission); + mHidden.add(mission); + } + } + applyChanges(); + + String msg = String.format(mContext.getString(R.string.deleted_downloads), mHidden.size()); + mSnackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE); + mSnackbar.setAction(R.string.undo, s -> { + Iterator i = mHidden.iterator(); + while (i.hasNext()) { + mIterator.unHide(i.next()); + i.remove(); + } + applyChanges(); + mHandler.removeCallbacks(rDelete); + }); + mSnackbar.setActionTextColor(Color.YELLOW); + mSnackbar.show(); + + mHandler.postDelayed(rDelete, 5000); + } else if (!delete) { + mDownloadManager.forgetFinishedDownloads(); + applyChanges(); + } + } + + private void deleteFinishedDownloads() { + if (mSnackbar != null) mSnackbar.dismiss(); + + Iterator i = mHidden.iterator(); + while (i.hasNext()) { + Mission mission = i.next(); + if (mission != null) { + mDownloadManager.deleteMission(mission); + mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri())); + } + i.remove(); + } } private boolean handlePopupItem(@NonNull ViewHolderItem h, @NonNull MenuItem option) { diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 921eaff5c..be0b0bb25 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -17,6 +17,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.CheckBox; import android.widget.Toast; import androidx.annotation.NonNull; @@ -189,10 +190,12 @@ public class MissionsFragment extends Fragment { return true; case R.id.clear_list: AlertDialog.Builder prompt = new AlertDialog.Builder(mContext); - prompt.setTitle(R.string.clear_finished_download); + prompt.setTitle(R.string.clear_download_history); prompt.setMessage(R.string.confirm_prompt); - prompt.setPositiveButton(android.R.string.ok, (dialog, which) -> mAdapter.clearFinishedDownloads()); - prompt.setNegativeButton(R.string.cancel, null); + // Intentionally misusing button's purpose in order to achieve good order + prompt.setNegativeButton(R.string.clear_download_history, (dialog, which) -> mAdapter.clearFinishedDownloads(false)); + prompt.setPositiveButton(R.string.delete_downloaded_files, (dialog, which) -> mAdapter.clearFinishedDownloads(true)); + prompt.setNeutralButton(R.string.cancel, null); prompt.create().show(); return true; case R.id.start_downloads: diff --git a/app/src/main/res/menu/download_menu.xml b/app/src/main/res/menu/download_menu.xml index f91f8ad7b..8728e146e 100644 --- a/app/src/main/res/menu/download_menu.xml +++ b/app/src/main/res/menu/download_menu.xml @@ -24,7 +24,7 @@ Progress lost, because the file was deleted Connection timeout Cannot recover this download - Clear finished downloads - Are you sure? + Clear download history + Do you want to clear your download history or delete all downloaded files? + Delete downloaded files + Deleted %1$s downloads Stop Maximum retries Maximum number of attempts before canceling the download @@ -587,5 +589,4 @@ Use SAF The Storage Access Framework allows downloads to an external SD card.\nNote: some devices are not compatible Choose an instance -