Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/0971 implement trash bin #3976

Merged
merged 9 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ dependencies {
runtimeOnly "com.github.tony19:logback-android:$logbackAndroidVersion"

implementation 'com.google.code.gson:gson:2.9.1'

implementation 'com.github.TeamAmaze:AmazeTrashBin:1.0.10'
}

kotlin {
Expand Down
4 changes: 3 additions & 1 deletion app/proguard.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,6 @@
#Keep constructors that involves an InputStream
-keepclassmembers class * extends org.apache.commons.compress.compressors.CompressorInputStream {
<init>(java.io.InputStream);
}
}

-keep class com.amaze.trashbin.** { *; }
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ class AppsRecyclerAdapter(
} else {
files.add(f1)
}
DeleteTask(fragment.requireContext()).execute(files)
DeleteTask(fragment.requireContext(), false).execute(files)
}
.build()
.show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class HiddenAdapter(
nomediaFile.mode = OpenMode.FILE
val filesToDelete = ArrayList<HybridFileParcelable>()
filesToDelete.add(nomediaFile)
val task = DeleteTask(context)
val task = DeleteTask(context, false)
task.execute(filesToDelete)
}
DataUtils.getInstance().removeHiddenFile(hiddenFiles[position].path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,21 @@ private void showPopup(@NonNull View view, @NonNull final LayoutElementParcelabl
popupMenu.getMenu().findItem(R.id.encrypt).setVisible(true);
}
}
if (rowItem.getMode() == OpenMode.TRASH_BIN) {
popupMenu.getMenu().findItem(R.id.return_select).setVisible(false);
popupMenu.getMenu().findItem(R.id.cut).setVisible(false);
popupMenu.getMenu().findItem(R.id.cpy).setVisible(false);
popupMenu.getMenu().findItem(R.id.rename).setVisible(false);
popupMenu.getMenu().findItem(R.id.encrypt).setVisible(false);
popupMenu.getMenu().findItem(R.id.decrypt).setVisible(false);
popupMenu.getMenu().findItem(R.id.about).setVisible(false);
popupMenu.getMenu().findItem(R.id.compress).setVisible(false);
popupMenu.getMenu().findItem(R.id.share).setVisible(false);
popupMenu.getMenu().findItem(R.id.ex).setVisible(false);
popupMenu.getMenu().findItem(R.id.book).setVisible(false);
popupMenu.getMenu().findItem(R.id.restore).setVisible(true);
popupMenu.getMenu().findItem(R.id.delete).setVisible(true);
}

popupMenu.show();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ public class LayoutElementParcelable implements Parcelable {
public final String desc;
public final String permissions;
public final String symlink;
public final String size;
public final boolean isDirectory;
public final long date, longSize;
public final String dateModification;
public String size;
public boolean isDirectory;
public long date, longSize;
public String dateModification;
public final boolean header;

// same as hfile.modes but different than openmode in Main.java
Expand Down
67 changes: 67 additions & 0 deletions app/src/main/java/com/amaze/filemanager/application/AppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package com.amaze.filemanager.application;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.concurrent.Callable;

Expand All @@ -39,25 +40,35 @@
import com.amaze.filemanager.database.ExplorerDatabase;
import com.amaze.filemanager.database.UtilitiesDatabase;
import com.amaze.filemanager.database.UtilsHandler;
import com.amaze.filemanager.fileoperations.exceptions.ShellNotRunningException;
import com.amaze.filemanager.fileoperations.filesystem.OpenMode;
import com.amaze.filemanager.filesystem.HybridFile;
import com.amaze.filemanager.filesystem.ssh.CustomSshJConfig;
import com.amaze.filemanager.ui.fragments.preferencefragments.PreferencesConstants;
import com.amaze.filemanager.ui.provider.UtilitiesProvider;
import com.amaze.filemanager.utils.ScreenUtils;
import com.amaze.trashbin.TrashBin;
import com.amaze.trashbin.TrashBinConfig;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.os.StrictMode;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.PreferenceManager;

import io.reactivex.Completable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import jcifs.Config;
import jcifs.smb.SmbException;

@AcraCore(
buildConfigClass = BuildConfig.class,
Expand All @@ -78,6 +89,11 @@ public class AppConfig extends GlideApplication {

private ExplorerDatabase explorerDatabase;

private TrashBinConfig trashBinConfig;
private TrashBin trashBin;
private static final String TRASH_BIN_BASE_PATH =
Environment.getExternalStorageDirectory().getPath() + File.separator + ".AmazeData";

public UtilitiesProvider getUtilsProvider() {
return utilsProvider;
}
Expand Down Expand Up @@ -253,4 +269,55 @@ protected void initACRA() {
R.string.app_ui_crash));
}
}

