Skip to content

Commit

Permalink
Merge pull request #58 from Arctosoft/develop
Browse files Browse the repository at this point in the history
Version 1.8.0
  • Loading branch information
hej2010 authored Mar 30, 2024
2 parents 2134367 + d36de38 commit 9be1676
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 102 deletions.
9 changes: 4 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "se.arctosoft.vault"
minSdk 28
targetSdk 34
versionCode 23
versionName "1.7.0"
versionCode 24
versionName "1.8.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -24,7 +24,6 @@ android {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
applicationIdSuffix ".dev"
}
applicationVariants.all { variant ->
variant.outputs.all {
Expand Down Expand Up @@ -53,8 +52,8 @@ dependencies {
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.security:security-crypto:1.0.0'
implementation 'androidx.media3:media3-exoplayer:1.2.1'
implementation 'androidx.media3:media3-ui:1.2.1'
implementation 'androidx.media3:media3-exoplayer:1.3.0'
implementation 'androidx.media3:media3-ui:1.3.0'

implementation 'com.github.bumptech.glide:glide:4.15.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'
Expand Down
76 changes: 57 additions & 19 deletions app/src/main/java/se/arctosoft/vault/GalleryActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import se.arctosoft.vault.encryption.Encryption;
import se.arctosoft.vault.encryption.Password;
import se.arctosoft.vault.interfaces.IOnDirectoryAdded;
import se.arctosoft.vault.interfaces.IOnProgress;
import se.arctosoft.vault.utils.Dialogs;
import se.arctosoft.vault.utils.FileStuff;
import se.arctosoft.vault.utils.Settings;
Expand All @@ -62,7 +63,7 @@ public class GalleryActivity extends AppCompatActivity {
private static final int REQUEST_IMPORT_IMAGES = 3;
private static final int REQUEST_IMPORT_VIDEOS = 4;

private static final Object lock = new Object();
private static final Object LOCK = new Object();

private GalleryViewModel viewModel;
private ActivityGalleryBinding binding;
Expand Down Expand Up @@ -217,10 +218,10 @@ private void setLoading(boolean loading) {
binding.cLLoading.txtProgress.setVisibility(View.GONE);
}

private void setLoadingProgress(int progress, int total, String doneMB, String totalMB) {
private void setLoadingProgress(int progress, int total, String doneMB, String totalMB, int percentageDone) {
binding.cLLoading.cLLoading.setVisibility(View.VISIBLE);
if (total > 0) {
binding.cLLoading.txtProgress.setText(getString(R.string.gallery_importing_progress, progress, total, doneMB, totalMB));
binding.cLLoading.txtProgress.setText(getString(R.string.gallery_importing_progress, progress, total, doneMB, totalMB, percentageDone));
binding.cLLoading.txtProgress.setVisibility(View.VISIBLE);
} else {
binding.cLLoading.txtProgress.setVisibility(View.GONE);
Expand All @@ -231,7 +232,7 @@ private void findFolders() {
setLoading(true);
new Thread(() -> {
runOnUiThread(() -> {
synchronized (lock) {
synchronized (LOCK) {
int size = galleryFiles.size();
galleryFiles.clear();
galleryGridAdapter.notifyItemRangeRemoved(0, size);
Expand Down Expand Up @@ -316,48 +317,52 @@ public void onOtherDirectory() {

private void importToDirectory(@NonNull List<DocumentFile> documentFiles, @NonNull DocumentFile directory, boolean deleteOriginal) {
new Thread(() -> {
double totalSize = 0;
double totalBytes = 0;
for (DocumentFile file : documentFiles) {
totalSize += (file.length() / 1000000.0);
totalBytes += file.length();
}
final DecimalFormat decimalFormat = new DecimalFormat("0.00");
final String totalMB = decimalFormat.format(totalSize);
final String totalMB = decimalFormat.format(totalBytes / 1000000.0);
final int[] progress = new int[]{1};
final double[] bytesDone = new double[]{0};
final List<DocumentFile> filesToDelete = new ArrayList<>();
runOnUiThread(() -> setLoadingProgress(progress[0], documentFiles.size(), "0", totalMB));
final long[] lastPublish = {0};
double finalTotalSize = totalBytes;
final IOnProgress onProgress = progress1 -> {
if (System.currentTimeMillis() - lastPublish[0] > 20) {
lastPublish[0] = System.currentTimeMillis();
runOnUiThread(() -> setLoadingProgress(progress[0], documentFiles.size(), decimalFormat.format((bytesDone[0] + progress1) / 1000000.0), totalMB,
(int) Math.round((bytesDone[0] + progress1) / finalTotalSize * 100.0)));
}
};
for (DocumentFile file : documentFiles) {
if (cancelTask) {
cancelTask = false;
break;
}
Pair<Boolean, Boolean> imported = new Pair<>(false, false);
try {
imported = Encryption.importFileToDirectory(GalleryActivity.this, file, directory, settings);
imported = Encryption.importFileToDirectory(GalleryActivity.this, file, directory, settings, onProgress);
} catch (SecurityException e) {
e.printStackTrace();
}
progress[0]++;
bytesDone[0] += file.length();
runOnUiThread(() -> setLoadingProgress(progress[0], documentFiles.size(), decimalFormat.format(bytesDone[0] / 1000000.0), totalMB));
if (!imported.first) {
progress[0]--;
runOnUiThread(() -> Toaster.getInstance(GalleryActivity.this).showLong(getString(R.string.gallery_importing_error, file.getName())));
} else if (!imported.second) {
runOnUiThread(() -> Toaster.getInstance(GalleryActivity.this).showLong(getString(R.string.gallery_importing_error_no_thumb, file.getName())));
}
if (deleteOriginal && imported.first) {
filesToDelete.add(file);
file.delete();
}
}
for (DocumentFile toDelete : filesToDelete) {
toDelete.delete();
}
runOnUiThread(() -> {
Toaster.getInstance(GalleryActivity.this).showLong(getString(R.string.gallery_importing_done, progress[0] - 1));
setLoading(false);
});
settings.addGalleryDirectory(directory.getUri(), null);
synchronized (lock) {
synchronized (LOCK) {
for (int i = 0; i < GalleryActivity.this.galleryFiles.size(); i++) {
GalleryFile g = GalleryActivity.this.galleryFiles.get(i);
if (g.getUri() != null && g.getUri().equals(directory.getUri())) {
Expand All @@ -380,18 +385,27 @@ private void importToDirectory(@NonNull List<DocumentFile> documentFiles, @NonNu
private void addDirectory(Uri directoryUri) {
List<GalleryFile> galleryFiles = FileStuff.getFilesInFolder(this, directoryUri);

synchronized (lock) {
synchronized (LOCK) {
this.galleryFiles.add(0, GalleryFile.asDirectory(directoryUri, galleryFiles));
galleryGridAdapter.notifyItemInserted(0);
}
}

private void refreshDirectory(GalleryFile dir) {
List<GalleryFile> found = FileStuff.getFilesInFolder(this, dir.getUri());
int pos = galleryFiles.indexOf(dir);
if (pos >= 0) {
dir.setFilesInDirectory(found);
galleryGridAdapter.notifyItemChanged(pos);
}
}

private void addDirectories(@NonNull List<Uri> directories) {
for (int i = 0; i < directories.size(); i++) {
Uri uri = directories.get(i);
GalleryFile galleryFile = GalleryFile.asDirectory(uri, null);
runOnUiThread(() -> {
synchronized (lock) {
synchronized (LOCK) {
this.galleryFiles.add(galleryFile);
galleryGridAdapter.notifyItemInserted(this.galleryFiles.size() - 1);
}
Expand All @@ -404,7 +418,7 @@ private void addDirectories(@NonNull List<Uri> directories) {
}
runOnUiThread(() -> {
if (!this.galleryFiles.isEmpty()) {
synchronized (lock) {
synchronized (LOCK) {
this.galleryFiles.add(0, GalleryFile.asAllFolder(getString(R.string.gallery_all)));
galleryGridAdapter.notifyItemInserted(0);
}
Expand Down Expand Up @@ -451,6 +465,30 @@ protected void onResume() {
}
}

@Override
protected void onStart() {
super.onStart();
if (galleryFiles != null && galleryGridAdapter != null && !galleryFiles.isEmpty()) {
synchronized (LOCK) {
GridLayoutManager lm = (GridLayoutManager) binding.recyclerView.getLayoutManager();
if (lm != null) {
int firstVisiblePosition = lm.findFirstVisibleItemPosition();
int lastVisibleItemPosition = lm.findLastVisibleItemPosition();
if (firstVisiblePosition != RecyclerView.NO_POSITION && lastVisibleItemPosition != RecyclerView.NO_POSITION) {
for (int i = firstVisiblePosition; i <= lastVisibleItemPosition; i++) {
if (i >= 0 && i < galleryFiles.size()) {
GalleryFile galleryFile = galleryFiles.get(i);
if (!galleryFile.isAllFolder() && galleryFile.isDirectory()) {
refreshDirectory(galleryFile);
}
}
}
}
}
}
}
}

@Override
public void onBackPressed() {
if (binding.cLLoading.cLLoading.getVisibility() == View.VISIBLE) {
Expand Down
88 changes: 66 additions & 22 deletions app/src/main/java/se/arctosoft/vault/GalleryDirectoryActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import se.arctosoft.vault.adapters.GalleryGridAdapter;
import se.arctosoft.vault.adapters.GalleryPagerAdapter;
Expand Down Expand Up @@ -162,6 +164,12 @@ private void init() {
finish();
return;
}
DocumentFile documentFile = DocumentFile.fromSingleUri(this, currentDirectory);
if (documentFile == null || !documentFile.isDirectory() || !documentFile.exists()) {
Toaster.getInstance(this).showLong(getString(R.string.directory_does_not_exist));
finish();
return;
}
setupViewpager();
setupRecycler();
setClickListeners();
Expand All @@ -185,31 +193,49 @@ public void onSelectionChanged(int selected) {
binding.btnDeleteFiles.setText(getString(R.string.gallery_delete_selected_files, selected));
}

private void deleteSelectedFiles() { // TODO run in parallel to make it faster, ExecutorService
private void deleteSelectedFiles() {
setLoading(true);
new Thread(() -> {
synchronized (LOCK) {
final int[] count = {0};
int failed = 0;
final int total = galleryGridAdapter.getSelectedFiles().size();
final List<Integer> positionsDeleted = new ArrayList<>();
for (GalleryFile f : galleryGridAdapter.getSelectedFiles()) {
if (isCancelled) {
isCancelled = false;
break;
}
runOnUiThread(() -> setLoadingWithProgress(++count[0], failed, total, R.string.gallery_deleting_progress));
boolean deleted = FileStuff.deleteFile(this, f.getUri());
FileStuff.deleteFile(this, f.getThumbUri());
if (deleted) {
int i = viewModel.getGalleryFiles().indexOf(f);
if (i >= 0) {
positionsDeleted.add(i);
List<GalleryFile> selectedFiles = galleryGridAdapter.getSelectedFiles();
ConcurrentLinkedQueue<GalleryFile> queue = new ConcurrentLinkedQueue<>(selectedFiles);
List<Integer> positionsDeleted = Collections.synchronizedList(new ArrayList<>());
AtomicInteger deletedCount = new AtomicInteger(0);
AtomicInteger failedCount = new AtomicInteger(0);
final int total = selectedFiles.size();
final int threadCount;
if (total < 4) {
threadCount = 1;
} else if (total < 20) {
threadCount = 4;
} else {
threadCount = 8;
}
runOnUiThread(() -> setLoadingWithProgress(0, 0, 0, R.string.gallery_deleting_progress));
List<Thread> threads = new ArrayList<>(threadCount);
for (int i = 0; i < threadCount; i++) {
Thread t = new Thread(() -> {
GalleryFile f;
while (!isCancelled && (f = queue.poll()) != null) {
deleteFile(total, f, positionsDeleted, deletedCount, failedCount);
}
});
threads.add(t);
t.start();
}

for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (isCancelled) {
isCancelled = false;
}
Collections.sort(positionsDeleted);
runOnUiThread(() -> {
Collections.sort(positionsDeleted);
for (int i = positionsDeleted.size() - 1; i >= 0; i--) {
viewModel.getGalleryFiles().remove(i);
galleryGridAdapter.notifyItemRemoved(i);
Expand All @@ -222,6 +248,25 @@ private void deleteSelectedFiles() { // TODO run in parallel to make it faster,
}).start();
}

private void deleteFile(int total, GalleryFile file, List<Integer> positionsDeleted, AtomicInteger deletedCount, AtomicInteger failedCount) {
if (file == null || isCancelled) {
return;
}
boolean deleted = FileStuff.deleteFile(this, file.getUri());
FileStuff.deleteFile(this, file.getThumbUri());
FileStuff.deleteFile(this, file.getNoteUri());
if (deleted) {
deletedCount.addAndGet(1);
int i = viewModel.getGalleryFiles().indexOf(file);
if (i >= 0) {
positionsDeleted.add(i);
}
} else {
failedCount.addAndGet(1);
}
runOnUiThread(() -> setLoadingWithProgress(deletedCount.get() + failedCount.get(), failedCount.get(), total, R.string.gallery_deleting_progress));
}

private void setupRecycler() {
if (viewModel.isInitialised()) {
binding.recyclerView.setFastScrollEnabled(viewModel.getGalleryFiles().size() > MIN_FILES_FOR_FAST_SCROLL);
Expand Down Expand Up @@ -250,7 +295,7 @@ private void onSelectionModeChanged(boolean inSelectionMode) {
}

private void setupViewpager() {
galleryPagerAdapter = new GalleryPagerAdapter(this, viewModel.getGalleryFiles(), pos -> galleryGridAdapter.notifyItemRemoved(pos), currentDocumentDirectory, isAllFolder);
galleryPagerAdapter = new GalleryPagerAdapter(this, viewModel.getGalleryFiles(), pos -> galleryGridAdapter.notifyItemRemoved(pos), currentDocumentDirectory, isAllFolder, nestedPath);
binding.viewPager.setAdapter(galleryPagerAdapter);
//Log.e(TAG, "setupViewpager: " + viewModel.getCurrentPosition() + " " + viewModel.isFullscreen());
binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
Expand All @@ -259,7 +304,6 @@ public void onPageSelected(int position) {
super.onPageSelected(position);
binding.recyclerView.scrollToPosition(position);
viewModel.setCurrentPosition(position);
galleryPagerAdapter.releaseVideo();
}
});
binding.viewPager.postDelayed(() -> {
Expand Down Expand Up @@ -468,15 +512,15 @@ private List<GalleryFile> findAllFilesInFolder(Uri uri) {
@Override
protected void onStop() {
if (galleryPagerAdapter != null) {
galleryPagerAdapter.pauseVideo();
galleryPagerAdapter.pausePlayers();
}
super.onStop();
}

@Override
protected void onDestroy() {
if (galleryPagerAdapter != null) {
galleryPagerAdapter.releaseVideo();
galleryPagerAdapter.releasePlayers();
}
super.onDestroy();
}
Expand Down
Loading

0 comments on commit 9be1676

Please sign in to comment.