mirror of
https://github.com/SimpleMobileTools/Simple-Gallery.git
synced 2025-06-05 21:59:19 +02:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f6b4516c0 | ||
|
|
cacb419b4f | ||
|
|
af970a459c | ||
|
|
03d53a8436 | ||
|
|
e5f9ea9627 | ||
|
|
fa4cadebb4 | ||
|
|
83dc85e63b | ||
|
|
06f7d8d29d | ||
|
|
db04516773 | ||
|
|
639c3d57c6 | ||
|
|
6a80ab4473 | ||
|
|
6ee959d2a4 | ||
|
|
f65b5013ab | ||
|
|
18bad5106a | ||
|
|
8c57a00947 | ||
|
|
c525a0ebc7 | ||
|
|
af246cdcf0 | ||
|
|
53aa8e86d7 | ||
|
|
b759f71363 | ||
|
|
f9502638f1 | ||
|
|
a842d4daf7 | ||
|
|
4394e6074e | ||
|
|
53ed959e63 | ||
|
|
60596b7e5c | ||
|
|
06c3645bf9 | ||
|
|
cc7c6a1e24 | ||
|
|
258c49eeb8 | ||
|
|
06f345240a | ||
|
|
cd4d98d386 | ||
|
|
6c4ec53cc1 | ||
|
|
613ab2bb10 | ||
|
|
9616e914b9 |
@@ -1,6 +1,13 @@
|
||||
Changelog
|
||||
==========
|
||||
|
||||
Version 1.36 *(2016-11-17)*
|
||||
----------------------------
|
||||
|
||||
* Do not be so strict at limiting characters at file names
|
||||
* Fix setting folders as un/hidden
|
||||
* A lot more smaller fixes
|
||||
|
||||
Version 1.35 *(2016-11-15)*
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.simplemobiletools.gallery"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 23
|
||||
versionCode 35
|
||||
versionName "1.35"
|
||||
versionCode 36
|
||||
versionName "1.36"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -44,8 +44,9 @@ dependencies {
|
||||
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0'
|
||||
compile 'com.theartofdev.edmodo:android-image-cropper:2.3.1'
|
||||
compile 'com.booking:rtlviewpager:1.0.1'
|
||||
compile 'com.simplemobiletools:fileproperties:1.0.4@aar'
|
||||
compile 'com.simplemobiletools:filepicker:1.4.2@aar'
|
||||
compile 'com.simplemobiletools:fileproperties:1.0.5@aar'
|
||||
compile 'com.simplemobiletools:filepicker:1.4.3@aar'
|
||||
compile 'com.bignerdranch.android:recyclerview-multiselect:0.2'
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
|
||||
apt 'com.jakewharton:butterknife-compiler:8.0.1'
|
||||
|
||||
@@ -1,608 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.GridView;
|
||||
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask;
|
||||
import com.simplemobiletools.fileproperties.dialogs.PropertiesDialog;
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.Utils;
|
||||
import com.simplemobiletools.gallery.adapters.DirectoryAdapter;
|
||||
import com.simplemobiletools.gallery.asynctasks.GetDirectoriesAsynctask;
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog;
|
||||
import com.simplemobiletools.gallery.dialogs.CopyDialog;
|
||||
import com.simplemobiletools.gallery.dialogs.RenameDirectoryDialog;
|
||||
import com.simplemobiletools.gallery.models.Directory;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class MainActivity extends SimpleActivity
|
||||
implements AdapterView.OnItemClickListener, GridView.MultiChoiceModeListener, GridView.OnTouchListener,
|
||||
SwipeRefreshLayout.OnRefreshListener, GetDirectoriesAsynctask.GetDirectoriesListener {
|
||||
@BindView(R.id.directories_grid) GridView mGridView;
|
||||
@BindView(R.id.directories_holder) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
private static final int STORAGE_PERMISSION = 1;
|
||||
private static final int PICK_MEDIA = 2;
|
||||
private static final int PICK_WALLPAPER = 3;
|
||||
|
||||
private static List<Directory> mDirs;
|
||||
private static Snackbar mSnackbar;
|
||||
private static List<String> mToBeDeleted;
|
||||
private static ActionMode mActionMode;
|
||||
private static Parcelable mState;
|
||||
|
||||
private static boolean mIsSnackbarShown;
|
||||
private static boolean mIsPickImageIntent;
|
||||
private static boolean mIsPickVideoIntent;
|
||||
private static boolean mIsGetImageContentIntent;
|
||||
private static boolean mIsGetVideoContentIntent;
|
||||
private static boolean mIsGetAnyContentIntent;
|
||||
private static boolean mIsSetWallpaperIntent;
|
||||
private static boolean mIsThirdPartyIntent;
|
||||
private static boolean mIsGettingDirs;
|
||||
private static int mSelectedItemsCnt;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
mIsPickImageIntent = isPickImageIntent(intent);
|
||||
mIsPickVideoIntent = isPickVideoIntent(intent);
|
||||
mIsGetImageContentIntent = isGetImageContentIntent(intent);
|
||||
mIsGetVideoContentIntent = isGetVideoContentIntent(intent);
|
||||
mIsGetAnyContentIntent = isGetAnyContentIntent(intent);
|
||||
mIsSetWallpaperIntent = isSetWallpaperIntent(intent);
|
||||
mIsThirdPartyIntent = mIsPickImageIntent || mIsPickVideoIntent || mIsGetImageContentIntent || mIsGetVideoContentIntent ||
|
||||
mIsGetAnyContentIntent || mIsSetWallpaperIntent;
|
||||
|
||||
mToBeDeleted = new ArrayList<>();
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
mDirs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (mIsThirdPartyIntent)
|
||||
return false;
|
||||
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.sort:
|
||||
showSortingDialog();
|
||||
return true;
|
||||
case R.id.camera:
|
||||
startActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
|
||||
return true;
|
||||
case R.id.settings:
|
||||
startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
|
||||
return true;
|
||||
case R.id.about:
|
||||
startActivity(new Intent(getApplicationContext(), AboutActivity.class));
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
tryloadGallery();
|
||||
if (mState != null && mGridView != null)
|
||||
mGridView.onRestoreInstanceState(mState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
deleteDirs();
|
||||
if (mGridView != null)
|
||||
mState = mGridView.onSaveInstanceState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mConfig.setFirstRun(false);
|
||||
}
|
||||
|
||||
private void tryloadGallery() {
|
||||
if (Utils.Companion.hasStoragePermission(getApplicationContext())) {
|
||||
getDirectories();
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (requestCode == STORAGE_PERMISSION) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
getDirectories();
|
||||
} else {
|
||||
Utils.Companion.showToast(getApplicationContext(), R.string.no_permissions);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getDirectories() {
|
||||
if (mIsGettingDirs)
|
||||
return;
|
||||
|
||||
mIsGettingDirs = true;
|
||||
new GetDirectoriesAsynctask(getApplicationContext(), mIsPickVideoIntent || mIsGetVideoContentIntent, mIsPickImageIntent || mIsGetImageContentIntent,
|
||||
mToBeDeleted, this).execute();
|
||||
}
|
||||
|
||||
private void showSortingDialog() {
|
||||
new ChangeSortingDialog(this, true, new ChangeSortingDialog.OnChangeSortingListener() {
|
||||
@Override
|
||||
public void sortingChanged() {
|
||||
getDirectories();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void prepareForDeleting() {
|
||||
Utils.Companion.showToast(this, R.string.deleting);
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
int deletedCnt = 0;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
final String path = mDirs.get(id).getPath();
|
||||
mToBeDeleted.add(path);
|
||||
deletedCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
for (String path : mToBeDeleted) {
|
||||
if (isShowingPermDialog(new File(path))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
notifyDeletion(deletedCnt);
|
||||
}
|
||||
|
||||
private void notifyDeletion(int cnt) {
|
||||
getDirectories();
|
||||
|
||||
final CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
|
||||
final Resources res = getResources();
|
||||
final String msg = res.getQuantityString(R.plurals.folders_deleted, cnt, cnt);
|
||||
mSnackbar = Snackbar.make(coordinator, msg, Snackbar.LENGTH_INDEFINITE);
|
||||
mSnackbar.setAction(res.getString(R.string.undo), undoDeletion);
|
||||
mSnackbar.setActionTextColor(Color.WHITE);
|
||||
mSnackbar.show();
|
||||
mIsSnackbarShown = true;
|
||||
}
|
||||
|
||||
private void deleteDirs() {
|
||||
if (mToBeDeleted == null || mToBeDeleted.isEmpty())
|
||||
return;
|
||||
|
||||
if (mSnackbar != null) {
|
||||
mSnackbar.dismiss();
|
||||
}
|
||||
|
||||
mIsSnackbarShown = false;
|
||||
|
||||
final ArrayList<File> updatedFiles = new ArrayList<>();
|
||||
for (String delPath : mToBeDeleted) {
|
||||
final File dir = new File(delPath);
|
||||
if (dir.exists()) {
|
||||
final File[] files = dir.listFiles();
|
||||
for (File file : files) {
|
||||
if (file.isFile() && Utils.Companion.isPhotoVideo(file)) {
|
||||
updatedFiles.add(file);
|
||||
deleteItem(file);
|
||||
}
|
||||
}
|
||||
updatedFiles.add(dir);
|
||||
if (dir.listFiles().length == 0)
|
||||
deleteItem(dir);
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Companion.scanFiles(getApplicationContext(), updatedFiles);
|
||||
mToBeDeleted.clear();
|
||||
}
|
||||
|
||||
private void deleteItem(File file) {
|
||||
if (Utils.Companion.needsStupidWritePermissions(this, file.getAbsolutePath())) {
|
||||
if (!isShowingPermDialog(file)) {
|
||||
final DocumentFile document = Utils.Companion.getFileDocument(this, file.getAbsolutePath(), mConfig.getTreeUri());
|
||||
document.delete();
|
||||
}
|
||||
} else {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener undoDeletion = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mSnackbar.dismiss();
|
||||
mIsSnackbarShown = false;
|
||||
mToBeDeleted.clear();
|
||||
getDirectories();
|
||||
}
|
||||
};
|
||||
|
||||
private void showProperties() {
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
if (items.size() == 1) {
|
||||
new PropertiesDialog(this, (String) getSelectedPaths().toArray()[0], false);
|
||||
} else {
|
||||
final List<String> paths = new ArrayList<>(items.size());
|
||||
final int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
paths.add(mDirs.get(id).getPath());
|
||||
}
|
||||
}
|
||||
|
||||
new PropertiesDialog(this, paths, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void editDirectory() {
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
final String path = mDirs.get(id).getPath();
|
||||
renameDir(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renameDir(final String path) {
|
||||
final File dir = new File(path);
|
||||
if (Utils.Companion.isAStorageRootFolder(this, path)) {
|
||||
Utils.Companion.showToast(this, R.string.rename_folder_root);
|
||||
return;
|
||||
}
|
||||
|
||||
new RenameDirectoryDialog(this, dir, new RenameDirectoryDialog.OnRenameDirListener() {
|
||||
@Override
|
||||
public void onRenameDirSuccess(@NotNull String[] changedFiles) {
|
||||
mActionMode.finish();
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), changedFiles, null, new MediaScannerConnection.OnScanCompletedListener() {
|
||||
@Override
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
scanCompleted(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayCopyDialog() {
|
||||
final ArrayList<File> files = new ArrayList<>();
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
final File dir = new File(mDirs.get(id).getPath());
|
||||
files.addAll(Arrays.asList(dir.listFiles()));
|
||||
}
|
||||
}
|
||||
|
||||
new CopyDialog(this, files, new CopyMoveTask.CopyMoveListener() {
|
||||
@Override
|
||||
public void copySucceeded(boolean deleted, boolean copiedAll) {
|
||||
int msgId;
|
||||
if (deleted) {
|
||||
getDirectories();
|
||||
msgId = copiedAll ? R.string.moving_success : R.string.moving_success_partial;
|
||||
} else {
|
||||
msgId = copiedAll ? R.string.copying_success : R.string.copying_success_partial;
|
||||
}
|
||||
Utils.Companion.showToast(getApplicationContext(), msgId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFailed() {
|
||||
Utils.Companion.showToast(getApplicationContext(), R.string.copy_move_failed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isPickImageIntent(Intent intent) {
|
||||
return isPickIntent(intent) && (hasImageContentData(intent) || isImageType(intent));
|
||||
}
|
||||
|
||||
private boolean isPickVideoIntent(Intent intent) {
|
||||
return isPickIntent(intent) && (hasVideoContentData(intent) || isVideoType(intent));
|
||||
}
|
||||
|
||||
private boolean isPickIntent(Intent intent) {
|
||||
return intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_PICK);
|
||||
}
|
||||
|
||||
private boolean isGetContentIntent(Intent intent) {
|
||||
return intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_GET_CONTENT) &&
|
||||
intent.getType() != null;
|
||||
}
|
||||
|
||||
private boolean isGetImageContentIntent(Intent intent) {
|
||||
return isGetContentIntent(intent) &&
|
||||
(intent.getType().startsWith("image/") || intent.getType().equals(MediaStore.Images.Media.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
private boolean isGetVideoContentIntent(Intent intent) {
|
||||
return isGetContentIntent(intent) &&
|
||||
(intent.getType().startsWith("video/") || intent.getType().equals(MediaStore.Video.Media.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
private boolean isGetAnyContentIntent(Intent intent) {
|
||||
return isGetContentIntent(intent) && intent.getType().equals("*/*");
|
||||
}
|
||||
|
||||
private boolean isSetWallpaperIntent(Intent intent) {
|
||||
return intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SET_WALLPAPER);
|
||||
}
|
||||
|
||||
private boolean hasImageContentData(Intent intent) {
|
||||
final Uri data = intent.getData();
|
||||
return data != null && data.equals(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
}
|
||||
|
||||
private boolean hasVideoContentData(Intent intent) {
|
||||
final Uri data = intent.getData();
|
||||
return data != null && data.equals(MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
|
||||
}
|
||||
|
||||
private boolean isImageType(Intent intent) {
|
||||
final String type = intent.getType();
|
||||
return type != null && (type.startsWith("image/") || type.equals(MediaStore.Images.Media.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
private boolean isVideoType(Intent intent) {
|
||||
final String type = intent.getType();
|
||||
return type != null && (type.startsWith("video/") || type.equals(MediaStore.Video.Media.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == PICK_MEDIA && resultData != null) {
|
||||
final Intent result = new Intent();
|
||||
final String path = resultData.getData().getPath();
|
||||
final Uri uri = Uri.fromFile(new File(path));
|
||||
if (mIsGetImageContentIntent || mIsGetVideoContentIntent || mIsGetAnyContentIntent) {
|
||||
final String type = Utils.Companion.getMimeType(path);
|
||||
result.setDataAndTypeAndNormalize(uri, type);
|
||||
result.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
} else if (mIsPickImageIntent || mIsPickVideoIntent) {
|
||||
result.setData(uri);
|
||||
result.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
|
||||
setResult(RESULT_OK, result);
|
||||
finish();
|
||||
} else if (requestCode == PICK_WALLPAPER) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, resultData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final Intent intent = new Intent(this, MediaActivity.class);
|
||||
intent.putExtra(Constants.INSTANCE.getDIRECTORY(), mDirs.get(position).getPath());
|
||||
|
||||
if (mIsSetWallpaperIntent) {
|
||||
intent.putExtra(Constants.INSTANCE.getSET_WALLPAPER_INTENT(), true);
|
||||
startActivityForResult(intent, PICK_WALLPAPER);
|
||||
} else {
|
||||
intent.putExtra(Constants.INSTANCE.getGET_IMAGE_INTENT(), mIsPickImageIntent || mIsGetImageContentIntent);
|
||||
intent.putExtra(Constants.INSTANCE.getGET_VIDEO_INTENT(), mIsPickVideoIntent || mIsGetVideoContentIntent);
|
||||
intent.putExtra(Constants.INSTANCE.getGET_ANY_INTENT(), mIsGetAnyContentIntent);
|
||||
startActivityForResult(intent, PICK_MEDIA);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
|
||||
if (checked) {
|
||||
mSelectedItemsCnt++;
|
||||
} else {
|
||||
mSelectedItemsCnt--;
|
||||
}
|
||||
|
||||
if (mSelectedItemsCnt > 0) {
|
||||
mode.setTitle(String.valueOf(mSelectedItemsCnt));
|
||||
}
|
||||
|
||||
mode.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
final MenuInflater inflater = mode.getMenuInflater();
|
||||
inflater.inflate(R.menu.cab_directories, menu);
|
||||
mActionMode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
menu.findItem(R.id.cab_edit).setVisible(mSelectedItemsCnt == 1);
|
||||
|
||||
int hiddenCnt = 0;
|
||||
int unhiddenCnt = 0;
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
if (mConfig.getIsFolderHidden(mDirs.get(id).getPath()))
|
||||
hiddenCnt++;
|
||||
else
|
||||
unhiddenCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
menu.findItem(R.id.cab_hide).setVisible(unhiddenCnt > 0);
|
||||
menu.findItem(R.id.cab_unhide).setVisible(hiddenCnt > 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.cab_properties:
|
||||
showProperties();
|
||||
return true;
|
||||
case R.id.cab_edit:
|
||||
editDirectory();
|
||||
return true;
|
||||
case R.id.cab_delete:
|
||||
prepareForDeleting();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_hide:
|
||||
hideFolders();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_unhide:
|
||||
unhideFolders();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_copy_move:
|
||||
displayCopyDialog();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mSelectedItemsCnt = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (mIsSnackbarShown) {
|
||||
deleteDirs();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void hideFolders() {
|
||||
mConfig.addHiddenDirectories(getSelectedPaths());
|
||||
getDirectories();
|
||||
}
|
||||
|
||||
private void unhideFolders() {
|
||||
mConfig.removeHiddenDirectories(getSelectedPaths());
|
||||
getDirectories();
|
||||
}
|
||||
|
||||
private Set<String> getSelectedPaths() {
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final Set<String> selectedPaths = new HashSet<>();
|
||||
final int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
selectedPaths.add(mDirs.get(id).getPath());
|
||||
}
|
||||
}
|
||||
return selectedPaths;
|
||||
}
|
||||
|
||||
private void scanCompleted(final String path) {
|
||||
final File dir = new File(path);
|
||||
if (dir.isDirectory()) {
|
||||
getDirectories();
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Utils.Companion.showToast(getApplicationContext(), R.string.rename_folder_ok);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
getDirectories();
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotDirectories(@NotNull ArrayList<Directory> dirs) {
|
||||
mIsGettingDirs = false;
|
||||
if (dirs.toString().equals(mDirs.toString())) {
|
||||
return;
|
||||
}
|
||||
mDirs = dirs;
|
||||
|
||||
final DirectoryAdapter adapter = new DirectoryAdapter(this, mDirs);
|
||||
mGridView.setAdapter(adapter);
|
||||
mGridView.setOnItemClickListener(this);
|
||||
mGridView.setMultiChoiceModeListener(this);
|
||||
mGridView.setOnTouchListener(this);
|
||||
mGridView.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
|
||||
}
|
||||
}
|
||||
@@ -40,35 +40,34 @@ class Config private constructor(context: Context) {
|
||||
set(showHiddenFolders) = mPrefs.edit().putBoolean(SHOW_HIDDEN_FOLDERS, showHiddenFolders).apply()
|
||||
|
||||
fun addHiddenDirectory(path: String) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.add(path)
|
||||
mPrefs.edit().putStringSet(HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
val currHiddenFolders = HashSet<String>(hiddenFolders)
|
||||
currHiddenFolders.add(path)
|
||||
hiddenFolders = currHiddenFolders
|
||||
}
|
||||
|
||||
fun addHiddenDirectories(paths: Set<String>) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.addAll(paths)
|
||||
mPrefs.edit().putStringSet(HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
val currHiddenFolders = HashSet<String>(hiddenFolders)
|
||||
currHiddenFolders.addAll(paths)
|
||||
hiddenFolders = currHiddenFolders
|
||||
}
|
||||
|
||||
fun removeHiddenDirectory(path: String) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.remove(path)
|
||||
mPrefs.edit().putStringSet(HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
val currHiddenFolders = HashSet<String>(hiddenFolders)
|
||||
currHiddenFolders.remove(path)
|
||||
hiddenFolders = currHiddenFolders
|
||||
}
|
||||
|
||||
fun removeHiddenDirectories(paths: Set<String>) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.removeAll(paths)
|
||||
mPrefs.edit().putStringSet(HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
val currHiddenFolders = HashSet<String>(hiddenFolders)
|
||||
currHiddenFolders.removeAll(paths)
|
||||
hiddenFolders = currHiddenFolders
|
||||
}
|
||||
|
||||
val hiddenFolders: MutableSet<String>
|
||||
fun getIsFolderHidden(path: String) = hiddenFolders.contains(path)
|
||||
|
||||
var hiddenFolders: MutableSet<String>
|
||||
get() = mPrefs.getStringSet(HIDDEN_FOLDERS, HashSet<String>())
|
||||
|
||||
fun getIsFolderHidden(path: String): Boolean {
|
||||
return hiddenFolders.contains(path)
|
||||
}
|
||||
set(hiddenFolders) = mPrefs.edit().remove(HIDDEN_FOLDERS).putStringSet(HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
|
||||
var autoplayVideos: Boolean
|
||||
get() = mPrefs.getBoolean(AUTOPLAY_VIDEOS, false)
|
||||
|
||||
@@ -97,10 +97,6 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
fun isAStorageRootFolder(context: Context, path: String) = context.isAStorageRootFolder(path)
|
||||
|
||||
fun isPhotoVideo(file: File) = file.isPhotoVideo()
|
||||
|
||||
fun needsStupidWritePermissions(context: Context, path: String) = context.needsStupidWritePermissions(path)
|
||||
|
||||
fun getFileDocument(context: Context, path: String, treeUri: String) = context.getFileDocument(path, treeUri)
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.Utils
|
||||
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
|
||||
import com.simplemobiletools.gallery.asynctasks.GetDirectoriesAsynctask
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeSortingDialog
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class MainActivity : SimpleActivity(), SwipeRefreshLayout.OnRefreshListener, GetDirectoriesAsynctask.GetDirectoriesListener, View.OnTouchListener, DirectoryAdapter.DirOperationsListener {
|
||||
companion object {
|
||||
private val STORAGE_PERMISSION = 1
|
||||
private val PICK_MEDIA = 2
|
||||
private val PICK_WALLPAPER = 3
|
||||
|
||||
private var mSnackbar: Snackbar? = null
|
||||
lateinit var mDirs: MutableList<Directory>
|
||||
lateinit var mToBeDeleted: MutableList<String>
|
||||
|
||||
private var mIsSnackbarShown = false
|
||||
private var mIsPickImageIntent = false
|
||||
private var mIsPickVideoIntent = false
|
||||
private var mIsGetImageContentIntent = false
|
||||
private var mIsGetVideoContentIntent = false
|
||||
private var mIsGetAnyContentIntent = false
|
||||
private var mIsSetWallpaperIntent = false
|
||||
private var mIsThirdPartyIntent = false
|
||||
private var mIsGettingDirs = false
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
mIsPickImageIntent = isPickImageIntent(intent)
|
||||
mIsPickVideoIntent = isPickVideoIntent(intent)
|
||||
mIsGetImageContentIntent = isGetImageContentIntent(intent)
|
||||
mIsGetVideoContentIntent = isGetVideoContentIntent(intent)
|
||||
mIsGetAnyContentIntent = isGetAnyContentIntent(intent)
|
||||
mIsSetWallpaperIntent = isSetWallpaperIntent(intent)
|
||||
mIsThirdPartyIntent = mIsPickImageIntent || mIsPickVideoIntent || mIsGetImageContentIntent || mIsGetVideoContentIntent ||
|
||||
mIsGetAnyContentIntent || mIsSetWallpaperIntent
|
||||
|
||||
mToBeDeleted = ArrayList<String>()
|
||||
directories_holder.setOnRefreshListener(this)
|
||||
mDirs = ArrayList<Directory>()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (mIsThirdPartyIntent)
|
||||
return false
|
||||
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.sort -> {
|
||||
showSortingDialog()
|
||||
true
|
||||
}
|
||||
R.id.camera -> {
|
||||
startActivity(Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA))
|
||||
true
|
||||
}
|
||||
R.id.settings -> {
|
||||
startActivity(Intent(applicationContext, SettingsActivity::class.java))
|
||||
true
|
||||
}
|
||||
R.id.about -> {
|
||||
startActivity(Intent(applicationContext, AboutActivity::class.java))
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
tryloadGallery()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
deleteDirs()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mConfig.isFirstRun = false
|
||||
}
|
||||
|
||||
private fun tryloadGallery() {
|
||||
if (hasStoragePermission()) {
|
||||
getDirectories()
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORAGE_PERMISSION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
if (requestCode == STORAGE_PERMISSION) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
getDirectories()
|
||||
} else {
|
||||
toast(R.string.no_permissions)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDirectories() {
|
||||
if (mIsGettingDirs)
|
||||
return
|
||||
|
||||
mIsGettingDirs = true
|
||||
GetDirectoriesAsynctask(applicationContext, mIsPickVideoIntent || mIsGetVideoContentIntent, mIsPickImageIntent || mIsGetImageContentIntent,
|
||||
mToBeDeleted, this).execute()
|
||||
}
|
||||
|
||||
private fun showSortingDialog() {
|
||||
ChangeSortingDialog(this, true, object : ChangeSortingDialog.OnChangeSortingListener {
|
||||
override fun sortingChanged() {
|
||||
getDirectories()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun prepareForDeleting(paths: ArrayList<String>) {
|
||||
toast(R.string.deleting)
|
||||
mToBeDeleted = paths
|
||||
val deletedCnt = mToBeDeleted.size
|
||||
|
||||
if (isShowingPermDialog(File(mToBeDeleted[0])))
|
||||
return
|
||||
|
||||
notifyDeletion(deletedCnt)
|
||||
}
|
||||
|
||||
private fun notifyDeletion(cnt: Int) {
|
||||
getDirectories()
|
||||
|
||||
val res = resources
|
||||
val msg = res.getQuantityString(R.plurals.folders_deleted, cnt, cnt)
|
||||
mSnackbar = Snackbar.make(coordinator_layout, msg, Snackbar.LENGTH_INDEFINITE)
|
||||
mSnackbar!!.apply {
|
||||
setAction(res.getString(R.string.undo), undoDeletion)
|
||||
setActionTextColor(Color.WHITE)
|
||||
show()
|
||||
}
|
||||
mIsSnackbarShown = true
|
||||
}
|
||||
|
||||
private fun deleteDirs() {
|
||||
if (mToBeDeleted.isEmpty())
|
||||
return
|
||||
|
||||
mSnackbar?.dismiss()
|
||||
mIsSnackbarShown = false
|
||||
|
||||
val updatedFiles = ArrayList<File>()
|
||||
for (delPath in mToBeDeleted) {
|
||||
val dir = File(delPath)
|
||||
if (dir.exists()) {
|
||||
val files = dir.listFiles()
|
||||
files.forEach {
|
||||
if (it.isFile && it.isPhotoVideo()) {
|
||||
updatedFiles.add(it)
|
||||
deleteItem(it)
|
||||
}
|
||||
}
|
||||
updatedFiles.add(dir)
|
||||
if (dir.listFiles().isEmpty())
|
||||
deleteItem(dir)
|
||||
}
|
||||
}
|
||||
|
||||
scanFiles(updatedFiles) {}
|
||||
mToBeDeleted.clear()
|
||||
}
|
||||
|
||||
private fun deleteItem(file: File) {
|
||||
if (needsStupidWritePermissions(file.absolutePath)) {
|
||||
if (!isShowingPermDialog(file)) {
|
||||
getFileDocument(file.absolutePath, mConfig.treeUri).delete()
|
||||
}
|
||||
} else {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
|
||||
private val undoDeletion = View.OnClickListener {
|
||||
mSnackbar!!.dismiss()
|
||||
mIsSnackbarShown = false
|
||||
mToBeDeleted.clear()
|
||||
getDirectories()
|
||||
}
|
||||
|
||||
private fun isPickImageIntent(intent: Intent) = isPickIntent(intent) && (hasImageContentData(intent) || isImageType(intent))
|
||||
|
||||
private fun isPickVideoIntent(intent: Intent) = isPickIntent(intent) && (hasVideoContentData(intent) || isVideoType(intent))
|
||||
|
||||
private fun isPickIntent(intent: Intent) = intent.action == Intent.ACTION_PICK
|
||||
|
||||
private fun isGetContentIntent(intent: Intent) = intent.action == Intent.ACTION_GET_CONTENT && intent.type != null
|
||||
|
||||
private fun isGetImageContentIntent(intent: Intent) = isGetContentIntent(intent) &&
|
||||
(intent.type.startsWith("image/") || intent.type == MediaStore.Images.Media.CONTENT_TYPE)
|
||||
|
||||
private fun isGetVideoContentIntent(intent: Intent) = isGetContentIntent(intent) &&
|
||||
(intent.type.startsWith("video/") || intent.type == MediaStore.Video.Media.CONTENT_TYPE)
|
||||
|
||||
private fun isGetAnyContentIntent(intent: Intent) = isGetContentIntent(intent) && intent.type == "*/*"
|
||||
|
||||
private fun isSetWallpaperIntent(intent: Intent?) = intent?.action == Intent.ACTION_SET_WALLPAPER
|
||||
|
||||
private fun hasImageContentData(intent: Intent) = intent.data == MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
|
||||
private fun hasVideoContentData(intent: Intent) = intent.data == MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
|
||||
private fun isImageType(intent: Intent) = (intent.type?.startsWith("image/") == true || intent.type == MediaStore.Images.Media.CONTENT_TYPE)
|
||||
|
||||
private fun isVideoType(intent: Intent) = (intent.type?.startsWith("video/") == true || intent.type == MediaStore.Video.Media.CONTENT_TYPE)
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == PICK_MEDIA && resultData != null) {
|
||||
Intent().apply {
|
||||
val path = resultData.data.path
|
||||
val uri = Uri.fromFile(File(path))
|
||||
if (mIsGetImageContentIntent || mIsGetVideoContentIntent || mIsGetAnyContentIntent) {
|
||||
val type = Utils.getMimeType(path)
|
||||
setDataAndTypeAndNormalize(uri, type)
|
||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
} else if (mIsPickImageIntent || mIsPickVideoIntent) {
|
||||
data = uri
|
||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
}
|
||||
|
||||
setResult(Activity.RESULT_OK, this)
|
||||
}
|
||||
finish()
|
||||
} else if (requestCode == PICK_WALLPAPER) {
|
||||
setResult(Activity.RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
}
|
||||
|
||||
fun itemClicked(path: String) {
|
||||
Intent(this, MediaActivity::class.java).apply {
|
||||
putExtra(Constants.DIRECTORY, path)
|
||||
|
||||
if (mIsSetWallpaperIntent) {
|
||||
putExtra(Constants.SET_WALLPAPER_INTENT, true)
|
||||
startActivityForResult(this, PICK_WALLPAPER)
|
||||
} else {
|
||||
putExtra(Constants.GET_IMAGE_INTENT, mIsPickImageIntent || mIsGetImageContentIntent)
|
||||
putExtra(Constants.GET_VIDEO_INTENT, mIsPickVideoIntent || mIsGetVideoContentIntent)
|
||||
putExtra(Constants.GET_ANY_INTENT, mIsGetAnyContentIntent)
|
||||
startActivityForResult(this, PICK_MEDIA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
getDirectories()
|
||||
directories_holder.isRefreshing = false
|
||||
}
|
||||
|
||||
override fun gotDirectories(dirs: ArrayList<Directory>) {
|
||||
mIsGettingDirs = false
|
||||
if (dirs.toString() == mDirs.toString()) {
|
||||
return
|
||||
}
|
||||
mDirs = dirs
|
||||
|
||||
val adapter = DirectoryAdapter(this, mDirs, this) {
|
||||
itemClicked(it.path)
|
||||
}
|
||||
directories_grid.adapter = adapter
|
||||
directories_grid.setOnTouchListener(this)
|
||||
}
|
||||
|
||||
override fun refreshItems() {
|
||||
getDirectories()
|
||||
}
|
||||
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
if (mIsSnackbarShown && event.action == MotionEvent.ACTION_MOVE) {
|
||||
deleteDirs()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -385,7 +385,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||
|
||||
scanFiles(invalidFiles) {}
|
||||
Medium.sorting = mConfig.sorting
|
||||
Collections.sort(media)
|
||||
media.sort()
|
||||
var j = 0
|
||||
for (medium in media) {
|
||||
if (medium.path == mPath) {
|
||||
|
||||
@@ -1,73 +1,256 @@
|
||||
package com.simplemobiletools.gallery.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.os.Build
|
||||
import android.support.v7.view.ActionMode
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.*
|
||||
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
|
||||
import com.bignerdranch.android.multiselector.MultiSelector
|
||||
import com.bignerdranch.android.multiselector.SwappingHolder
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.signature.StringSignature
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask
|
||||
import com.simplemobiletools.filepicker.extensions.isAStorageRootFolder
|
||||
import com.simplemobiletools.filepicker.extensions.scanPaths
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import com.simplemobiletools.fileproperties.dialogs.PropertiesDialog
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import com.simplemobiletools.gallery.dialogs.CopyDialog
|
||||
import com.simplemobiletools.gallery.dialogs.RenameDirectoryDialog
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.directory_item.view.*
|
||||
import kotlinx.android.synthetic.main.directory_tmb.view.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class DirectoryAdapter(private val mContext: Context, private val mDirs: MutableList<Directory>) : BaseAdapter() {
|
||||
private val mInflater: LayoutInflater
|
||||
class DirectoryAdapter(val activity: SimpleActivity, val dirs: MutableList<Directory>, val listener: DirOperationsListener?, val itemClick: (Directory) -> Unit) :
|
||||
RecyclerView.Adapter<DirectoryAdapter.ViewHolder>() {
|
||||
|
||||
init {
|
||||
mInflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
val multiSelector = MultiSelector()
|
||||
val views = ArrayList<View>()
|
||||
val config = Config.newInstance(activity)
|
||||
|
||||
companion object {
|
||||
var actMode: ActionMode? = null
|
||||
|
||||
fun toggleItemSelection(itemView: View, select: Boolean) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
|
||||
itemView.dir_frame.isActivated = select
|
||||
else
|
||||
itemView.dir_thumbnail.isActivated = select
|
||||
}
|
||||
}
|
||||
|
||||
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
|
||||
var convertView = view
|
||||
val viewHolder: ViewHolder
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.directory_item, parent, false)
|
||||
viewHolder = ViewHolder(convertView)
|
||||
convertView!!.tag = viewHolder
|
||||
} else {
|
||||
viewHolder = convertView.tag as ViewHolder
|
||||
val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.cab_properties -> {
|
||||
showProperties()
|
||||
true
|
||||
}
|
||||
R.id.cab_edit -> {
|
||||
editDir()
|
||||
true
|
||||
}
|
||||
R.id.cab_hide -> {
|
||||
hideDirs()
|
||||
mode.finish()
|
||||
true
|
||||
}
|
||||
R.id.cab_unhide -> {
|
||||
unhideDir()
|
||||
mode.finish()
|
||||
true
|
||||
}
|
||||
R.id.cab_copy_move -> {
|
||||
displayCopyDialog()
|
||||
true
|
||||
}
|
||||
R.id.cab_delete -> {
|
||||
prepareForDeleting()
|
||||
mode.finish()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
val dir = mDirs[position]
|
||||
viewHolder.dirName.text = formatDirectoryName(dir)
|
||||
viewHolder.photoCnt.text = dir.mediaCnt.toString()
|
||||
val tmb = dir.thumbnail
|
||||
val timestampSignature = StringSignature(dir.timestamp.toString())
|
||||
if (tmb.endsWith(".gif")) {
|
||||
Glide.with(mContext).load(tmb).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(viewHolder.dirThumbnail)
|
||||
} else {
|
||||
Glide.with(mContext).load(tmb).diskCacheStrategy(DiskCacheStrategy.RESULT).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(viewHolder.dirThumbnail)
|
||||
override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean {
|
||||
super.onCreateActionMode(actionMode, menu)
|
||||
actMode = actionMode
|
||||
activity.menuInflater.inflate(R.menu.cab_directories, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
return convertView
|
||||
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
|
||||
val menuItem = menu.findItem(R.id.cab_edit)
|
||||
menuItem.isVisible = multiSelector.selectedPositions.size <= 1
|
||||
|
||||
var hiddenCnt = 0
|
||||
var unhiddenCnt = 0
|
||||
val positions = multiSelector.selectedPositions
|
||||
for (i in positions) {
|
||||
val path = dirs[i].path
|
||||
if (config.getIsFolderHidden(path))
|
||||
hiddenCnt++
|
||||
else
|
||||
unhiddenCnt++
|
||||
}
|
||||
|
||||
menu.findItem(R.id.cab_hide).isVisible = unhiddenCnt > 0
|
||||
menu.findItem(R.id.cab_unhide).isVisible = hiddenCnt > 0
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(actionMode: ActionMode?) {
|
||||
super.onDestroyActionMode(actionMode)
|
||||
views.forEach { toggleItemSelection(it, false) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDirectoryName(dir: Directory): String {
|
||||
return dir.name
|
||||
private fun showProperties() {
|
||||
val selections = multiSelector.selectedPositions
|
||||
if (selections.size <= 1) {
|
||||
PropertiesDialog(activity, dirs[selections[0]].path, config.showHiddenFolders)
|
||||
} else {
|
||||
val paths = ArrayList<String>()
|
||||
selections.forEach { paths.add(dirs[it].path) }
|
||||
PropertiesDialog(activity, paths, config.showHiddenFolders)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return mDirs.size
|
||||
private fun editDir() {
|
||||
val path = dirs[multiSelector.selectedPositions[0]].path
|
||||
val dir = File(path)
|
||||
if (activity.isAStorageRootFolder(dir.absolutePath)) {
|
||||
activity.toast(R.string.rename_folder_root)
|
||||
return
|
||||
}
|
||||
|
||||
RenameDirectoryDialog(activity, dir, object : RenameDirectoryDialog.OnRenameDirListener {
|
||||
override fun onRenameDirSuccess(changedPaths: ArrayList<String>) {
|
||||
activity.scanPaths(changedPaths) {
|
||||
activity.runOnUiThread {
|
||||
actMode?.finish()
|
||||
listener?.refreshItems()
|
||||
activity.toast(R.string.rename_folder_ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return mDirs[position]
|
||||
private fun hideDirs() {
|
||||
config.addHiddenDirectories(getSelectedPaths())
|
||||
listener?.refreshItems()
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return 0
|
||||
private fun unhideDir() {
|
||||
config.removeHiddenDirectories(getSelectedPaths())
|
||||
listener?.refreshItems()
|
||||
}
|
||||
|
||||
internal class ViewHolder(view: View) {
|
||||
val dirName: TextView = view.dir_name
|
||||
val photoCnt: TextView = view.photo_cnt
|
||||
val dirThumbnail: ImageView = view.dir_thumbnail
|
||||
private fun displayCopyDialog() {
|
||||
val files = ArrayList<File>()
|
||||
val positions = multiSelector.selectedPositions
|
||||
positions.forEach { files.add(File(dirs[it].path)) }
|
||||
|
||||
CopyDialog(activity, files, object : CopyMoveTask.CopyMoveListener {
|
||||
override fun copySucceeded(deleted: Boolean, copiedAll: Boolean) {
|
||||
if (deleted) {
|
||||
activity.toast(if (copiedAll) R.string.moving_success else R.string.moving_success_partial)
|
||||
} else {
|
||||
activity.toast(if (copiedAll) R.string.copying_success else R.string.copying_success_partial)
|
||||
}
|
||||
listener?.refreshItems()
|
||||
actMode?.finish()
|
||||
}
|
||||
|
||||
override fun copyFailed() {
|
||||
activity.toast(R.string.copy_move_failed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun prepareForDeleting() {
|
||||
val selections = multiSelector.selectedPositions
|
||||
val paths = ArrayList<String>()
|
||||
selections.forEach { paths.add(dirs[it].path.toLowerCase()) }
|
||||
listener?.prepareForDeleting(paths)
|
||||
}
|
||||
|
||||
private fun getSelectedPaths(): HashSet<String> {
|
||||
val positions = multiSelector.selectedPositions
|
||||
val paths = HashSet<String>()
|
||||
positions.forEach { paths.add(dirs[it].path) }
|
||||
return paths
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
views.add(holder.bindView(activity, multiSelectorMode, multiSelector, dirs[position]))
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent?.context).inflate(R.layout.directory_item, parent, false)
|
||||
return ViewHolder(view, itemClick)
|
||||
}
|
||||
|
||||
override fun getItemCount() = dirs.size
|
||||
|
||||
class ViewHolder(view: View, val itemClick: (Directory) -> (Unit)) : SwappingHolder(view, MultiSelector()) {
|
||||
fun bindView(activity: SimpleActivity, multiSelectorCallback: ModalMultiSelectorCallback, multiSelector: MultiSelector, directory: Directory): View {
|
||||
itemView.dir_name.text = directory.name
|
||||
itemView.photo_cnt.text = directory.mediaCnt.toString()
|
||||
|
||||
val tmb = directory.thumbnail
|
||||
val timestampSignature = StringSignature(directory.timestamp.toString())
|
||||
if (tmb.endsWith(".gif")) {
|
||||
Glide.with(activity.applicationContext).load(tmb).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(itemView.dir_thumbnail)
|
||||
} else {
|
||||
Glide.with(activity.applicationContext).load(tmb).diskCacheStrategy(DiskCacheStrategy.RESULT).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(itemView.dir_thumbnail)
|
||||
}
|
||||
|
||||
itemView.setOnClickListener { viewClicked(multiSelector, directory) }
|
||||
itemView.setOnLongClickListener {
|
||||
if (!multiSelector.isSelectable) {
|
||||
activity.startSupportActionMode(multiSelectorCallback)
|
||||
multiSelector.setSelected(this, true)
|
||||
actMode?.title = multiSelector.selectedPositions.size.toString()
|
||||
toggleItemSelection(itemView, true)
|
||||
actMode?.invalidate()
|
||||
}
|
||||
true
|
||||
}
|
||||
return itemView
|
||||
}
|
||||
|
||||
fun viewClicked(multiSelector: MultiSelector, directory: Directory) {
|
||||
if (multiSelector.isSelectable) {
|
||||
val isSelected = multiSelector.selectedPositions.contains(layoutPosition)
|
||||
multiSelector.setSelected(this, !isSelected)
|
||||
toggleItemSelection(itemView, !isSelected)
|
||||
|
||||
val selectedCnt = multiSelector.selectedPositions.size
|
||||
if (selectedCnt == 0) {
|
||||
actMode?.finish()
|
||||
} else {
|
||||
actMode?.title = selectedCnt.toString()
|
||||
}
|
||||
actMode?.invalidate()
|
||||
} else {
|
||||
itemClick(directory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface DirOperationsListener {
|
||||
fun refreshItems()
|
||||
|
||||
fun prepareForDeleting(paths: ArrayList<String>)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class GetDirectoriesAsynctask(val context: Context, val isPickVideo: Boolean, va
|
||||
val file = File(fullPath)
|
||||
val parentDir = file.parent
|
||||
|
||||
if (!file.exists()) {
|
||||
if (!file.exists() || file.length() == 0L) {
|
||||
invalidFiles.add(file)
|
||||
continue
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class GetDirectoriesAsynctask(val context: Context, val isPickVideo: Boolean, va
|
||||
val dirs = ArrayList(directories.values)
|
||||
filterDirectories(dirs)
|
||||
Directory.sorting = mConfig.directorySorting
|
||||
Collections.sort<Directory>(dirs)
|
||||
dirs.sort()
|
||||
|
||||
context.scanFiles(invalidFiles) {}
|
||||
return dirs
|
||||
@@ -111,12 +111,7 @@ class GetDirectoriesAsynctask(val context: Context, val isPickVideo: Boolean, va
|
||||
|
||||
private fun removeHiddenFolders(dirs: MutableList<Directory>) {
|
||||
val hiddenDirs = mConfig.hiddenFolders
|
||||
val ignoreDirs = ArrayList<Directory>()
|
||||
for (dir in dirs) {
|
||||
if (hiddenDirs.contains(dir.path))
|
||||
ignoreDirs.add(dir)
|
||||
}
|
||||
|
||||
val ignoreDirs = dirs.filter { hiddenDirs.contains(it.path) }
|
||||
dirs.removeAll(ignoreDirs)
|
||||
}
|
||||
|
||||
@@ -126,8 +121,7 @@ class GetDirectoriesAsynctask(val context: Context, val isPickVideo: Boolean, va
|
||||
val dir = File(d.path)
|
||||
if (dir.exists() && dir.isDirectory) {
|
||||
val res = dir.list { file, filename -> filename == ".nomedia" }
|
||||
|
||||
if (res != null && res.size > 0)
|
||||
if (res?.isNotEmpty() == true)
|
||||
ignoreDirs.add(d)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,23 @@ import java.util.*
|
||||
class CopyDialog(val activity: SimpleActivity, val files: ArrayList<File>, val copyMoveListener: CopyMoveTask.CopyMoveListener) {
|
||||
|
||||
init {
|
||||
val context = activity
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_copy_move, null)
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.dialog_copy_move, null)
|
||||
val sourcePath = files[0].parent.trimEnd('/')
|
||||
var destinationPath = ""
|
||||
|
||||
view.source.text = context.humanizePath(sourcePath)
|
||||
view.source.text = activity.humanizePath(sourcePath)
|
||||
|
||||
view.destination.setOnClickListener {
|
||||
PickAlbumDialog(activity, object : PickAlbumDialog.OnPickAlbumListener {
|
||||
override fun onSuccess(path: String) {
|
||||
destinationPath = path
|
||||
view.destination.text = context.humanizePath(path)
|
||||
view.destination.text = activity.humanizePath(path)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(if (files.size == 1) R.string.copy_item else R.string.copy_items))
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(activity.resources.getString(if (files.size == 1) R.string.copy_item else R.string.copy_items))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
|
||||
@@ -1,52 +1,41 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.GridView
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import com.simplemobiletools.gallery.adapters.DirectoryAdapter
|
||||
import com.simplemobiletools.gallery.asynctasks.GetDirectoriesAsynctask
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.activity_main.view.*
|
||||
import kotlinx.android.synthetic.main.dialog_album_picker.view.*
|
||||
import java.util.*
|
||||
|
||||
class PickAlbumDialog(val activity: Activity, val listener: OnPickAlbumListener) : AdapterView.OnItemClickListener, GetDirectoriesAsynctask.GetDirectoriesListener {
|
||||
val context = activity.applicationContext
|
||||
var grid: GridView? = null
|
||||
var dirs = ArrayList<Directory>()
|
||||
var dialog: AlertDialog? = null
|
||||
class PickAlbumDialog(val activity: SimpleActivity, val listener: OnPickAlbumListener) : GetDirectoriesAsynctask.GetDirectoriesListener {
|
||||
var dialog: AlertDialog
|
||||
var directoriesGrid: RecyclerView
|
||||
|
||||
init {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_album_picker, null)
|
||||
grid = view.directories_grid
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.dialog_album_picker, null)
|
||||
directoriesGrid = view.directories_grid
|
||||
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.setTitle(context.resources.getString(R.string.select_destination))
|
||||
.setTitle(activity.resources.getString(R.string.select_destination))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
show()
|
||||
}
|
||||
.create()
|
||||
|
||||
GetDirectoriesAsynctask(context, false, false, ArrayList<String>(), this).execute()
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
listener.onSuccess(dirs[position].path)
|
||||
dialog?.dismiss()
|
||||
dialog.show()
|
||||
GetDirectoriesAsynctask(activity, false, false, ArrayList<String>(), this).execute()
|
||||
}
|
||||
|
||||
override fun gotDirectories(dirs: ArrayList<Directory>) {
|
||||
this.dirs = dirs
|
||||
|
||||
val adapter = DirectoryAdapter(context, dirs)
|
||||
|
||||
grid?.adapter = adapter
|
||||
grid?.onItemClickListener = this
|
||||
val adapter = DirectoryAdapter(activity, dirs, null) {
|
||||
listener.onSuccess(it.path)
|
||||
dialog.dismiss()
|
||||
}
|
||||
directoriesGrid.adapter = adapter
|
||||
}
|
||||
|
||||
interface OnPickAlbumListener {
|
||||
|
||||
@@ -12,16 +12,14 @@ import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class RenameDirectoryDialog(val activity: SimpleActivity, val dir: File, val listener: OnRenameDirListener) {
|
||||
val context = activity
|
||||
|
||||
init {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.rename_directory, null)
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.rename_directory, null)
|
||||
|
||||
view.directory_name.setText(dir.name)
|
||||
view.directory_path.text = "${context.humanizePath(dir.parent)}/"
|
||||
view.directory_path.text = "${activity.humanizePath(dir.parent)}/"
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.rename_folder))
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(activity.resources.getString(R.string.rename_folder))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
@@ -30,12 +28,16 @@ class RenameDirectoryDialog(val activity: SimpleActivity, val dir: File, val lis
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener({
|
||||
val newDirName = view.directory_name.value
|
||||
|
||||
if (newDirName.isEmpty()) {
|
||||
context.toast(R.string.rename_folder_empty)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (!newDirName.isAValidFilename()) {
|
||||
context.toast(R.string.invalid_name)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val updatedFiles = ArrayList<String>()
|
||||
updatedFiles.add(dir.absolutePath)
|
||||
val newDir = File(dir.parent, newDirName)
|
||||
@@ -65,18 +67,15 @@ class RenameDirectoryDialog(val activity: SimpleActivity, val dir: File, val lis
|
||||
}
|
||||
|
||||
private fun sendSuccess(updatedFiles: ArrayList<String>, newDir: File) {
|
||||
context.toast(R.string.renaming_folder)
|
||||
activity.toast(R.string.renaming_folder)
|
||||
val files = newDir.listFiles()
|
||||
for (file in files) {
|
||||
updatedFiles.add(file.absolutePath)
|
||||
}
|
||||
files.mapTo(updatedFiles) { it.absolutePath }
|
||||
|
||||
updatedFiles.add(newDir.absolutePath)
|
||||
val changedFiles = updatedFiles.toTypedArray()
|
||||
listener.onRenameDirSuccess(changedFiles)
|
||||
listener.onRenameDirSuccess(updatedFiles)
|
||||
}
|
||||
|
||||
interface OnRenameDirListener {
|
||||
fun onRenameDirSuccess(changedFiles: Array<String>)
|
||||
fun onRenameDirSuccess(changedPaths: ArrayList<String>)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,7 @@ import java.io.File
|
||||
class RenameFileDialog(val activity: SimpleActivity, val file: File, val listener: OnRenameFileListener) {
|
||||
|
||||
init {
|
||||
val context = activity
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.rename_file, null)
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.rename_file, null)
|
||||
val fullName = file.name
|
||||
val dotAt = fullName.lastIndexOf(".")
|
||||
var name = fullName
|
||||
@@ -26,10 +25,10 @@ class RenameFileDialog(val activity: SimpleActivity, val file: File, val listene
|
||||
}
|
||||
|
||||
view.file_name.setText(name)
|
||||
view.file_path.text = "${context.humanizePath(file.parent)}/"
|
||||
view.file_path.text = "${activity.humanizePath(file.parent)}/"
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.rename_file))
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(activity.resources.getString(R.string.rename_file))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
@@ -45,6 +44,11 @@ class RenameFileDialog(val activity: SimpleActivity, val file: File, val listene
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (!fileName.isAValidFilename()) {
|
||||
context.toast(R.string.invalid_name)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val newFile = File(file.parent, "$fileName.$extension")
|
||||
|
||||
if (context.needsStupidWritePermissions(file.absolutePath)) {
|
||||
|
||||
@@ -14,12 +14,11 @@ import kotlinx.android.synthetic.main.rename_file.view.*
|
||||
class SaveAsDialog(val activity: Activity, val path: String, val listener: OnSaveAsListener) {
|
||||
|
||||
init {
|
||||
val context = activity
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_save_as, null)
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.dialog_save_as, null)
|
||||
view.file_name.setText(path.getFilenameFromPath())
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.save_as))
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(activity.resources.getString(R.string.save_as))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
|
||||
@@ -12,7 +12,7 @@ class Directory(val path: String, val thumbnail: String, val name: String, var m
|
||||
override fun compareTo(other: Directory): Int {
|
||||
var res: Int
|
||||
if (sorting and SORT_BY_NAME != 0) {
|
||||
res = path.compareTo(other.path)
|
||||
res = name.toLowerCase().compareTo(other.name.toLowerCase())
|
||||
} else if (sorting and SORT_BY_DATE != 0) {
|
||||
res = if (timestamp > other.timestamp) 1 else -1
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@ class Medium(val name: String, var path: String, val isVideo: Boolean, val times
|
||||
override fun compareTo(other: Medium): Int {
|
||||
var res: Int
|
||||
if (sorting and SORT_BY_NAME != 0) {
|
||||
res = path.compareTo(other.path)
|
||||
res = name.toLowerCase().compareTo(other.name.toLowerCase())
|
||||
} else if (sorting and SORT_BY_DATE != 0) {
|
||||
res = if (timestamp > other.timestamp) 1 else -1
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.gallery.views.MyImageView
|
||||
android:id="@+id/dir_thumbnail"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dir_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="@drawable/selector"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
android:id="@+id/about_scrollview"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/about_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
@@ -12,6 +12,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<TextView
|
||||
@@ -89,6 +90,8 @@
|
||||
android:layout_height="@dimen/social_logo"
|
||||
android:layout_below="@+id/about_follow_us"
|
||||
android:layout_marginLeft="@dimen/social_padding"
|
||||
android:layout_marginRight="@dimen/social_padding"
|
||||
android:layout_toEndOf="@+id/about_facebook"
|
||||
android:layout_toRightOf="@+id/about_facebook"
|
||||
android:src="@mipmap/gplus"/>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -10,15 +11,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<GridView
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/directories_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnWidth="@dimen/dir_tmb_size"
|
||||
android:horizontalSpacing="1dp"
|
||||
android:numColumns="auto_fit"
|
||||
android:stretchMode="columnWidth"
|
||||
android:verticalSpacing="1dp"/>
|
||||
app:layoutManager="android.support.v7.widget.GridLayoutManager"
|
||||
app:spanCount="@integer/columns"/>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<GridView
|
||||
<android.support.v7.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/directories_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnWidth="@dimen/dir_tmb_size"
|
||||
android:horizontalSpacing="1dp"
|
||||
android:numColumns="auto_fit"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:stretchMode="columnWidth"
|
||||
android:verticalSpacing="1dp"/>
|
||||
app:layoutManager="android.support.v7.widget.GridLayoutManager"
|
||||
app:spanCount="@integer/columns"/>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dir_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="1px">
|
||||
|
||||
<include layout="@layout/directory_tmb"/>
|
||||
|
||||
@@ -23,6 +24,7 @@
|
||||
android:id="@+id/dir_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/photo_cnt"
|
||||
android:paddingBottom="@dimen/small_padding"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
@@ -30,7 +32,7 @@
|
||||
android:id="@+id/photo_cnt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/dir_name"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">Der Name enthält nicht erlaubte Zeichen</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 Ordner gelöscht</item>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">The name contains invalid characters</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 carpeta eliminada</item>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">Il nome contiene caratteri non validi</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 cartella eliminata</item>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">名前に無効な文字が含まれています</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 フォルダーを削除しました</item>
|
||||
|
||||
3
app/src/main/res/values-land/integers.xml
Normal file
3
app/src/main/res/values-land/integers.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<integer name="columns">4</integer>
|
||||
</resources>
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">Já existe um ficheiro com este nome</string>
|
||||
<string name="moving_success_partial">Alguns ficheiros não foram movidos</string>
|
||||
<string name="copying_success_partial">Alguns ficheiros não foram copiados</string>
|
||||
<string name="invalid_name">O nome contém caracteres inválidos</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 pasta apagada</item>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">Namnet innehåller ogiltiga tecken</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 mapp borttagen</item>
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<string name="already_exists">相同的文件名已经存在</string>
|
||||
<string name="moving_success_partial">相同文件不能移动</string>
|
||||
<string name="copying_success_partial">相同文件不能复制</string>
|
||||
<string name="invalid_name">The name contains invalid characters</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 folder deleted</item>
|
||||
|
||||
3
app/src/main/res/values/integers.xml
Normal file
3
app/src/main/res/values/integers.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<integer name="columns">2</integer>
|
||||
</resources>
|
||||
@@ -60,6 +60,7 @@
|
||||
<string name="already_exists">A file with that name already exists</string>
|
||||
<string name="moving_success_partial">Some files could not be moved</string>
|
||||
<string name="copying_success_partial">Some files could not be copied</string>
|
||||
<string name="invalid_name">The name contains invalid characters</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 folder deleted</item>
|
||||
|
||||
Reference in New Issue
Block a user