public TrashBin getTrashBinInstance() {
if (trashBin == null) {
trashBin =
new TrashBin(
getApplicationContext(),
true,
getTrashBinConfig(),
s -> {
runInBackground(
() -> {
HybridFile file = new HybridFile(OpenMode.TRASH_BIN, s);
try {
file.delete(getMainActivityContext(), false);
} catch (ShellNotRunningException | SmbException e) {
log.warn("failed to delete file in trash bin cleanup", e);
}
});
return true;
},
null);
}
return trashBin;
}

private TrashBinConfig getTrashBinConfig() {
if (trashBinConfig == null) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);

int days =
sharedPrefs.getInt(
PreferencesConstants.KEY_TRASH_BIN_RETENTION_DAYS,
TrashBinConfig.RETENTION_DAYS_INFINITE);
long bytes =
sharedPrefs.getLong(
PreferencesConstants.KEY_TRASH_BIN_RETENTION_BYTES,
TrashBinConfig.RETENTION_BYTES_INFINITE);
int numOfFiles =
sharedPrefs.getInt(
PreferencesConstants.KEY_TRASH_BIN_RETENTION_NUM_OF_FILES,
TrashBinConfig.RETENTION_NUM_OF_FILES);
int intervalHours =
sharedPrefs.getInt(
PreferencesConstants.KEY_TRASH_BIN_CLEANUP_INTERVAL_HOURS,
TrashBinConfig.INTERVAL_CLEANUP_HOURS);
trashBinConfig =
new TrashBinConfig(
TRASH_BIN_BASE_PATH, days, bytes, numOfFiles, intervalHours, false, true);
}
return trashBinConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,13 @@ public class DeleteTask
private final Context applicationContext;
private final boolean rootMode;
private CompressedExplorerFragment compressedExplorerFragment;

private boolean doDeletePermanently;
private final DataUtils dataUtils = DataUtils.getInstance();

public DeleteTask(@NonNull Context applicationContext) {
public DeleteTask(@NonNull Context applicationContext, @NonNull boolean doDeletePermanently) {
this.applicationContext = applicationContext.getApplicationContext();
this.doDeletePermanently = doDeletePermanently;
rootMode =
PreferenceManager.getDefaultSharedPreferences(applicationContext)
.getBoolean(PreferencesConstants.PREFERENCE_ROOTMODE, false);
Expand All @@ -80,6 +83,7 @@ public DeleteTask(@NonNull Context applicationContext) {
public DeleteTask(
@NonNull Context applicationContext, CompressedExplorerFragment compressedExplorerFragment) {
this.applicationContext = applicationContext.getApplicationContext();
this.doDeletePermanently = false;
rootMode =
PreferenceManager.getDefaultSharedPreferences(applicationContext)
.getBoolean(PreferencesConstants.PREFERENCE_ROOTMODE, false);
Expand Down Expand Up @@ -109,7 +113,7 @@ protected final AsyncTaskResult<Boolean> doInBackground(
}

// delete file from media database
if (!file.isSmb())
if (!file.isSmb() && !file.isSftp())
MediaConnectionUtils.scanFile(
applicationContext, files.toArray(new HybridFile[files.size()]));

Expand Down Expand Up @@ -180,7 +184,15 @@ private boolean doDeleteFile(@NonNull HybridFileParcelable file) throws Exceptio
}
default:
try {
return (file.delete(applicationContext, rootMode));
/* SMB and SFTP (or any remote files that may support in the future) should not be
* supported by recycle bin. - TranceLove
*/
if (!doDeletePermanently
&& !OpenMode.SMB.equals(file.getMode())
&& !OpenMode.SFTP.equals(file.getMode())) {
return file.moveToBin(applicationContext);
}
return file.delete(applicationContext, rootMode);
} catch (ShellNotRunningException | SmbException e) {
LOG.warn("failed to delete files", e);
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
import com.amaze.filemanager.utils.OTGUtil;
import com.amaze.filemanager.utils.OnAsyncTaskFinished;
import com.amaze.filemanager.utils.OnFileFound;
import com.amaze.filemanager.utils.Utils;
import com.amaze.trashbin.TrashBin;
import com.amaze.trashbin.TrashBinFile;
import com.cloudrail.si.interfaces.CloudStorage;

import android.content.ContentResolver;
Expand Down Expand Up @@ -135,7 +138,9 @@ public LoadFilesListTask(
MainFragmentViewModel mainFragmentViewModel = mainFragment.getMainFragmentViewModel();
MainActivityViewModel mainActivityViewModel = mainFragment.getMainActivityViewModel();

if (OpenMode.UNKNOWN.equals(openmode) || OpenMode.CUSTOM.equals(openmode)) {
if (OpenMode.UNKNOWN.equals(openmode)
|| OpenMode.CUSTOM.equals(openmode)
|| OpenMode.TRASH_BIN.equals(openmode)) {
hFile = new HybridFile(openmode, path);
hFile.generateMode(mainFragment.getActivity());
openmode = hFile.getMode();
Expand All @@ -159,6 +164,7 @@ public LoadFilesListTask(
list = listSftp(mainActivityViewModel);
break;
case CUSTOM:
case TRASH_BIN:
list = getCachedMediaList(mainActivityViewModel);
break;
case OTG:
Expand Down Expand Up @@ -191,7 +197,8 @@ public LoadFilesListTask(
}

if (list != null
&& !(openmode == OpenMode.CUSTOM && ((path).equals("5") || (path).equals("6")))) {
&& !(openmode == OpenMode.CUSTOM
&& (("5").equals(path) || ("6").equals(path) || ("7").equals(path)))) {
postListCustomPathProcess(list, mainFragment);
}

Expand All @@ -214,6 +221,7 @@ private List<LayoutElementParcelable> getCachedMediaList(
int mediaType = Integer.parseInt(path);
if (5 == mediaType
|| 6 == mediaType
|| 7 == mediaType
|| mainActivityViewModel.getMediaCacheHash().get(mediaType) == null
|| forceReload) {
switch (Integer.parseInt(path)) {
Expand All @@ -238,10 +246,13 @@ private List<LayoutElementParcelable> getCachedMediaList(
case 6:
list = listRecentFiles();
break;
case 7:
list = listTrashBinFiles();
break;
default:
throw new IllegalStateException();
}
if (5 != mediaType && 6 != mediaType) {
if (5 != mediaType && 6 != mediaType && 7 != mediaType) {
// not saving recent files in cache
mainActivityViewModel.getMediaCacheHash().set(mediaType, list);
}
Expand Down Expand Up @@ -556,6 +567,40 @@ else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
return recentFiles;
}

private @Nullable List<LayoutElementParcelable> listTrashBinFiles() {
final Context context = this.context.get();

if (context == null) {
cancel(true);
return null;
}

TrashBin trashBin = AppConfig.getInstance().getTrashBinInstance();
List<LayoutElementParcelable> deletedFiles = new ArrayList<>();
if (trashBin != null) {
for (TrashBinFile trashBinFile : trashBin.listFilesInBin()) {
HybridFile hybridFile =
new HybridFile(
OpenMode.TRASH_BIN,
trashBinFile.getDeletedPath(
AppConfig.getInstance().getTrashBinInstance().getConfig()),
trashBinFile.getFileName(),
trashBinFile.isDirectory());
if (trashBinFile.getDeleteTime() != null) {
hybridFile.setLastModified(trashBinFile.getDeleteTime() * 1000);
}
LayoutElementParcelable element = hybridFile.generateLayoutElement(context, true);
element.date = trashBinFile.getDeleteTime();
element.longSize = trashBinFile.getSizeBytes();
element.size = Formatter.formatFileSize(context, trashBinFile.getSizeBytes());
element.dateModification = Utils.getDate(context, trashBinFile.getDeleteTime() * 1000);
element.isDirectory = trashBinFile.isDirectory();
deletedFiles.add(element);
}
}
return deletedFiles;
}

private @NonNull List<LayoutElementParcelable> listAppDataDirectories(@NonNull String basePath) {
if (!GenericExtKt.containsPath(FileProperties.ANDROID_DEVICE_DATA_DIRS, basePath)) {
throw new IllegalArgumentException("Invalid base path: [" + basePath + "]");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ public void execute(
for (HybridFileParcelable a : sourceFiles) {
if (!failedFOps.contains(a)) toDelete.add(a);
}
new DeleteTask(c).execute((toDelete));
new DeleteTask(c, true).execute((toDelete));
}
}

Expand Down
Loading
Loading