Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c480dd23ff | ||
|
|
101b717d71 | ||
|
|
04e3ea1fb2 | ||
|
|
511fc5e420 | ||
|
|
e013cc02a4 | ||
|
|
9b8420e9d1 | ||
|
|
09231c516c | ||
|
|
4d324e491e | ||
|
|
856913520a | ||
|
|
c6779c8047 | ||
|
|
57836b229d | ||
|
|
d2a8aca830 | ||
|
|
6b268a1c07 | ||
|
|
9e15c5e38d | ||
|
|
921eb4750c | ||
|
|
83be878d50 | ||
|
|
5e9cc0bea8 | ||
|
|
3c0b8bb845 | ||
|
|
7d9a08d2fe | ||
|
|
eb218f6fa6 | ||
|
|
8ccb0385ca | ||
|
|
493ba31c5f | ||
|
|
719c510f59 | ||
|
|
7ced072f9c | ||
|
|
cec3e5f640 | ||
|
|
a6bca1ae88 | ||
|
|
afb722ab24 | ||
|
|
4f21221698 | ||
|
|
c8b927e7e1 | ||
|
|
2465e7ae62 | ||
|
|
d2546e1a3e | ||
|
|
34d015734e | ||
|
|
f548ed833a | ||
|
|
7c3ad32dee | ||
|
|
cf67f52ea2 | ||
|
|
84613885ef | ||
|
|
a5deb81e58 | ||
|
|
807add5579 | ||
|
|
36aaf03541 | ||
|
|
d4855573c9 | ||
|
|
93b8281cfb | ||
|
|
df5b90319f | ||
|
|
75beef4da6 | ||
|
|
c4edf3c28e | ||
|
|
bf94d8172c | ||
|
|
9e5936b8a0 | ||
|
|
42be5de0cb | ||
|
|
e3cc1b91cc | ||
|
|
cb734d7c10 | ||
|
|
737d2f2a9c | ||
|
|
293f77afe0 | ||
|
|
4b12949a73 | ||
|
|
48f5a33f90 | ||
|
|
0959403628 | ||
|
|
d4c75c2107 | ||
|
|
af3d247b7f | ||
|
|
805f726022 | ||
|
|
4e9dc8e85f | ||
|
|
534ff0ab7d | ||
|
|
d80a1bd185 | ||
|
|
3e2cfe90bc | ||
|
|
8f85b5da2f | ||
|
|
c609072eaf | ||
|
|
401569043a | ||
|
|
d6dd6210c7 | ||
|
|
93d4353d42 | ||
|
|
6f2ef95b40 | ||
|
|
1710590639 | ||
|
|
a971b215a5 | ||
|
|
dfae308cc7 | ||
|
|
8108a109dc | ||
|
|
03acb74ba3 | ||
|
|
855daa4675 | ||
|
|
fa4c6928bd | ||
|
|
3323ff7157 | ||
|
|
96b25a43b8 | ||
|
|
267317c7c2 | ||
|
|
fa14b43e3e | ||
|
|
beba22b764 | ||
|
|
c176959305 | ||
|
|
8487ef44c4 | ||
|
|
d7ffc35dd0 | ||
|
|
d6fd4ad378 | ||
|
|
2c7d62c863 | ||
|
|
3804f3d8f4 | ||
|
|
9b809790f9 | ||
|
|
c6598528fd | ||
|
|
fbe1409862 | ||
|
|
10e197af95 | ||
|
|
1eb125e36d | ||
|
|
ac7757c76e | ||
|
|
f25ae4f1b7 | ||
|
|
57048d3956 | ||
|
|
f2e13e9cb3 | ||
|
|
1e1d0f8dc7 | ||
|
|
bebc8f808f | ||
|
|
4c50b5bc0e | ||
|
|
5cb0bb904f | ||
|
|
90d704cff4 | ||
|
|
a31533418d | ||
|
|
a5da407ed3 | ||
|
|
c7408fb9fe | ||
|
|
fc8f8c3fa7 | ||
|
|
0ade1ec579 | ||
|
|
6c9c072dc9 | ||
|
|
c71f94d9ec | ||
|
|
fb59224405 | ||
|
|
dd983c9753 | ||
|
|
84f81ed3e2 | ||
|
|
a70e99da34 | ||
|
|
7ba442e32e | ||
|
|
251ccd8078 | ||
|
|
32fe796d66 | ||
|
|
3ec6bd3a94 | ||
|
|
4f74709774 | ||
|
|
165cff24e6 | ||
|
|
122209fb28 | ||
|
|
def05ffbe2 | ||
|
|
d60521411e | ||
|
|
f0e8746bce | ||
|
|
3f756369f2 | ||
|
|
657b14fdb4 | ||
|
|
001bf403d1 | ||
|
|
4153a73139 | ||
|
|
9a58d3fedb | ||
|
|
a5fc444ba3 | ||
|
|
b3fa4bf880 | ||
|
|
97d6f2d452 | ||
|
|
60536bfdf6 | ||
|
|
db2b1fedb3 | ||
|
|
0889aa76d7 | ||
|
|
871e6d9cf1 | ||
|
|
2f9c63e43b | ||
|
|
9081d1a579 | ||
|
|
4f289b4c47 | ||
|
|
6e0f60b770 | ||
|
|
37bda0c72e | ||
|
|
07b60e0afb | ||
|
|
def5c9ce2a | ||
|
|
97cc6f4a62 | ||
|
|
fe6b65d407 | ||
|
|
b240ea6692 | ||
|
|
d643cc2822 | ||
|
|
34158c217c |
55
CHANGELOG.md
@@ -1,6 +1,61 @@
|
||||
Changelog
|
||||
==========
|
||||
|
||||
Version 1.32 *(2016-11-13)*
|
||||
----------------------------
|
||||
|
||||
* Added Chinese translation
|
||||
* Couple small bugfixes
|
||||
|
||||
Version 1.31 *(2016-11-12)*
|
||||
----------------------------
|
||||
|
||||
* Add a Move function
|
||||
* Many small improvements, mostly related to Copy/Move
|
||||
|
||||
Version 1.30 *(2016-11-10)*
|
||||
----------------------------
|
||||
|
||||
* Some improvements to the Copy function
|
||||
* Allow displaying filenames at the thumbnail view
|
||||
* Changing the bottom shadow to gradient
|
||||
|
||||
Version 1.29 *(2016-11-09)*
|
||||
----------------------------
|
||||
|
||||
* Adding an initial implementation of the Copy feature
|
||||
* Sort items by date_modified instead of date_taken
|
||||
* Make "Save as" the only saving option in the editor
|
||||
* Autoplay videos only if selected so
|
||||
|
||||
Version 1.28 *(2016-11-07)*
|
||||
----------------------------
|
||||
|
||||
* Couple file operation fixes on devices without SD card
|
||||
* Set the default folder sorting by Date, descending
|
||||
* Couple Spanish string corrections
|
||||
|
||||
Version 1.27 *(2016-11-06)*
|
||||
----------------------------
|
||||
|
||||
* Add a "Save as" option to the editor
|
||||
* Fix file operations on SD card
|
||||
* Do not delete folders recursively, just the direct children
|
||||
* Many other small improvements
|
||||
|
||||
Version 1.26 *(2016-11-03)*
|
||||
----------------------------
|
||||
|
||||
* Add a menu item for Properties
|
||||
|
||||
Version 1.25 *(2016-10-25)*
|
||||
----------------------------
|
||||
|
||||
* Change the light themes window backgrounds to white
|
||||
* Change the default theme to dark
|
||||
* Add an option for autoplaying videos
|
||||
* Misc performance improvements
|
||||
|
||||
Version 1.24 *(2016-10-09)*
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -3,18 +3,20 @@
|
||||
|
||||
A gallery for viewing photos and videos.
|
||||
|
||||
A simple tool usable for viewing photos and videos. Items can be sorted by date, size, name both ascending or descending, photos can be zoomed in. Media files are shown in multiple columns, depending on the size of the display. They can be renamed, shared or deleted. Images can also be cropped, rotated or set as Wallpaper directly from the app.
|
||||
A simple tool usable for viewing photos and videos. Items can be sorted by date, size, name both ascending or descending, photos can be zoomed in. Media files are shown in multiple columns, depending on the size of the display. They can be renamed, shared, deleted, copied, moved. Images can also be cropped, rotated or set as Wallpaper directly from the app.
|
||||
|
||||
The Gallery is also offered for third party usage for previewing images / videos, adding attachments at email clients etc. It's perfect for everyday usage.
|
||||
|
||||
Contains no ads or unnecessary permissions. It is fully opensource, provides a Dark theme too.
|
||||
|
||||
This app is just one piece of a bigger series of apps. You can find the rest of them at http://www.simplemobiletools.com
|
||||
|
||||
<a href='https://play.google.com/store/apps/details?id=com.simplemobiletools.gallery'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height=60/></a>
|
||||
<a href="https://f-droid.org/app/com.simplemobiletools.gallery"><img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="60"></a>
|
||||
|
||||
<img alt="App image" src="screenshots/app.jpg" width="250">
|
||||
<img alt="App image" src="screenshots/app_2.jpg" width="250">
|
||||
<img alt="App image" src="screenshots/app_3.jpg" width="250">
|
||||
<img alt="App image" src="screenshots/app_5.jpg" width="250">
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.simplemobiletools.gallery"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 23
|
||||
versionCode 24
|
||||
versionName "1.24"
|
||||
versionCode 32
|
||||
versionName "1.32"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -27,6 +27,10 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/library-compileDebugKotlin.kotlin_module'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
@@ -42,15 +46,13 @@ dependencies {
|
||||
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.5.0'
|
||||
compile 'com.theartofdev.edmodo:android-image-cropper:2.3.1'
|
||||
compile 'com.booking:rtlviewpager:1.0.1'
|
||||
compile 'com.simplemobiletools:fileproperties:1.0.3@aar'
|
||||
compile 'com.simplemobiletools:filepicker:1.3.20@aar'
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
|
||||
apt 'com.jakewharton:butterknife-compiler:8.0.1'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.0.3'
|
||||
repositories {
|
||||
|
||||
2
app/proguard-rules.pro
vendored
@@ -15,3 +15,5 @@
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
-keep class com.simplemobiletools.** { *; }
|
||||
-dontwarn com.simplemobiletools.**
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.simplemobiletools.gallery;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Config {
|
||||
private SharedPreferences mPrefs;
|
||||
|
||||
public static Config newInstance(Context context) {
|
||||
return new Config(context);
|
||||
}
|
||||
|
||||
private Config(Context context) {
|
||||
mPrefs = context.getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public boolean getIsFirstRun() {
|
||||
return mPrefs.getBoolean(Constants.IS_FIRST_RUN, true);
|
||||
}
|
||||
|
||||
public void setIsFirstRun(boolean firstRun) {
|
||||
mPrefs.edit().putBoolean(Constants.IS_FIRST_RUN, firstRun).apply();
|
||||
}
|
||||
|
||||
public boolean getIsDarkTheme() {
|
||||
return mPrefs.getBoolean(Constants.IS_DARK_THEME, false);
|
||||
}
|
||||
|
||||
public void setIsDarkTheme(boolean isDarkTheme) {
|
||||
mPrefs.edit().putBoolean(Constants.IS_DARK_THEME, isDarkTheme).apply();
|
||||
}
|
||||
|
||||
public boolean getIsSameSorting() {
|
||||
return mPrefs.getBoolean(Constants.IS_SAME_SORTING, true);
|
||||
}
|
||||
|
||||
public void setIsSameSorting(boolean isSameSorting) {
|
||||
mPrefs.edit().putBoolean(Constants.IS_SAME_SORTING, isSameSorting).apply();
|
||||
}
|
||||
|
||||
public int getSorting() {
|
||||
if (getIsSameSorting())
|
||||
return getDirectorySorting();
|
||||
|
||||
return mPrefs.getInt(Constants.SORT_ORDER, Constants.SORT_BY_DATE | Constants.SORT_DESCENDING);
|
||||
}
|
||||
|
||||
public void setSorting(int order) {
|
||||
if (getIsSameSorting())
|
||||
setDirectorySorting(order);
|
||||
else
|
||||
mPrefs.edit().putInt(Constants.SORT_ORDER, order).apply();
|
||||
}
|
||||
|
||||
public int getDirectorySorting() {
|
||||
return mPrefs.getInt(Constants.DIRECTORY_SORT_ORDER, Constants.SORT_BY_NAME);
|
||||
}
|
||||
|
||||
public void setDirectorySorting(int order) {
|
||||
mPrefs.edit().putInt(Constants.DIRECTORY_SORT_ORDER, order).apply();
|
||||
}
|
||||
|
||||
public boolean getShowHiddenFolders() {
|
||||
return mPrefs.getBoolean(Constants.SHOW_HIDDEN_FOLDERS, false);
|
||||
}
|
||||
|
||||
public void setShowHiddenFolders(boolean showHiddenFolders) {
|
||||
mPrefs.edit().putBoolean(Constants.SHOW_HIDDEN_FOLDERS, showHiddenFolders).apply();
|
||||
}
|
||||
|
||||
public void addHiddenDirectory(String path) {
|
||||
final Set<String> hiddenFolders = getHiddenFolders();
|
||||
hiddenFolders.add(path);
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply();
|
||||
}
|
||||
|
||||
public void addHiddenDirectories(Set<String> paths) {
|
||||
final Set<String> hiddenFolders = getHiddenFolders();
|
||||
hiddenFolders.addAll(paths);
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply();
|
||||
}
|
||||
|
||||
public void removeHiddenDirectory(String path) {
|
||||
final Set<String> hiddenFolders = getHiddenFolders();
|
||||
hiddenFolders.remove(path);
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply();
|
||||
}
|
||||
|
||||
public void removeHiddenDirectories(Set<String> paths) {
|
||||
final Set<String> hiddenFolders = getHiddenFolders();
|
||||
hiddenFolders.removeAll(paths);
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply();
|
||||
}
|
||||
|
||||
public Set<String> getHiddenFolders() {
|
||||
return mPrefs.getStringSet(Constants.HIDDEN_FOLDERS, new HashSet<String>());
|
||||
}
|
||||
|
||||
public boolean getIsFolderHidden(String path) {
|
||||
return getHiddenFolders().contains(path);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public class Constants {
|
||||
public static final String DIRECTORY_SORT_ORDER = "directory_sort_order";
|
||||
public static final String HIDDEN_FOLDERS = "hidden_folders";
|
||||
public static final String SHOW_HIDDEN_FOLDERS = "show_hidden_folders";
|
||||
public static final String AUTOPLAY_VIDEOS = "autoplay_videos";
|
||||
public static final String TREE_URI = "tree_uri";
|
||||
public static final String DISPLAY_FILE_NAMES = "display_file_names";
|
||||
|
||||
// sorting
|
||||
public static final int SORT_BY_NAME = 1;
|
||||
@@ -24,4 +27,7 @@ public class Constants {
|
||||
public static final int SORT_BY_SIZE = 4;
|
||||
|
||||
public static final int SORT_DESCENDING = 1024;
|
||||
|
||||
// global intents
|
||||
public static final int OPEN_DOCUMENT_TREE = 1000;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.simplemobiletools.gallery;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class MyImageView extends ImageView {
|
||||
|
||||
public MyImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MyImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.simplemobiletools.gallery;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.booking.rtlviewpager.RtlViewPager;
|
||||
|
||||
public class MyViewPager extends RtlViewPager {
|
||||
|
||||
public MyViewPager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MyViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
package com.simplemobiletools.gallery;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.Window;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Utils {
|
||||
public static String getFilename(final String path) {
|
||||
return path.substring(path.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
public static void showToast(Context context, int resId) {
|
||||
Toast.makeText(context, context.getResources().getString(resId), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static int getActionBarHeight(Context context, Resources res) {
|
||||
final TypedValue tv = new TypedValue();
|
||||
int height = 0;
|
||||
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
|
||||
height = TypedValue.complexToDimensionPixelSize(tv.data, res.getDisplayMetrics());
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(Resources res) {
|
||||
int id = res.getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (id > 0) {
|
||||
return res.getDimensionPixelSize(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getNavBarHeight(Resources res) {
|
||||
int id = res.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (id > 0) {
|
||||
return res.getDimensionPixelSize(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean hasNavBar(Activity act) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Display display = act.getWindowManager().getDefaultDisplay();
|
||||
|
||||
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
|
||||
display.getRealMetrics(realDisplayMetrics);
|
||||
|
||||
int realHeight = realDisplayMetrics.heightPixels;
|
||||
int realWidth = realDisplayMetrics.widthPixels;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
display.getMetrics(displayMetrics);
|
||||
|
||||
int displayHeight = displayMetrics.heightPixels;
|
||||
int displayWidth = displayMetrics.widthPixels;
|
||||
|
||||
return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
|
||||
} else {
|
||||
boolean hasMenuKey = ViewConfiguration.get(act).hasPermanentMenuKey();
|
||||
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
|
||||
return !hasMenuKey && !hasBackKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasStoragePermission(Context cxt) {
|
||||
return ContextCompat.checkSelfPermission(cxt, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public static String getMimeType(String url) {
|
||||
final String extension = MimeTypeMap.getFileExtensionFromUrl(url);
|
||||
if (extension != null) {
|
||||
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void shareMedium(Medium medium, Activity activity) {
|
||||
final String shareTitle = activity.getResources().getString(R.string.share_via);
|
||||
final Intent intent = new Intent();
|
||||
final File file = new File(medium.getPath());
|
||||
final Uri uri = Uri.fromFile(file);
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.setType(getMimeType(medium));
|
||||
activity.startActivity(Intent.createChooser(intent, shareTitle));
|
||||
}
|
||||
|
||||
public static String getMimeType(Medium medium) {
|
||||
if (medium.getIsVideo())
|
||||
return "video/*";
|
||||
else
|
||||
return "image/*";
|
||||
}
|
||||
|
||||
public static void showSystemUI(ActionBar actionbar, Window window) {
|
||||
if (actionbar != null)
|
||||
actionbar.show();
|
||||
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
public static void hideSystemUI(ActionBar actionbar, Window window) {
|
||||
if (actionbar != null)
|
||||
actionbar.hide();
|
||||
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||
}
|
||||
|
||||
public static String getRealPathFromURI(Context context, Uri uri) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
String[] projection = {MediaStore.Images.Media.DATA};
|
||||
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||
cursor.moveToFirst();
|
||||
return cursor.getString(index);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package com.simplemobiletools.gallery;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Display;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.Window;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ViewServer {
|
||||
public static String getFilename(final String path) {
|
||||
return path.substring(path.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
public static void showToast(Context context, int resId) {
|
||||
Toast.makeText(context, context.getResources().getString(resId), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static int getActionBarHeight(Context context, Resources res) {
|
||||
final TypedValue tv = new TypedValue();
|
||||
int height = 0;
|
||||
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
|
||||
height = TypedValue.complexToDimensionPixelSize(tv.data, res.getDisplayMetrics());
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(Resources res) {
|
||||
int id = res.getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (id > 0) {
|
||||
return res.getDimensionPixelSize(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getNavBarHeight(Resources res) {
|
||||
int id = res.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (id > 0) {
|
||||
return res.getDimensionPixelSize(id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean hasNavBar(Activity act) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Display display = act.getWindowManager().getDefaultDisplay();
|
||||
|
||||
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
|
||||
display.getRealMetrics(realDisplayMetrics);
|
||||
|
||||
int realHeight = realDisplayMetrics.heightPixels;
|
||||
int realWidth = realDisplayMetrics.widthPixels;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
display.getMetrics(displayMetrics);
|
||||
|
||||
int displayHeight = displayMetrics.heightPixels;
|
||||
int displayWidth = displayMetrics.widthPixels;
|
||||
|
||||
return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
|
||||
} else {
|
||||
boolean hasMenuKey = ViewConfiguration.get(act).hasPermanentMenuKey();
|
||||
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
|
||||
return !hasMenuKey && !hasBackKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasStoragePermission(Context cxt) {
|
||||
return ContextCompat.checkSelfPermission(cxt, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public static String getMimeType(String url) {
|
||||
final String extension = MimeTypeMap.getFileExtensionFromUrl(url);
|
||||
if (extension != null) {
|
||||
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void shareMedium(Medium medium, Activity activity) {
|
||||
final String shareTitle = activity.getResources().getString(R.string.share_via);
|
||||
final Intent intent = new Intent();
|
||||
final File file = new File(medium.getPath());
|
||||
final Uri uri = Uri.fromFile(file);
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
intent.setType(getMimeType(medium));
|
||||
activity.startActivity(Intent.createChooser(intent, shareTitle));
|
||||
}
|
||||
|
||||
public static String getMimeType(Medium medium) {
|
||||
if (medium.getIsVideo())
|
||||
return "video/*";
|
||||
else
|
||||
return "image/*";
|
||||
}
|
||||
|
||||
public static void showSystemUI(ActionBar actionbar, Window window) {
|
||||
if (actionbar != null)
|
||||
actionbar.show();
|
||||
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
public static void hideSystemUI(ActionBar actionbar, Window window) {
|
||||
if (actionbar != null)
|
||||
actionbar.hide();
|
||||
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.simplemobiletools.gallery.BuildConfig;
|
||||
import com.simplemobiletools.gallery.Config;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class AboutActivity extends SimpleActivity {
|
||||
@BindView(R.id.about_copyright) TextView mCopyright;
|
||||
@BindView(R.id.about_email) TextView mEmailTV;
|
||||
@BindView(R.id.about_rate_us) View mRateUs;
|
||||
|
||||
private static Resources mRes;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_about);
|
||||
ButterKnife.bind(this);
|
||||
mRes = getResources();
|
||||
|
||||
setupEmail();
|
||||
setupCopyright();
|
||||
setupRateUs();
|
||||
}
|
||||
|
||||
private void setupEmail() {
|
||||
final String email = mRes.getString(R.string.email);
|
||||
final String appName = mRes.getString(R.string.app_name);
|
||||
final String href = "<a href=\"mailto:" + email + "?subject=" + appName + "\">" + email + "</a>";
|
||||
mEmailTV.setText(Html.fromHtml(href));
|
||||
mEmailTV.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
private void setupCopyright() {
|
||||
final String versionName = BuildConfig.VERSION_NAME;
|
||||
final int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
final String copyrightText = String.format(mRes.getString(R.string.copyright), versionName, year);
|
||||
mCopyright.setText(copyrightText);
|
||||
}
|
||||
|
||||
private void setupRateUs() {
|
||||
if (Config.newInstance(getApplicationContext()).getIsFirstRun()) {
|
||||
mRateUs.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.about_invite)
|
||||
public void inviteFriend() {
|
||||
final Intent intent = new Intent();
|
||||
final String text = String.format(getString(R.string.share_text), getString(R.string.app_name), getStoreUrl());
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
|
||||
intent.putExtra(Intent.EXTRA_TEXT, text);
|
||||
intent.setType("text/plain");
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.invite_via)));
|
||||
}
|
||||
|
||||
@OnClick(R.id.about_rate_us)
|
||||
public void rateUsClicked() {
|
||||
final Uri uri = Uri.parse("market://details?id=" + getPackageName());
|
||||
try {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getStoreUrl())));
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.about_license)
|
||||
public void licenseClicked() {
|
||||
final Intent intent = new Intent(getApplicationContext(), LicenseActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@OnClick(R.id.about_facebook)
|
||||
public void facebookClicked() {
|
||||
String link = "https://www.facebook.com/simplemobiletools";
|
||||
try {
|
||||
getPackageManager().getPackageInfo("com.facebook.katana", 0);
|
||||
link = "fb://page/150270895341774";
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
|
||||
}
|
||||
|
||||
@OnClick(R.id.about_gplus)
|
||||
public void googlePlusClicked() {
|
||||
final String link = "https://plus.google.com/communities/104880861558693868382";
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
|
||||
}
|
||||
|
||||
private String getStoreUrl() {
|
||||
return "https://play.google.com/store/apps/details?id=" + getPackageName();
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.simplemobiletools.gallery.R;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class LicenseActivity extends SimpleActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_license);
|
||||
ButterKnife.bind(this);
|
||||
}
|
||||
|
||||
@OnClick(R.id.license_butterknife_title)
|
||||
public void butterKnifeClicked() {
|
||||
openUrl(R.string.butterknife_url);
|
||||
}
|
||||
|
||||
@OnClick(R.id.license_photoview_title)
|
||||
public void photoViewClicked() {
|
||||
openUrl(R.string.photoview_url);
|
||||
}
|
||||
|
||||
@OnClick(R.id.license_glide_title)
|
||||
public void glideClicked() {
|
||||
openUrl(R.string.glide_url);
|
||||
}
|
||||
|
||||
@OnClick(R.id.license_cropper_title)
|
||||
public void cropperClicked() {
|
||||
openUrl(R.string.cropper_url);
|
||||
}
|
||||
|
||||
private void openUrl(int id) {
|
||||
final String url = getResources().getString(id);
|
||||
final Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
startActivity(browserIntent);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
@@ -14,8 +13,8 @@ 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.support.v7.app.AlertDialog;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
@@ -24,26 +23,27 @@ import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.GridView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.simplemobiletools.gallery.Config;
|
||||
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.ChangeSorting;
|
||||
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.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import butterknife.BindView;
|
||||
@@ -51,7 +51,7 @@ import butterknife.ButterKnife;
|
||||
|
||||
public class MainActivity extends SimpleActivity
|
||||
implements AdapterView.OnItemClickListener, GridView.MultiChoiceModeListener, GridView.OnTouchListener,
|
||||
SwipeRefreshLayout.OnRefreshListener, ChangeSorting.ChangeDialogListener {
|
||||
SwipeRefreshLayout.OnRefreshListener, ChangeSorting.ChangeDialogListener, GetDirectoriesAsynctask.GetDirectoriesListener {
|
||||
@BindView(R.id.directories_grid) GridView mGridView;
|
||||
@BindView(R.id.directories_holder) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
@@ -73,6 +73,7 @@ public class MainActivity extends SimpleActivity
|
||||
private static boolean mIsGetAnyContentIntent;
|
||||
private static boolean mIsSetWallpaperIntent;
|
||||
private static boolean mIsThirdPartyIntent;
|
||||
private static boolean mIsGettingDirs;
|
||||
private static int mSelectedItemsCnt;
|
||||
|
||||
@Override
|
||||
@@ -144,14 +145,14 @@ public class MainActivity extends SimpleActivity
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
Config.newInstance(getApplicationContext()).setIsFirstRun(false);
|
||||
mConfig.setFirstRun(false);
|
||||
}
|
||||
|
||||
private void tryloadGallery() {
|
||||
if (Utils.hasStoragePermission(getApplicationContext())) {
|
||||
initializeGallery();
|
||||
if (Utils.Companion.hasStoragePermission(getApplicationContext())) {
|
||||
getDirectories();
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION);
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,139 +162,21 @@ public class MainActivity extends SimpleActivity
|
||||
|
||||
if (requestCode == STORAGE_PERMISSION) {
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
initializeGallery();
|
||||
getDirectories();
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.no_permissions);
|
||||
Utils.Companion.showToast(getApplicationContext(), R.string.no_permissions);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeGallery() {
|
||||
final List<Directory> newDirs = getDirectories();
|
||||
if (newDirs.toString().equals(mDirs.toString())) {
|
||||
private void getDirectories() {
|
||||
if (mIsGettingDirs)
|
||||
return;
|
||||
}
|
||||
mDirs = newDirs;
|
||||
|
||||
final DirectoryAdapter adapter = new DirectoryAdapter(this, mDirs);
|
||||
mGridView.setAdapter(adapter);
|
||||
mGridView.setOnItemClickListener(this);
|
||||
mGridView.setMultiChoiceModeListener(this);
|
||||
mGridView.setOnTouchListener(this);
|
||||
}
|
||||
|
||||
private List<Directory> getDirectories() {
|
||||
final Map<String, Directory> directories = new LinkedHashMap<>();
|
||||
final List<String> invalidFiles = new ArrayList<>();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if ((mIsPickVideoIntent || mIsGetVideoContentIntent) && i == 0)
|
||||
continue;
|
||||
|
||||
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
if (i == 1) {
|
||||
if (mIsPickImageIntent || mIsGetImageContentIntent)
|
||||
continue;
|
||||
|
||||
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
}
|
||||
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN};
|
||||
final String order = getSortOrder();
|
||||
final Cursor cursor = getContentResolver().query(uri, columns, null, null, order);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
||||
do {
|
||||
final String fullPath = cursor.getString(pathIndex);
|
||||
final File file = new File(fullPath);
|
||||
final String parentDir = file.getParent();
|
||||
|
||||
if (!file.exists()) {
|
||||
invalidFiles.add(file.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
final int dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
|
||||
final long timestamp = cursor.getLong(dateIndex);
|
||||
if (directories.containsKey(parentDir)) {
|
||||
final Directory directory = directories.get(parentDir);
|
||||
final int newImageCnt = directory.getMediaCnt() + 1;
|
||||
directory.setMediaCnt(newImageCnt);
|
||||
directory.addSize(file.length());
|
||||
} else if (!mToBeDeleted.contains(parentDir)) {
|
||||
String dirName = Utils.getFilename(parentDir);
|
||||
if (mConfig.getIsFolderHidden(parentDir)) {
|
||||
dirName += " " + getResources().getString(R.string.hidden);
|
||||
}
|
||||
|
||||
directories.put(parentDir, new Directory(parentDir, fullPath, dirName, 1, timestamp, file.length()));
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
final List<Directory> dirs = new ArrayList<>(directories.values());
|
||||
filterDirectories(dirs);
|
||||
Directory.mSorting = mConfig.getDirectorySorting();
|
||||
Collections.sort(dirs);
|
||||
|
||||
final String[] invalids = invalidFiles.toArray(new String[invalidFiles.size()]);
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), invalids, null, null);
|
||||
|
||||
return dirs;
|
||||
}
|
||||
|
||||
private void filterDirectories(List<Directory> dirs) {
|
||||
if (!mConfig.getShowHiddenFolders())
|
||||
removeHiddenFolders(dirs);
|
||||
|
||||
removeNoMediaFolders(dirs);
|
||||
}
|
||||
|
||||
private void removeHiddenFolders(List<Directory> dirs) {
|
||||
final Set<String> hiddenDirs = mConfig.getHiddenFolders();
|
||||
final List<Directory> ignoreDirs = new ArrayList<>();
|
||||
for (Directory d : dirs) {
|
||||
if (hiddenDirs.contains(d.getPath()))
|
||||
ignoreDirs.add(d);
|
||||
}
|
||||
|
||||
dirs.removeAll(ignoreDirs);
|
||||
}
|
||||
|
||||
private void removeNoMediaFolders(List<Directory> dirs) {
|
||||
final List<Directory> ignoreDirs = new ArrayList<>();
|
||||
for (final Directory d : dirs) {
|
||||
final File dir = new File(d.getPath());
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
final String[] res = dir.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File file, String filename) {
|
||||
return filename.equals(".nomedia");
|
||||
}
|
||||
});
|
||||
|
||||
if (res.length > 0)
|
||||
ignoreDirs.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
dirs.removeAll(ignoreDirs);
|
||||
}
|
||||
|
||||
// sort the files at querying too, just to get the correct thumbnail
|
||||
private String getSortOrder() {
|
||||
final int sorting = mConfig.getDirectorySorting();
|
||||
String sortBy = MediaStore.Images.Media.DATE_TAKEN;
|
||||
if ((sorting & Constants.SORT_BY_NAME) != 0) {
|
||||
sortBy = MediaStore.Images.Media.DATA;
|
||||
}
|
||||
|
||||
if ((sorting & Constants.SORT_DESCENDING) != 0) {
|
||||
sortBy += " DESC";
|
||||
}
|
||||
return sortBy;
|
||||
mIsGettingDirs = true;
|
||||
new GetDirectoriesAsynctask(getApplicationContext(), mIsPickVideoIntent || mIsGetVideoContentIntent, mIsPickImageIntent || mIsGetImageContentIntent,
|
||||
mToBeDeleted, this).execute();
|
||||
}
|
||||
|
||||
private void showSortingDialog() {
|
||||
@@ -301,7 +184,7 @@ public class MainActivity extends SimpleActivity
|
||||
}
|
||||
|
||||
private void prepareForDeleting() {
|
||||
Utils.showToast(this, R.string.deleting);
|
||||
Utils.Companion.showToast(this, R.string.deleting);
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
int deletedCnt = 0;
|
||||
@@ -314,11 +197,17 @@ public class MainActivity extends SimpleActivity
|
||||
}
|
||||
}
|
||||
|
||||
for (String path : mToBeDeleted) {
|
||||
if (isShowingPermDialog(new File(path))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
notifyDeletion(deletedCnt);
|
||||
}
|
||||
|
||||
private void notifyDeletion(int cnt) {
|
||||
mDirs = getDirectories();
|
||||
getDirectories();
|
||||
|
||||
final CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
|
||||
final Resources res = getResources();
|
||||
@@ -328,7 +217,6 @@ public class MainActivity extends SimpleActivity
|
||||
mSnackbar.setActionTextColor(Color.WHITE);
|
||||
mSnackbar.show();
|
||||
mIsSnackbarShown = true;
|
||||
updateGridView();
|
||||
}
|
||||
|
||||
private void deleteDirs() {
|
||||
@@ -341,39 +229,64 @@ public class MainActivity extends SimpleActivity
|
||||
|
||||
mIsSnackbarShown = false;
|
||||
|
||||
final List<String> updatedFiles = new ArrayList<>();
|
||||
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 f : files) {
|
||||
updatedFiles.add(f.getAbsolutePath());
|
||||
f.delete();
|
||||
for (File file : files) {
|
||||
if (file.isFile() && Utils.Companion.isPhotoVideo(file)) {
|
||||
updatedFiles.add(file);
|
||||
deleteItem(file);
|
||||
}
|
||||
}
|
||||
updatedFiles.add(dir.getAbsolutePath());
|
||||
dir.delete();
|
||||
updatedFiles.add(dir);
|
||||
if (dir.listFiles().length == 0)
|
||||
deleteItem(dir);
|
||||
}
|
||||
}
|
||||
|
||||
final String[] deletedPaths = updatedFiles.toArray(new String[updatedFiles.size()]);
|
||||
MediaScannerConnection.scanFile(this, deletedPaths, null, null);
|
||||
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();
|
||||
mDirs = getDirectories();
|
||||
updateGridView();
|
||||
getDirectories();
|
||||
}
|
||||
};
|
||||
|
||||
private void updateGridView() {
|
||||
final DirectoryAdapter adapter = (DirectoryAdapter) mGridView.getAdapter();
|
||||
adapter.updateItems(mDirs);
|
||||
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() {
|
||||
@@ -391,59 +304,53 @@ public class MainActivity extends SimpleActivity
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
final View renameDirView = getLayoutInflater().inflate(R.layout.rename_directory, null);
|
||||
final EditText dirNameET = (EditText) renameDirView.findViewById(R.id.directory_name);
|
||||
dirNameET.setText(dir.getName());
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(getResources().getString(R.string.rename_folder));
|
||||
builder.setView(renameDirView);
|
||||
|
||||
final TextView dirPath = (TextView) renameDirView.findViewById(R.id.directory_path);
|
||||
dirPath.setText(dir.getParent() + "/");
|
||||
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
|
||||
final AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
|
||||
new RenameDirectoryDialog(this, dir, new RenameDirectoryDialog.OnRenameDirListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String newDirName = dirNameET.getText().toString().trim();
|
||||
|
||||
if (newDirName.isEmpty()) {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_folder_empty);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> updatedFiles = new ArrayList<>();
|
||||
updatedFiles.add(dir.getAbsolutePath());
|
||||
|
||||
final File newDir = new File(dir.getParent(), newDirName);
|
||||
if (dir.renameTo(newDir)) {
|
||||
Utils.showToast(getApplicationContext(), R.string.renaming_folder);
|
||||
alertDialog.dismiss();
|
||||
mActionMode.finish();
|
||||
|
||||
final File[] files = newDir.listFiles();
|
||||
for (File f : files) {
|
||||
updatedFiles.add(f.getAbsolutePath());
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updatedFiles.add(newDir.getAbsolutePath());
|
||||
final String[] changedFiles = updatedFiles.toArray(new String[updatedFiles.size()]);
|
||||
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 {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_folder_error);
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -504,14 +411,14 @@ public class MainActivity extends SimpleActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (requestCode == PICK_MEDIA && data != null) {
|
||||
if (requestCode == PICK_MEDIA && resultData != null) {
|
||||
final Intent result = new Intent();
|
||||
final String path = data.getData().getPath();
|
||||
final String path = resultData.getData().getPath();
|
||||
final Uri uri = Uri.fromFile(new File(path));
|
||||
if (mIsGetImageContentIntent || mIsGetVideoContentIntent || mIsGetAnyContentIntent) {
|
||||
final String type = Utils.getMimeType(path);
|
||||
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) {
|
||||
@@ -526,7 +433,7 @@ public class MainActivity extends SimpleActivity
|
||||
finish();
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, resultData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -563,7 +470,7 @@ public class MainActivity extends SimpleActivity
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
final MenuInflater inflater = mode.getMenuInflater();
|
||||
inflater.inflate(R.menu.directories_cab, menu);
|
||||
inflater.inflate(R.menu.cab_directories, menu);
|
||||
mActionMode = mode;
|
||||
return true;
|
||||
}
|
||||
@@ -595,6 +502,9 @@ public class MainActivity extends SimpleActivity
|
||||
@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;
|
||||
@@ -610,6 +520,9 @@ public class MainActivity extends SimpleActivity
|
||||
unhideFolders();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_copy_move:
|
||||
displayCopyDialog();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -631,12 +544,12 @@ public class MainActivity extends SimpleActivity
|
||||
|
||||
private void hideFolders() {
|
||||
mConfig.addHiddenDirectories(getSelectedPaths());
|
||||
initializeGallery();
|
||||
getDirectories();
|
||||
}
|
||||
|
||||
private void unhideFolders() {
|
||||
mConfig.removeHiddenDirectories(getSelectedPaths());
|
||||
initializeGallery();
|
||||
getDirectories();
|
||||
}
|
||||
|
||||
private Set<String> getSelectedPaths() {
|
||||
@@ -655,14 +568,12 @@ public class MainActivity extends SimpleActivity
|
||||
private void scanCompleted(final String path) {
|
||||
final File dir = new File(path);
|
||||
if (dir.isDirectory()) {
|
||||
mDirs = getDirectories();
|
||||
getDirectories();
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateGridView();
|
||||
mGridView.requestLayout();
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_folder_ok);
|
||||
Utils.Companion.showToast(getApplicationContext(), R.string.rename_folder_ok);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -670,12 +581,28 @@ public class MainActivity extends SimpleActivity
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
initializeGallery();
|
||||
getDirectories();
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dialogClosed() {
|
||||
initializeGallery();
|
||||
public void sortingDialogClosed() {
|
||||
getDirectories();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.util.Log;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -28,11 +29,14 @@ import android.widget.GridView;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.animation.GlideAnimation;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
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.MediaAdapter;
|
||||
import com.simplemobiletools.gallery.dialogs.ChangeSorting;
|
||||
import com.simplemobiletools.gallery.dialogs.CopyDialog;
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.io.File;
|
||||
@@ -99,7 +103,7 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
|
||||
private void tryloadGallery() {
|
||||
if (Utils.hasStoragePermission(getApplicationContext())) {
|
||||
if (Utils.Companion.hasStoragePermission(getApplicationContext())) {
|
||||
initializeGallery();
|
||||
} else {
|
||||
finish();
|
||||
@@ -123,7 +127,7 @@ public class MediaActivity extends SimpleActivity
|
||||
mGridView.setOnTouchListener(this);
|
||||
mIsSnackbarShown = false;
|
||||
|
||||
final String dirName = Utils.getFilename(mPath);
|
||||
final String dirName = Utils.Companion.getFilename(this, mPath);
|
||||
setTitle(dirName);
|
||||
}
|
||||
|
||||
@@ -144,6 +148,9 @@ public class MediaActivity extends SimpleActivity
|
||||
case R.id.sort:
|
||||
showSortingDialog();
|
||||
return true;
|
||||
case R.id.toggle_filename:
|
||||
toggleFilenameVisibility();
|
||||
return true;
|
||||
case R.id.hide_folder:
|
||||
hideDirectory();
|
||||
return true;
|
||||
@@ -155,17 +162,9 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void rescanDirectory(File dir) {
|
||||
final File[] files = dir.listFiles();
|
||||
final String[] paths = new String[files.length];
|
||||
final int cnt = dir.listFiles().length;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
paths[i] = files[i].getPath();
|
||||
if (files[i].isDirectory()) {
|
||||
rescanDirectory(files[i]);
|
||||
}
|
||||
}
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), paths, null, null);
|
||||
private void toggleFilenameVisibility() {
|
||||
mConfig.setDisplayFileNames(!mConfig.getDisplayFileNames());
|
||||
((MediaAdapter)mGridView.getAdapter()).updateDisplayFilenames(mConfig.getDisplayFileNames());
|
||||
}
|
||||
|
||||
private void showSortingDialog() {
|
||||
@@ -195,7 +194,7 @@ public class MediaActivity extends SimpleActivity
|
||||
|
||||
private List<Medium> getMedia() {
|
||||
final List<Medium> media = new ArrayList<>();
|
||||
final List<String> invalidFiles = new ArrayList<>();
|
||||
final ArrayList<File> invalidFiles = new ArrayList<>();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (mIsGetVideoIntent && i == 0)
|
||||
continue;
|
||||
@@ -209,34 +208,37 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
final String where = MediaStore.Images.Media.DATA + " like ? ";
|
||||
final String[] args = new String[]{mPath + "%"};
|
||||
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN};
|
||||
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED};
|
||||
final Cursor cursor = getContentResolver().query(uri, columns, where, args, null);
|
||||
final String pattern = Pattern.quote(mPath) + "/[^/]*";
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
||||
do {
|
||||
final String curPath = cursor.getString(pathIndex);
|
||||
if (curPath.matches(pattern) && !mToBeDeleted.contains(curPath)) {
|
||||
final File file = new File(curPath);
|
||||
if (file.exists()) {
|
||||
final int dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
|
||||
final long timestamp = cursor.getLong(dateIndex);
|
||||
media.add(new Medium(curPath, (i == 1), timestamp, file.length()));
|
||||
} else {
|
||||
invalidFiles.add(file.getAbsolutePath());
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
final int pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
||||
do {
|
||||
final String curPath = cursor.getString(pathIndex);
|
||||
if (curPath == null)
|
||||
continue;
|
||||
|
||||
if (curPath.matches(pattern) && !mToBeDeleted.contains(curPath)) {
|
||||
final File file = new File(curPath);
|
||||
if (file.exists()) {
|
||||
final int dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED);
|
||||
final long timestamp = cursor.getLong(dateIndex);
|
||||
media.add(new Medium(file.getName(), curPath, (i == 1), timestamp, file.length()));
|
||||
} else {
|
||||
invalidFiles.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
Medium.mSorting = mConfig.getSorting();
|
||||
Medium.Companion.setSorting(mConfig.getSorting());
|
||||
Collections.sort(media);
|
||||
|
||||
final String[] invalids = invalidFiles.toArray(new String[invalidFiles.size()]);
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), invalids, null, null);
|
||||
Utils.Companion.scanFiles(getApplicationContext(), invalidFiles);
|
||||
|
||||
return media;
|
||||
}
|
||||
@@ -253,7 +255,7 @@ public class MediaActivity extends SimpleActivity
|
||||
private void shareMedia() {
|
||||
final List<Medium> selectedMedia = getSelectedMedia();
|
||||
if (selectedMedia.size() <= 1) {
|
||||
Utils.shareMedium(selectedMedia.get(0), this);
|
||||
Utils.Companion.shareMedium(selectedMedia.get(0), this);
|
||||
} else {
|
||||
shareMedia(selectedMedia);
|
||||
}
|
||||
@@ -288,7 +290,10 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
|
||||
private void prepareForDeleting() {
|
||||
Utils.showToast(this, R.string.deleting);
|
||||
if (isShowingPermDialog(new File(mPath)))
|
||||
return;
|
||||
|
||||
Utils.Companion.showToast(this, R.string.deleting);
|
||||
final SparseBooleanArray items = mGridView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
int deletedCnt = 0;
|
||||
@@ -331,23 +336,38 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
|
||||
mIsSnackbarShown = false;
|
||||
boolean wereFilesDeleted = false;
|
||||
|
||||
for (String delPath : mToBeDeleted) {
|
||||
final File file = new File(delPath);
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
}
|
||||
if (file.exists()) {
|
||||
if (Utils.Companion.needsStupidWritePermissions(this, delPath)) {
|
||||
if (isShowingPermDialog(file))
|
||||
return;
|
||||
|
||||
final String[] deletedPaths = mToBeDeleted.toArray(new String[mToBeDeleted.size()]);
|
||||
MediaScannerConnection.scanFile(this, deletedPaths, null, new MediaScannerConnection.OnScanCompletedListener() {
|
||||
@Override
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
if (mMedia != null && mMedia.isEmpty()) {
|
||||
finish();
|
||||
final DocumentFile document = Utils.Companion.getFileDocument(this, delPath, mConfig.getTreeUri());
|
||||
if (document.delete()) {
|
||||
wereFilesDeleted = true;
|
||||
}
|
||||
} else {
|
||||
if (file.delete())
|
||||
wereFilesDeleted = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
mToBeDeleted.clear();
|
||||
}
|
||||
|
||||
if (wereFilesDeleted) {
|
||||
final String[] deletedPaths = mToBeDeleted.toArray(new String[mToBeDeleted.size()]);
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), deletedPaths, null, new MediaScannerConnection.OnScanCompletedListener() {
|
||||
@Override
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
if (mMedia != null && mMedia.isEmpty()) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
mToBeDeleted.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener undoDeletion = new View.OnClickListener() {
|
||||
@@ -368,15 +388,60 @@ public class MediaActivity extends SimpleActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void showProperties() {
|
||||
final List<Medium> selectedMedia = getSelectedMedia();
|
||||
if (selectedMedia.size() == 1) {
|
||||
new PropertiesDialog(this, selectedMedia.get(0).getPath(), false);
|
||||
} else {
|
||||
final List<String> paths = new ArrayList<>(selectedMedia.size());
|
||||
for (Medium medium : selectedMedia) {
|
||||
paths.add(medium.getPath());
|
||||
}
|
||||
new PropertiesDialog(this, paths, false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSetWallpaperIntent() {
|
||||
return getIntent().getBooleanExtra(Constants.SET_WALLPAPER_INTENT, false);
|
||||
}
|
||||
|
||||
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);
|
||||
files.add(new File(mMedia.get(id).getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
new CopyDialog(this, files, new CopyMoveTask.CopyMoveListener() {
|
||||
@Override
|
||||
public void copySucceeded(boolean deleted, boolean copiedAll) {
|
||||
int msgId;
|
||||
if (deleted) {
|
||||
refreshDir();
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final String curItemPath = mMedia.get(position).getPath();
|
||||
if (isSetWallpaperIntent()) {
|
||||
Utils.showToast(this, R.string.setting_wallpaper);
|
||||
Utils.Companion.showToast(this, R.string.setting_wallpaper);
|
||||
|
||||
final int wantedWidth = getWallpaperDesiredMinimumWidth();
|
||||
final int wantedHeight = getWallpaperDesiredMinimumHeight();
|
||||
@@ -439,6 +504,9 @@ public class MediaActivity extends SimpleActivity
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.cab_properties:
|
||||
showProperties();
|
||||
return true;
|
||||
case R.id.cab_share:
|
||||
shareMedia();
|
||||
return true;
|
||||
@@ -446,6 +514,9 @@ public class MediaActivity extends SimpleActivity
|
||||
prepareForDeleting();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_copy_move:
|
||||
displayCopyDialog();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -467,16 +538,20 @@ public class MediaActivity extends SimpleActivity
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
refreshDir();
|
||||
}
|
||||
|
||||
private void refreshDir() {
|
||||
final File dir = new File(mPath);
|
||||
if (dir.isDirectory()) {
|
||||
rescanDirectory(dir);
|
||||
Utils.Companion.scanPath(getApplicationContext(), mPath);
|
||||
}
|
||||
initializeGallery();
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dialogClosed() {
|
||||
public void sortingDialogClosed() {
|
||||
initializeGallery();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class PhotoActivity extends PhotoVideoActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mIsVideo = false;
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.Utils;
|
||||
import com.simplemobiletools.gallery.fragments.PhotoFragment;
|
||||
import com.simplemobiletools.gallery.fragments.VideoFragment;
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment;
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class PhotoVideoActivity extends SimpleActivity implements ViewPagerFragment.FragmentClickListener {
|
||||
private static ActionBar mActionbar;
|
||||
private static Uri mUri;
|
||||
private static ViewPagerFragment mFragment;
|
||||
|
||||
private static boolean mIsFullScreen;
|
||||
|
||||
protected static boolean mIsVideo;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.fragment_holder);
|
||||
|
||||
mUri = getIntent().getData();
|
||||
if (mUri == null)
|
||||
return;
|
||||
|
||||
mActionbar = getSupportActionBar();
|
||||
mIsFullScreen = true;
|
||||
hideSystemUI();
|
||||
|
||||
final Bundle bundle = new Bundle();
|
||||
final File file = new File(mUri.toString());
|
||||
final Medium medium = new Medium(mUri.toString(), mIsVideo, 0, file.length());
|
||||
bundle.putSerializable(Constants.MEDIUM, medium);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
mFragment = (mIsVideo ? new VideoFragment() : new PhotoFragment());
|
||||
mFragment.setListener(this);
|
||||
mFragment.setArguments(bundle);
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder, mFragment).commit();
|
||||
}
|
||||
hideSystemUI();
|
||||
setTitle(Utils.getFilename(mUri.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
mFragment.updateItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.photo_video_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_share:
|
||||
shareMedium();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void shareMedium() {
|
||||
final String shareTitle = getResources().getString(R.string.share_via);
|
||||
final Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, mUri);
|
||||
sendIntent.setType(mIsVideo ? "video/*" : "image/*");
|
||||
startActivity(Intent.createChooser(sendIntent, shareTitle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fragmentClicked() {
|
||||
mIsFullScreen = !mIsFullScreen;
|
||||
if (mIsFullScreen) {
|
||||
hideSystemUI();
|
||||
} else {
|
||||
showSystemUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideSystemUI() {
|
||||
Utils.hideSystemUI(mActionbar, getWindow());
|
||||
}
|
||||
|
||||
private void showSystemUI() {
|
||||
Utils.showSystemUI(mActionbar, getWindow());
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
|
||||
import com.simplemobiletools.gallery.Config;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class SettingsActivity extends SimpleActivity {
|
||||
@BindView(R.id.settings_dark_theme) SwitchCompat mDarkThemeSwitch;
|
||||
@BindView(R.id.settings_same_sorting) SwitchCompat mSameSortingSwitch;
|
||||
@BindView(R.id.settings_show_hidden_folders) SwitchCompat mShowHiddenFoldersSwitch;
|
||||
|
||||
private static Config mConfig;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_settings);
|
||||
mConfig = Config.newInstance(getApplicationContext());
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setupDarkTheme();
|
||||
setupSameSorting();
|
||||
setupShowHiddenFolders();
|
||||
}
|
||||
|
||||
private void setupDarkTheme() {
|
||||
mDarkThemeSwitch.setChecked(mConfig.getIsDarkTheme());
|
||||
}
|
||||
|
||||
private void setupSameSorting() {
|
||||
mSameSortingSwitch.setChecked(mConfig.getIsSameSorting());
|
||||
}
|
||||
|
||||
private void setupShowHiddenFolders() {
|
||||
mShowHiddenFoldersSwitch.setChecked(mConfig.getShowHiddenFolders());
|
||||
}
|
||||
|
||||
@OnClick(R.id.settings_dark_theme_holder)
|
||||
public void handleDarkTheme() {
|
||||
mDarkThemeSwitch.setChecked(!mDarkThemeSwitch.isChecked());
|
||||
mConfig.setIsDarkTheme(mDarkThemeSwitch.isChecked());
|
||||
restartActivity();
|
||||
}
|
||||
|
||||
@OnClick(R.id.settings_same_sorting_holder)
|
||||
public void handleSameSorting() {
|
||||
mSameSortingSwitch.setChecked(!mSameSortingSwitch.isChecked());
|
||||
mConfig.setIsSameSorting(mSameSortingSwitch.isChecked());
|
||||
}
|
||||
|
||||
@OnClick(R.id.settings_show_hidden_folders_holder)
|
||||
public void handleShowHiddenFolders() {
|
||||
mShowHiddenFoldersSwitch.setChecked(!mShowHiddenFoldersSwitch.isChecked());
|
||||
mConfig.setShowHiddenFolders(mShowHiddenFoldersSwitch.isChecked());
|
||||
}
|
||||
|
||||
private void restartActivity() {
|
||||
TaskStackBuilder.create(getApplicationContext()).addNextIntentWithParentStack(getIntent()).startActivities();
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.simplemobiletools.gallery.Config;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
|
||||
public class SimpleActivity extends AppCompatActivity {
|
||||
protected Config mConfig;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
mConfig = Config.newInstance(getApplicationContext());
|
||||
int theme = mConfig.getIsDarkTheme() ? R.style.AppTheme_Dark : R.style.AppTheme;
|
||||
if (this instanceof ViewPagerActivity || this instanceof PhotoActivity || this instanceof VideoActivity) {
|
||||
theme = mConfig.getIsDarkTheme() ? R.style.FullScreenTheme_Dark : R.style.FullScreenTheme;
|
||||
}
|
||||
setTheme(theme);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class VideoActivity extends PhotoVideoActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mIsVideo = true;
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
package com.simplemobiletools.gallery.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
import com.simplemobiletools.gallery.MyViewPager;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.Utils;
|
||||
import com.simplemobiletools.gallery.adapters.MyPagerAdapter;
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment;
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class ViewPagerActivity extends SimpleActivity
|
||||
implements ViewPager.OnPageChangeListener, View.OnSystemUiVisibilityChangeListener, ViewPager.OnTouchListener,
|
||||
ViewPagerFragment.FragmentClickListener {
|
||||
@BindView(R.id.undo_delete) View mUndoBtn;
|
||||
@BindView(R.id.view_pager) MyViewPager mPager;
|
||||
|
||||
private static final int EDIT_IMAGE = 1;
|
||||
private static final int SET_WALLPAPER = 2;
|
||||
private static ActionBar mActionbar;
|
||||
private static List<Medium> mMedia;
|
||||
private static String mPath;
|
||||
private static String mDirectory;
|
||||
private static String mToBeDeleted;
|
||||
private static String mBeingDeleted;
|
||||
|
||||
private static boolean mIsFullScreen;
|
||||
private static boolean mIsUndoShown;
|
||||
private static int mPos;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_medium);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
if (!Utils.hasStoragePermission(getApplicationContext())) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
final Uri uri = getIntent().getData();
|
||||
if (uri != null) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
final String[] proj = {MediaStore.Images.Media.DATA};
|
||||
cursor = getContentResolver().query(uri, proj, null, null, null);
|
||||
if (cursor != null) {
|
||||
final int dataIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
|
||||
cursor.moveToFirst();
|
||||
mPath = cursor.getString(dataIndex);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mPath = getIntent().getStringExtra(Constants.MEDIUM);
|
||||
}
|
||||
|
||||
if (mPath == null || mPath.isEmpty()) {
|
||||
Utils.showToast(getApplicationContext(), R.string.unknown_error);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mPos = 0;
|
||||
mIsFullScreen = true;
|
||||
mActionbar = getSupportActionBar();
|
||||
mToBeDeleted = "";
|
||||
mBeingDeleted = "";
|
||||
hideSystemUI();
|
||||
|
||||
MediaScannerConnection.scanFile(this, new String[]{mPath}, null, null);
|
||||
addUndoMargin();
|
||||
mDirectory = new File(mPath).getParent();
|
||||
mMedia = getMedia();
|
||||
if (isDirEmpty())
|
||||
return;
|
||||
|
||||
final MyPagerAdapter adapter = new MyPagerAdapter(this, getSupportFragmentManager(), mMedia);
|
||||
mPager.setAdapter(adapter);
|
||||
mPager.setCurrentItem(mPos);
|
||||
mPager.addOnPageChangeListener(this);
|
||||
mPager.setOnTouchListener(this);
|
||||
|
||||
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
|
||||
updateActionbarTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (!Utils.hasStoragePermission(getApplicationContext())) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.undo_delete)
|
||||
public void undoDeletion() {
|
||||
mIsUndoShown = false;
|
||||
mToBeDeleted = "";
|
||||
mBeingDeleted = "";
|
||||
mUndoBtn.setVisibility(View.GONE);
|
||||
reloadViewPager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.viewpager_menu, menu);
|
||||
menu.findItem(R.id.menu_set_as_wallpaper).setVisible(getCurrentMedium().isImage());
|
||||
menu.findItem(R.id.menu_edit).setVisible(getCurrentMedium().isImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
deleteFile();
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_set_as_wallpaper:
|
||||
setAsWallpaper();
|
||||
return true;
|
||||
case R.id.menu_open_with:
|
||||
openWith();
|
||||
return true;
|
||||
case R.id.menu_share:
|
||||
shareMedium();
|
||||
return true;
|
||||
case R.id.menu_delete:
|
||||
notifyDeletion();
|
||||
return true;
|
||||
case R.id.menu_rename:
|
||||
editMedium();
|
||||
return true;
|
||||
case R.id.menu_edit:
|
||||
openEditor();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
final MyPagerAdapter adapter = (MyPagerAdapter) mPager.getAdapter();
|
||||
adapter.updateItems(mPos);
|
||||
}
|
||||
|
||||
private void openEditor() {
|
||||
final Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), "image/*");
|
||||
final Intent chooser = Intent.createChooser(intent, getString(R.string.edit_image_with));
|
||||
|
||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivityForResult(chooser, EDIT_IMAGE);
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.no_editor_found);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAsWallpaper() {
|
||||
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), "image/jpeg");
|
||||
final Intent chooser = Intent.createChooser(intent, getString(R.string.set_as_wallpaper_with));
|
||||
|
||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivityForResult(chooser, SET_WALLPAPER);
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.no_wallpaper_setter_found);
|
||||
}
|
||||
}
|
||||
|
||||
private void openWith() {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), Utils.getMimeType(getCurrentMedium()));
|
||||
final Intent chooser = Intent.createChooser(intent, getString(R.string.open_with));
|
||||
|
||||
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivity(chooser);
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.no_app_found);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == EDIT_IMAGE) {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
final MyPagerAdapter adapter = (MyPagerAdapter) mPager.getAdapter();
|
||||
adapter.updateItems(mPos);
|
||||
}
|
||||
} else if (requestCode == SET_WALLPAPER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Utils.showToast(getApplicationContext(), R.string.wallpaper_set_successfully);
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void shareMedium() {
|
||||
final Medium medium = getCurrentMedium();
|
||||
Utils.shareMedium(medium, this);
|
||||
}
|
||||
|
||||
private void notifyDeletion() {
|
||||
mToBeDeleted = getCurrentFile().getAbsolutePath();
|
||||
|
||||
if (mMedia.size() <= 1) {
|
||||
deleteFile();
|
||||
} else {
|
||||
Utils.showToast(this, R.string.file_deleted);
|
||||
mUndoBtn.setVisibility(View.VISIBLE);
|
||||
mIsUndoShown = true;
|
||||
reloadViewPager();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteFile() {
|
||||
if (mToBeDeleted.isEmpty())
|
||||
return;
|
||||
|
||||
mIsUndoShown = false;
|
||||
mBeingDeleted = "";
|
||||
|
||||
final File file = new File(mToBeDeleted);
|
||||
if (file.delete()) {
|
||||
mBeingDeleted = mToBeDeleted;
|
||||
final String[] deletedPath = new String[]{mToBeDeleted};
|
||||
MediaScannerConnection.scanFile(this, deletedPath, null, new MediaScannerConnection.OnScanCompletedListener() {
|
||||
@Override
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
scanCompleted();
|
||||
}
|
||||
});
|
||||
}
|
||||
mToBeDeleted = "";
|
||||
mUndoBtn.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private boolean isDirEmpty() {
|
||||
if (mMedia.size() <= 0) {
|
||||
deleteDirectoryIfEmpty();
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void editMedium() {
|
||||
final File file = getCurrentFile();
|
||||
final String fullName = file.getName();
|
||||
final int dotAt = fullName.lastIndexOf(".");
|
||||
if (dotAt <= 0)
|
||||
return;
|
||||
|
||||
final String name = fullName.substring(0, dotAt);
|
||||
final String extension = fullName.substring(dotAt + 1, fullName.length());
|
||||
|
||||
final View renameFileView = getLayoutInflater().inflate(R.layout.rename_file, null);
|
||||
final EditText fileNameET = (EditText) renameFileView.findViewById(R.id.file_name);
|
||||
fileNameET.setText(name);
|
||||
|
||||
final EditText extensionET = (EditText) renameFileView.findViewById(R.id.extension);
|
||||
extensionET.setText(extension);
|
||||
|
||||
final TextView filePath = (TextView) renameFileView.findViewById(R.id.file_path);
|
||||
filePath.setText(file.getParent() + "/");
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(getResources().getString(R.string.rename_file));
|
||||
builder.setView(renameFileView);
|
||||
|
||||
builder.setPositiveButton(R.string.ok, null);
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
|
||||
final AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String fileName = fileNameET.getText().toString().trim();
|
||||
final String extension = extensionET.getText().toString().trim();
|
||||
|
||||
if (fileName.isEmpty() || extension.isEmpty()) {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_file_empty);
|
||||
return;
|
||||
}
|
||||
|
||||
final File newFile = new File(file.getParent(), fileName + "." + extension);
|
||||
|
||||
if (file.renameTo(newFile)) {
|
||||
final int currItem = mPager.getCurrentItem();
|
||||
mMedia.set(currItem, new Medium(newFile.getAbsolutePath(), mMedia.get(currItem).getIsVideo(), 0, file.length()));
|
||||
|
||||
final String[] changedFiles = {file.getAbsolutePath(), newFile.getAbsolutePath()};
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), changedFiles, null, null);
|
||||
updateActionbarTitle();
|
||||
alertDialog.dismiss();
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_file_error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void reloadViewPager() {
|
||||
final MyPagerAdapter adapter = (MyPagerAdapter) mPager.getAdapter();
|
||||
final int curPos = mPager.getCurrentItem();
|
||||
mMedia = getMedia();
|
||||
if (isDirEmpty())
|
||||
return;
|
||||
|
||||
mPager.setAdapter(null);
|
||||
adapter.updateItems(mMedia);
|
||||
mPager.setAdapter(adapter);
|
||||
|
||||
final int newPos = Math.min(curPos, adapter.getCount());
|
||||
mPager.setCurrentItem(newPos);
|
||||
updateActionbarTitle();
|
||||
}
|
||||
|
||||
private void deleteDirectoryIfEmpty() {
|
||||
final File file = new File(mDirectory);
|
||||
if (file.isDirectory() && file.listFiles().length == 0) {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
final String[] toBeDeleted = new String[]{mDirectory};
|
||||
MediaScannerConnection.scanFile(getApplicationContext(), toBeDeleted, null, null);
|
||||
}
|
||||
|
||||
private List<Medium> getMedia() {
|
||||
final List<Medium> media = new ArrayList<>();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
if (i == 1) {
|
||||
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
||||
}
|
||||
final String where = MediaStore.Images.Media.DATA + " like ? ";
|
||||
final String[] args = new String[]{mDirectory + "%"};
|
||||
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.SIZE};
|
||||
final Cursor cursor = getContentResolver().query(uri, columns, where, args, null);
|
||||
final String pattern = Pattern.quote(mDirectory) + "/[^/]*";
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
||||
do {
|
||||
final String curPath = cursor.getString(pathIndex);
|
||||
if (curPath.matches(pattern) && !curPath.equals(mToBeDeleted) && !curPath.equals(mBeingDeleted)) {
|
||||
final int dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
|
||||
final long timestamp = cursor.getLong(dateIndex);
|
||||
|
||||
final int sizeIndex = cursor.getColumnIndex(MediaStore.Images.Media.SIZE);
|
||||
final long size = cursor.getLong(sizeIndex);
|
||||
media.add(new Medium(curPath, i == 1, timestamp, size));
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
Medium.mSorting = mConfig.getSorting();
|
||||
Collections.sort(media);
|
||||
int j = 0;
|
||||
for (Medium medium : media) {
|
||||
if (medium.getPath().equals(mPath)) {
|
||||
mPos = j;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return media;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fragmentClicked() {
|
||||
deleteFile();
|
||||
mIsFullScreen = !mIsFullScreen;
|
||||
if (mIsFullScreen) {
|
||||
hideSystemUI();
|
||||
} else {
|
||||
showSystemUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideSystemUI() {
|
||||
Utils.hideSystemUI(mActionbar, getWindow());
|
||||
}
|
||||
|
||||
private void showSystemUI() {
|
||||
Utils.showSystemUI(mActionbar, getWindow());
|
||||
}
|
||||
|
||||
private void updateActionbarTitle() {
|
||||
setTitle(Utils.getFilename(mMedia.get(mPager.getCurrentItem()).getPath()));
|
||||
}
|
||||
|
||||
private Medium getCurrentMedium() {
|
||||
if (mPos >= mMedia.size())
|
||||
mPos = mMedia.size() - 1;
|
||||
return mMedia.get(mPos);
|
||||
}
|
||||
|
||||
private File getCurrentFile() {
|
||||
return new File(getCurrentMedium().getPath());
|
||||
}
|
||||
|
||||
private void addUndoMargin() {
|
||||
final Resources res = getResources();
|
||||
final RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mUndoBtn.getLayoutParams();
|
||||
final int topMargin = Utils.getStatusBarHeight(res) + Utils.getActionBarHeight(getApplicationContext(), res);
|
||||
int rightMargin = params.rightMargin;
|
||||
|
||||
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||
rightMargin += Utils.getNavBarHeight(res);
|
||||
}
|
||||
|
||||
params.setMargins(params.leftMargin, topMargin, rightMargin, params.bottomMargin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
updateActionbarTitle();
|
||||
mPos = position;
|
||||
supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
|
||||
final MyPagerAdapter adapter = (MyPagerAdapter) mPager.getAdapter();
|
||||
adapter.itemDragged(mPos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSystemUiVisibilityChange(int visibility) {
|
||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
mIsFullScreen = false;
|
||||
}
|
||||
|
||||
final MyPagerAdapter adapter = (MyPagerAdapter) mPager.getAdapter();
|
||||
adapter.updateUiVisibility(mIsFullScreen, mPos);
|
||||
}
|
||||
|
||||
private void scanCompleted() {
|
||||
mBeingDeleted = "";
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mMedia != null && mMedia.size() <= 1) {
|
||||
reloadViewPager();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (mIsUndoShown) {
|
||||
deleteFile();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
deleteFile();
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
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 com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.signature.StringSignature;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.models.Directory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class DirectoryAdapter extends BaseAdapter {
|
||||
private final Context mContext;
|
||||
private final List<Directory> mDirs;
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public DirectoryAdapter(Context context, List<Directory> dirs) {
|
||||
mContext = context;
|
||||
mDirs = dirs;
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.directory_item, parent, false);
|
||||
viewHolder = new ViewHolder(convertView);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
final Directory dir = mDirs.get(position);
|
||||
viewHolder.dirName.setText(dir.getName());
|
||||
viewHolder.photoCnt.setText(String.valueOf(dir.getMediaCnt()));
|
||||
final String tmb = dir.getThumbnail();
|
||||
final StringSignature timestampSignature = new StringSignature(String.valueOf(dir.getTimestamp()));
|
||||
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);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mDirs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mDirs.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void updateItems(List<Directory> newDirs) {
|
||||
mDirs.clear();
|
||||
mDirs.addAll(newDirs);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
@BindView(R.id.dir_name) TextView dirName;
|
||||
@BindView(R.id.photo_cnt) TextView photoCnt;
|
||||
@BindView(R.id.dir_thumbnail) ImageView dirThumbnail;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
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 com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.signature.StringSignature;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class MediaAdapter extends BaseAdapter {
|
||||
private final Context mContext;
|
||||
private final List<Medium> mMedia;
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public MediaAdapter(Context context, List<Medium> media) {
|
||||
mContext = context;
|
||||
mMedia = media;
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final Medium medium = mMedia.get(position);
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.photo_video_item, parent, false);
|
||||
viewHolder = new ViewHolder(convertView);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
if (medium.getIsVideo()) {
|
||||
viewHolder.playOutline.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.playOutline.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final String path = medium.getPath();
|
||||
final StringSignature timestampSignature = new StringSignature(String.valueOf(medium.getTimestamp()));
|
||||
if (medium.isGif()) {
|
||||
Glide.with(mContext).load(path).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature).into(viewHolder.photoThumbnail);
|
||||
} else {
|
||||
Glide.with(mContext).load(path).diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(viewHolder.photoThumbnail);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mMedia.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mMedia.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void updateItems(List<Medium> newPhotos) {
|
||||
mMedia.clear();
|
||||
mMedia.addAll(newPhotos);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
@BindView(R.id.medium_thumbnail) ImageView photoThumbnail;
|
||||
@BindView(R.id.play_outline) View playOutline;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.simplemobiletools.gallery.adapters;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
import com.simplemobiletools.gallery.activities.ViewPagerActivity;
|
||||
import com.simplemobiletools.gallery.fragments.PhotoFragment;
|
||||
import com.simplemobiletools.gallery.fragments.VideoFragment;
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment;
|
||||
import com.simplemobiletools.gallery.models.Medium;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MyPagerAdapter extends FragmentStatePagerAdapter {
|
||||
private final List<Medium> mMedia;
|
||||
private final Map<Integer, ViewPagerFragment> mFragments;
|
||||
private final ViewPagerActivity mActivity;
|
||||
|
||||
public MyPagerAdapter(ViewPagerActivity act, FragmentManager fm, List<Medium> media) {
|
||||
super(fm);
|
||||
mActivity = act;
|
||||
mMedia = media;
|
||||
mFragments = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mMedia.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
final Medium medium = mMedia.get(position);
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Constants.MEDIUM, medium);
|
||||
ViewPagerFragment fragment;
|
||||
|
||||
if (medium.getIsVideo()) {
|
||||
fragment = new VideoFragment();
|
||||
} else {
|
||||
fragment = new PhotoFragment();
|
||||
}
|
||||
|
||||
mFragments.put(position, fragment);
|
||||
fragment.setArguments(bundle);
|
||||
fragment.setListener(mActivity);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public void itemDragged(int pos) {
|
||||
if (mFragments.get(pos) != null) {
|
||||
mFragments.get(pos).itemDragged();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUiVisibility(boolean isFullscreen, int pos) {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
final ViewPagerFragment fragment = mFragments.get(pos + i);
|
||||
if (fragment != null) {
|
||||
fragment.systemUiVisibilityChanged(isFullscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateItems(int pos) {
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
final ViewPagerFragment fragment = mFragments.get(pos + i);
|
||||
if (fragment != null) {
|
||||
fragment.updateItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateItems(List<Medium> newPaths) {
|
||||
mMedia.clear();
|
||||
mMedia.addAll(newPaths);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class ChangeSorting extends AlertDialog.Builder implements DialogInterfac
|
||||
|
||||
mIsDirectorySorting = isDirectorySorting;
|
||||
mListener = (ChangeDialogListener) act;
|
||||
mConfig = Config.newInstance(getContext());
|
||||
mConfig = Config.Companion.newInstance(getContext());
|
||||
mHolder = act.getLayoutInflater().inflate(R.layout.change_sorting, null);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
@@ -90,10 +90,10 @@ public class ChangeSorting extends AlertDialog.Builder implements DialogInterfac
|
||||
mConfig.setSorting(sorting);
|
||||
}
|
||||
}
|
||||
mListener.dialogClosed();
|
||||
mListener.sortingDialogClosed();
|
||||
}
|
||||
|
||||
public interface ChangeDialogListener {
|
||||
void dialogClosed();
|
||||
void sortingDialogClosed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class PhotoFragment extends ViewPagerFragment implements View.OnClickList
|
||||
|
||||
mMedium = (Medium) getArguments().getSerializable(Constants.MEDIUM);
|
||||
if (mMedium.getPath().startsWith("content://"))
|
||||
mMedium.setPath(Utils.getRealPathFromURI(getContext(), Uri.parse(mMedium.getPath())));
|
||||
mMedium.setPath(Utils.Companion.getRealPathFromURI(getContext(), Uri.parse(mMedium.getPath())));
|
||||
|
||||
if (mMedium == null)
|
||||
return view;
|
||||
@@ -39,6 +39,7 @@ public class PhotoFragment extends ViewPagerFragment implements View.OnClickList
|
||||
Glide.with(getContext()).load(mMedium.getPath()).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
|
||||
imageView.setOnClickListener(this);
|
||||
} else {
|
||||
mSubsamplingView.setDoubleTapZoomScale(1.2f);
|
||||
mSubsamplingView.setOrientation(SubsamplingScaleImageView.ORIENTATION_USE_EXIF);
|
||||
mSubsamplingView.setImage(ImageSource.uri(mMedium.getPath()));
|
||||
mSubsamplingView.setMaxScale(4f);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.simplemobiletools.gallery.Config;
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
import com.simplemobiletools.gallery.R;
|
||||
import com.simplemobiletools.gallery.Utils;
|
||||
@@ -52,6 +53,7 @@ public class VideoFragment extends ViewPagerFragment
|
||||
private boolean mIsPlaying;
|
||||
private boolean mIsDragged;
|
||||
private boolean mIsFullscreen;
|
||||
private boolean mIsFragmentVisible;
|
||||
private int mCurrTime;
|
||||
private int mDuration;
|
||||
|
||||
@@ -87,6 +89,17 @@ public class VideoFragment extends ViewPagerFragment
|
||||
initTimeHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
mIsFragmentVisible = menuVisible;
|
||||
if (menuVisible) {
|
||||
if (getContext() != null && Config.Companion.newInstance(getContext()).getAutoplayVideos()) {
|
||||
playVideo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void itemDragged() {
|
||||
pauseVideo();
|
||||
}
|
||||
@@ -108,13 +121,13 @@ public class VideoFragment extends ViewPagerFragment
|
||||
private void initTimeHolder() {
|
||||
mTimeHolder = mView.findViewById(R.id.video_time_holder);
|
||||
final Resources res = getResources();
|
||||
final int height = Utils.getNavBarHeight(res);
|
||||
final int height = Utils.Companion.getNavBarHeight(res);
|
||||
final int left = mTimeHolder.getPaddingLeft();
|
||||
final int top = mTimeHolder.getPaddingTop();
|
||||
int right = (int) getResources().getDimension(R.dimen.timer_padding);
|
||||
int bottom = 0;
|
||||
|
||||
if (Utils.hasNavBar(getActivity())) {
|
||||
if (Utils.Companion.hasNavBar(getActivity())) {
|
||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
bottom += height;
|
||||
} else {
|
||||
@@ -190,34 +203,38 @@ public class VideoFragment extends ViewPagerFragment
|
||||
mTimeHolder.startAnimation(animation);
|
||||
}
|
||||
|
||||
private void pauseVideo() {
|
||||
if (mIsPlaying) {
|
||||
togglePlayPause();
|
||||
}
|
||||
}
|
||||
|
||||
private void togglePlayPause() {
|
||||
if (getActivity() == null)
|
||||
if (getActivity() == null || !isAdded())
|
||||
return;
|
||||
|
||||
mIsPlaying = !mIsPlaying;
|
||||
if (mIsPlaying) {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.start();
|
||||
}
|
||||
|
||||
mPlayOutline.setImageDrawable(null);
|
||||
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
playVideo();
|
||||
} else {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.pause();
|
||||
}
|
||||
|
||||
mPlayOutline.setImageDrawable(getResources().getDrawable(R.mipmap.play_outline_big));
|
||||
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
pauseVideo();
|
||||
}
|
||||
}
|
||||
|
||||
private void playVideo() {
|
||||
mIsPlaying = true;
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.start();
|
||||
}
|
||||
|
||||
mPlayOutline.setImageDrawable(null);
|
||||
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
private void pauseVideo() {
|
||||
mIsPlaying = false;
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.pause();
|
||||
}
|
||||
|
||||
mPlayOutline.setImageDrawable(getResources().getDrawable(R.mipmap.play_outline_big));
|
||||
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
private void initMediaPlayer() {
|
||||
if (mMediaPlayer != null)
|
||||
return;
|
||||
@@ -251,6 +268,7 @@ public class VideoFragment extends ViewPagerFragment
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
pauseVideo();
|
||||
mIsFragmentVisible = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -390,5 +408,8 @@ public class VideoFragment extends ViewPagerFragment
|
||||
addPreviewImage();
|
||||
setupTimeHolder();
|
||||
setProgress(mCurrTime);
|
||||
|
||||
if (mIsFragmentVisible && Config.Companion.newInstance(getContext()).getAutoplayVideos())
|
||||
playVideo();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.simplemobiletools.gallery.models;
|
||||
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
|
||||
public class Directory implements Comparable {
|
||||
private final String mPath;
|
||||
private final String mThumbnail;
|
||||
private final String mName;
|
||||
private final long mTimestamp;
|
||||
private int mMediaCnt;
|
||||
private long mSize;
|
||||
public static int mSorting;
|
||||
|
||||
public Directory(String path, String thumbnail, String name, int mediaCnt, long timestamp, long size) {
|
||||
mPath = path;
|
||||
mThumbnail = thumbnail;
|
||||
mName = name;
|
||||
mMediaCnt = mediaCnt;
|
||||
mTimestamp = timestamp;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public String getThumbnail() {
|
||||
return mThumbnail;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public int getMediaCnt() {
|
||||
return mMediaCnt;
|
||||
}
|
||||
|
||||
public void setMediaCnt(int cnt) {
|
||||
mMediaCnt = cnt;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
public void addSize(long bytes) {
|
||||
mSize += bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object object) {
|
||||
final Directory directory = (Directory) object;
|
||||
int res;
|
||||
if ((mSorting & Constants.SORT_BY_NAME) != 0) {
|
||||
res = mPath.compareTo(directory.getPath());
|
||||
} else if ((mSorting & Constants.SORT_BY_DATE) != 0) {
|
||||
res = (mTimestamp > directory.getTimestamp()) ? 1 : -1;
|
||||
} else {
|
||||
res = (mSize > directory.getSize()) ? 1 : -1;
|
||||
}
|
||||
|
||||
if ((mSorting & Constants.SORT_DESCENDING) != 0) {
|
||||
res *= -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Directory {" +
|
||||
"path=" + getPath() +
|
||||
", thumbnail=" + getThumbnail() +
|
||||
", name=" + getName() +
|
||||
", timestamp=" + getTimestamp() +
|
||||
", mediaCnt=" + getMediaCnt() + "}";
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.simplemobiletools.gallery.models;
|
||||
|
||||
import com.simplemobiletools.gallery.Constants;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Medium implements Serializable, Comparable {
|
||||
private static final long serialVersionUID = -6543139465975455L;
|
||||
private final boolean mIsVideo;
|
||||
private final long mTimestamp;
|
||||
private final long mSize;
|
||||
public static int mSorting;
|
||||
private String mPath;
|
||||
|
||||
public Medium(String path, boolean isVideo, long timestamp, long size) {
|
||||
mPath = path;
|
||||
mIsVideo = isVideo;
|
||||
mTimestamp = timestamp;
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public boolean getIsVideo() {
|
||||
return mIsVideo;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return mTimestamp;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
public boolean isGif() {
|
||||
return getPath().toLowerCase().endsWith(".gif");
|
||||
}
|
||||
|
||||
public boolean isImage() {
|
||||
return !isGif() && !getIsVideo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object object) {
|
||||
final Medium medium = (Medium) object;
|
||||
int res;
|
||||
if ((mSorting & Constants.SORT_BY_NAME) != 0) {
|
||||
res = mPath.compareTo(medium.getPath());
|
||||
} else if ((mSorting & Constants.SORT_BY_DATE) != 0) {
|
||||
res = (mTimestamp > medium.getTimestamp()) ? 1 : -1;
|
||||
} else {
|
||||
res = (mSize > medium.getSize()) ? 1 : -1;
|
||||
}
|
||||
|
||||
if ((mSorting & Constants.SORT_DESCENDING) != 0) {
|
||||
res *= -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Medium {" +
|
||||
"isVideo=" + getIsVideo() +
|
||||
", timestamp=" + getTimestamp() +
|
||||
", size=" + getSize() +
|
||||
", path=" + getPath() + "}";
|
||||
}
|
||||
}
|
||||
86
app/src/main/kotlin/com/simplemobiletools/gallery/Config.kt
Normal file
@@ -0,0 +1,86 @@
|
||||
package com.simplemobiletools.gallery
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import java.util.*
|
||||
|
||||
class Config private constructor(context: Context) {
|
||||
private val mPrefs: SharedPreferences
|
||||
|
||||
companion object {
|
||||
fun newInstance(context: Context): Config {
|
||||
return Config(context)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
mPrefs = context.getSharedPreferences(Constants.PREFS_KEY, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
var isFirstRun: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.IS_FIRST_RUN, true)
|
||||
set(isFirstRun) = mPrefs.edit().putBoolean(Constants.IS_FIRST_RUN, isFirstRun).apply()
|
||||
|
||||
var isDarkTheme: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.IS_DARK_THEME, true)
|
||||
set(isDarkTheme) = mPrefs.edit().putBoolean(Constants.IS_DARK_THEME, isDarkTheme).apply()
|
||||
|
||||
var isSameSorting: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.IS_SAME_SORTING, true)
|
||||
set(isSameSorting) = mPrefs.edit().putBoolean(Constants.IS_SAME_SORTING, isSameSorting).apply()
|
||||
|
||||
var sorting: Int
|
||||
get() = if (isSameSorting) directorySorting else mPrefs.getInt(Constants.SORT_ORDER, Constants.SORT_BY_DATE or Constants.SORT_DESCENDING)
|
||||
set(order) = if (isSameSorting) directorySorting = order else mPrefs.edit().putInt(Constants.SORT_ORDER, order).apply()
|
||||
|
||||
var directorySorting: Int
|
||||
get() = mPrefs.getInt(Constants.DIRECTORY_SORT_ORDER, Constants.SORT_BY_DATE or Constants.SORT_DESCENDING)
|
||||
set(order) = mPrefs.edit().putInt(Constants.DIRECTORY_SORT_ORDER, order).apply()
|
||||
|
||||
var showHiddenFolders: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.SHOW_HIDDEN_FOLDERS, false)
|
||||
set(showHiddenFolders) = mPrefs.edit().putBoolean(Constants.SHOW_HIDDEN_FOLDERS, showHiddenFolders).apply()
|
||||
|
||||
fun addHiddenDirectory(path: String) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.add(path)
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
}
|
||||
|
||||
fun addHiddenDirectories(paths: Set<String>) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.addAll(paths)
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
}
|
||||
|
||||
fun removeHiddenDirectory(path: String) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.remove(path)
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
}
|
||||
|
||||
fun removeHiddenDirectories(paths: Set<String>) {
|
||||
val hiddenFolders = hiddenFolders
|
||||
hiddenFolders.removeAll(paths)
|
||||
mPrefs.edit().putStringSet(Constants.HIDDEN_FOLDERS, hiddenFolders).apply()
|
||||
}
|
||||
|
||||
val hiddenFolders: MutableSet<String>
|
||||
get() = mPrefs.getStringSet(Constants.HIDDEN_FOLDERS, HashSet<String>())
|
||||
|
||||
fun getIsFolderHidden(path: String): Boolean {
|
||||
return hiddenFolders.contains(path)
|
||||
}
|
||||
|
||||
var autoplayVideos: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.AUTOPLAY_VIDEOS, false)
|
||||
set(autoplay) = mPrefs.edit().putBoolean(Constants.AUTOPLAY_VIDEOS, autoplay).apply()
|
||||
|
||||
var treeUri: String
|
||||
get() = mPrefs.getString(Constants.TREE_URI, "")
|
||||
set(uri) = mPrefs.edit().putString(Constants.TREE_URI, uri).apply()
|
||||
|
||||
var displayFileNames: Boolean
|
||||
get() = mPrefs.getBoolean(Constants.DISPLAY_FILE_NAMES, false)
|
||||
set(display) = mPrefs.edit().putBoolean(Constants.DISPLAY_FILE_NAMES, display).apply()
|
||||
}
|
||||
126
app/src/main/kotlin/com/simplemobiletools/gallery/Utils.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.simplemobiletools.gallery
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyCharacterMap
|
||||
import android.view.KeyEvent
|
||||
import android.view.ViewConfiguration
|
||||
import android.webkit.MimeTypeMap
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class Utils {
|
||||
companion object {
|
||||
fun getFilename(context: Context, path: String): String {
|
||||
val humanized = context.humanizePath(path)
|
||||
return humanized.substring(humanized.lastIndexOf("/") + 1)
|
||||
}
|
||||
|
||||
fun showToast(context: Context, resId: Int) = context.toast(resId)
|
||||
|
||||
fun getActionBarHeight(context: Context, res: Resources): Int {
|
||||
val tv = TypedValue()
|
||||
var height = 0
|
||||
if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
|
||||
height = TypedValue.complexToDimensionPixelSize(tv.data, res.displayMetrics)
|
||||
}
|
||||
return height
|
||||
}
|
||||
|
||||
fun getStatusBarHeight(res: Resources): Int {
|
||||
val id = res.getIdentifier("status_bar_height", "dimen", "android")
|
||||
return if (id > 0) {
|
||||
res.getDimensionPixelSize(id)
|
||||
} else
|
||||
0
|
||||
}
|
||||
|
||||
fun getNavBarHeight(res: Resources): Int {
|
||||
val id = res.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (id > 0) {
|
||||
res.getDimensionPixelSize(id)
|
||||
} else
|
||||
0
|
||||
}
|
||||
|
||||
fun hasNavBar(act: Activity): Boolean {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
val display = act.windowManager.defaultDisplay
|
||||
|
||||
val realDisplayMetrics = DisplayMetrics()
|
||||
display.getRealMetrics(realDisplayMetrics)
|
||||
|
||||
val realHeight = realDisplayMetrics.heightPixels
|
||||
val realWidth = realDisplayMetrics.widthPixels
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
display.getMetrics(displayMetrics)
|
||||
|
||||
val displayHeight = displayMetrics.heightPixels
|
||||
val displayWidth = displayMetrics.widthPixels
|
||||
|
||||
realWidth - displayWidth > 0 || realHeight - displayHeight > 0
|
||||
} else {
|
||||
val hasMenuKey = ViewConfiguration.get(act).hasPermanentMenuKey()
|
||||
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
|
||||
!hasMenuKey && !hasBackKey
|
||||
}
|
||||
}
|
||||
|
||||
fun hasStoragePermission(context: Context) = context.hasStoragePermission()
|
||||
|
||||
fun getMimeType(url: String): String {
|
||||
val extension = MimeTypeMap.getFileExtensionFromUrl(url)
|
||||
return if (extension != null) {
|
||||
MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
|
||||
} else
|
||||
""
|
||||
}
|
||||
|
||||
fun shareMedium(medium: Medium, activity: Activity) {
|
||||
val shareTitle = activity.resources.getString(R.string.share_via)
|
||||
val intent = Intent()
|
||||
val file = File(medium.path)
|
||||
val uri = Uri.fromFile(file)
|
||||
intent.action = Intent.ACTION_SEND
|
||||
intent.putExtra(Intent.EXTRA_STREAM, uri)
|
||||
intent.type = medium.getMimeType()
|
||||
activity.startActivity(Intent.createChooser(intent, shareTitle))
|
||||
}
|
||||
|
||||
fun getRealPathFromURI(context: Context, uri: Uri): String? {
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
val projection = arrayOf(MediaStore.Images.Media.DATA)
|
||||
cursor = context.contentResolver.query(uri, projection, null, null, null)
|
||||
val index = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
||||
cursor.moveToFirst()
|
||||
return cursor.getString(index)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
fun scanPath(context: Context, path: String) = context.scanPath(path) {}
|
||||
|
||||
fun scanFiles(context: Context, files: ArrayList<File>) = context.scanFiles(files) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import com.simplemobiletools.gallery.BuildConfig
|
||||
import com.simplemobiletools.gallery.R
|
||||
import kotlinx.android.synthetic.main.activity_about.*
|
||||
import java.util.*
|
||||
|
||||
class AboutActivity : SimpleActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_about)
|
||||
|
||||
setupEmail()
|
||||
setupCopyright()
|
||||
setupRateUs()
|
||||
setupInvite()
|
||||
setupLicense()
|
||||
setupFacebook()
|
||||
setupGPlus()
|
||||
}
|
||||
|
||||
private fun setupEmail() {
|
||||
val email = getString(R.string.email)
|
||||
val appName = getString(R.string.app_name)
|
||||
val href = "<a href=\"mailto:$email?subject=$appName\">$email</a>"
|
||||
about_email.text = Html.fromHtml(href)
|
||||
about_email.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
private fun setupCopyright() {
|
||||
val versionName = BuildConfig.VERSION_NAME
|
||||
val year = Calendar.getInstance().get(Calendar.YEAR)
|
||||
val copyrightText = String.format(getString(R.string.copyright), versionName, year)
|
||||
about_copyright.text = copyrightText
|
||||
}
|
||||
|
||||
private fun setupRateUs() {
|
||||
if (mConfig.isFirstRun) {
|
||||
about_rate_us.visibility = View.GONE
|
||||
} else {
|
||||
about_rate_us.setOnClickListener {
|
||||
val uri = Uri.parse("market://details?id=$packageName")
|
||||
try {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, uri))
|
||||
} catch (ignored: ActivityNotFoundException) {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getStoreUrl())))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setupInvite() {
|
||||
about_invite.setOnClickListener {
|
||||
val text = String.format(getString(R.string.share_text), getString(R.string.app_name), getStoreUrl())
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name))
|
||||
putExtra(Intent.EXTRA_TEXT, text)
|
||||
type = "text/plain"
|
||||
startActivity(Intent.createChooser(this, getString(R.string.invite_via)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setupLicense() {
|
||||
about_license.setOnClickListener {
|
||||
val intent = Intent(applicationContext, LicenseActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
fun setupFacebook() {
|
||||
about_facebook.setOnClickListener {
|
||||
var link = "https://www.facebook.com/simplemobiletools"
|
||||
try {
|
||||
packageManager.getPackageInfo("com.facebook.katana", 0)
|
||||
link = "fb://page/150270895341774"
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
|
||||
}
|
||||
}
|
||||
|
||||
fun setupGPlus() {
|
||||
about_gplus.setOnClickListener {
|
||||
val link = "https://plus.google.com/communities/104880861558693868382"
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStoreUrl() = "https://play.google.com/store/apps/details?id=$packageName"
|
||||
}
|
||||
@@ -2,23 +2,28 @@ package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Bitmap
|
||||
import android.media.MediaScannerConnection
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
||||
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
||||
import com.simplemobiletools.filepicker.extensions.scanPath
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.Utils
|
||||
import com.simplemobiletools.gallery.extensions.toast
|
||||
import com.simplemobiletools.gallery.dialogs.SaveAsDialog
|
||||
import com.theartofdev.edmodo.cropper.CropImageView
|
||||
import kotlinx.android.synthetic.main.activity_edit.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener {
|
||||
val TAG: String = EditActivity::class.java.simpleName
|
||||
|
||||
lateinit var uri: Uri
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -51,27 +56,39 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.save -> {
|
||||
return when (item.itemId) {
|
||||
R.id.save_as -> {
|
||||
crop_image_view.getCroppedImageAsync()
|
||||
return true
|
||||
true
|
||||
}
|
||||
R.id.rotate -> {
|
||||
crop_image_view.rotateImage(90)
|
||||
return true
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onCropImageComplete(view: CropImageView, result: CropImageView.CropResult) {
|
||||
if (result.error == null) {
|
||||
if (uri.scheme == "file") {
|
||||
saveBitmapToFile(result.bitmap, uri.path)
|
||||
SaveAsDialog(this, uri.path, object : SaveAsDialog.OnSaveAsListener {
|
||||
override fun onSaveAsSuccess(filename: String) {
|
||||
val parent = File(uri.path).parent
|
||||
val path = File(parent, filename).absolutePath
|
||||
saveBitmapToFile(result.bitmap, path)
|
||||
}
|
||||
})
|
||||
} else if (uri.scheme == "content") {
|
||||
val newPath = Utils.getRealPathFromURI(applicationContext, uri) ?: ""
|
||||
if (!newPath.isEmpty()) {
|
||||
saveBitmapToFile(result.bitmap, newPath)
|
||||
SaveAsDialog(this, newPath, object : SaveAsDialog.OnSaveAsListener {
|
||||
override fun onSaveAsSuccess(filename: String) {
|
||||
val parent = File(uri.path).parent
|
||||
val path = File(parent, filename).absolutePath
|
||||
saveBitmapToFile(result.bitmap, path)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
toast(R.string.image_editing_failed)
|
||||
finish()
|
||||
@@ -87,19 +104,26 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||
|
||||
private fun saveBitmapToFile(bitmap: Bitmap, path: String) {
|
||||
val file = File(path)
|
||||
if (!file.exists()) {
|
||||
toast(R.string.error_saving_file)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
var out: FileOutputStream? = null
|
||||
var out: OutputStream? = null
|
||||
try {
|
||||
out = FileOutputStream(file)
|
||||
if (needsStupidWritePermissions(path)) {
|
||||
if (isShowingPermDialog(file))
|
||||
return
|
||||
|
||||
var document = getFileDocument(path, mConfig.treeUri)
|
||||
if (!file.exists()) {
|
||||
document = document.createFile("", file.name)
|
||||
}
|
||||
out = contentResolver.openOutputStream(document.uri)
|
||||
} else {
|
||||
out = FileOutputStream(file)
|
||||
}
|
||||
|
||||
bitmap.compress(getCompressionFormat(file), 90, out)
|
||||
setResult(Activity.RESULT_OK, intent)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Crop compressing failed $e")
|
||||
Log.e(TAG, "Crop compressing failed $path $e")
|
||||
toast(R.string.image_editing_failed)
|
||||
finish()
|
||||
} finally {
|
||||
@@ -110,10 +134,14 @@ class EditActivity : SimpleActivity(), CropImageView.OnCropImageCompleteListener
|
||||
}
|
||||
}
|
||||
|
||||
MediaScannerConnection.scanFile(applicationContext, arrayOf(path), null, { path: String, uri: Uri ->
|
||||
scanPath(path) {
|
||||
setResult(Activity.RESULT_OK, intent)
|
||||
runOnUiThread {
|
||||
toast(R.string.file_saved)
|
||||
}
|
||||
|
||||
finish()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCompressionFormat(file: File): Bitmap.CompressFormat {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.simplemobiletools.gallery.R
|
||||
import kotlinx.android.synthetic.main.activity_license.*
|
||||
|
||||
class LicenseActivity : SimpleActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_license)
|
||||
|
||||
license_butterknife_title.setOnClickListener { openUrl(R.string.butterknife_url) }
|
||||
license_photoview_title.setOnClickListener { openUrl(R.string.photoview_url) }
|
||||
license_glide_title.setOnClickListener { openUrl(R.string.glide_url) }
|
||||
license_cropper_title.setOnClickListener { openUrl(R.string.cropper_url) }
|
||||
license_filepicker_title.setOnClickListener { openUrl(R.string.filepicker_url) }
|
||||
license_fileproperties_title.setOnClickListener { openUrl(R.string.fileproperties_url) }
|
||||
}
|
||||
|
||||
private fun openUrl(id: Int) {
|
||||
val url = resources.getString(id)
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(browserIntent)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.os.Bundle
|
||||
|
||||
class PhotoActivity : PhotoVideoActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
PhotoVideoActivity.mIsVideo = false
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.filepicker.extensions.getFilenameFromPath
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.fragments.PhotoFragment
|
||||
import com.simplemobiletools.gallery.fragments.VideoFragment
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import java.io.File
|
||||
|
||||
open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentClickListener {
|
||||
companion object {
|
||||
private var mUri: Uri? = null
|
||||
private var mFragment: ViewPagerFragment? = null
|
||||
private var mIsFullScreen = false
|
||||
var mIsVideo = false
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.fragment_holder)
|
||||
|
||||
mUri = intent.data ?: return
|
||||
|
||||
mIsFullScreen = true
|
||||
|
||||
val bundle = Bundle()
|
||||
val file = File(mUri!!.toString())
|
||||
val medium = Medium(file.name, mUri!!.toString(), mIsVideo, 0, file.length())
|
||||
bundle.putSerializable(Constants.MEDIUM, medium)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
mFragment = if (mIsVideo) VideoFragment() else PhotoFragment()
|
||||
mFragment!!.setListener(this)
|
||||
mFragment!!.arguments = bundle
|
||||
supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, mFragment).commit()
|
||||
}
|
||||
hideUI()
|
||||
|
||||
if (mUri!!.scheme == "content") {
|
||||
val proj = arrayOf(MediaStore.Images.Media.TITLE)
|
||||
val cursor = contentResolver.query(mUri!!, proj, null, null, null)
|
||||
if (cursor != null && cursor.count != 0) {
|
||||
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE)
|
||||
cursor.moveToFirst()
|
||||
title = cursor.getString(columnIndex)
|
||||
}
|
||||
cursor?.close()
|
||||
} else {
|
||||
title = mUri!!.toString().getFilenameFromPath()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
mFragment!!.updateItem()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.photo_video_menu, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.menu_share -> {
|
||||
shareMedium()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareMedium() {
|
||||
val shareTitle = resources.getString(R.string.share_via)
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_STREAM, mUri)
|
||||
type = if (mIsVideo) "video/*" else "image/*"
|
||||
startActivity(Intent.createChooser(this, shareTitle))
|
||||
}
|
||||
}
|
||||
|
||||
override fun fragmentClicked() {
|
||||
mIsFullScreen = !mIsFullScreen
|
||||
if (mIsFullScreen) {
|
||||
hideUI()
|
||||
} else {
|
||||
showUI()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.toast
|
||||
import com.theartofdev.edmodo.cropper.CropImageView
|
||||
import kotlinx.android.synthetic.main.activity_edit.*
|
||||
|
||||
@@ -87,14 +87,14 @@ class SetWallpaperActivity : SimpleActivity(), CropImageView.OnCropImageComplete
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
if (requestCode == PICK_IMAGE) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
handleImage(data)
|
||||
if (resultCode == Activity.RESULT_OK && resultData != null) {
|
||||
handleImage(resultData)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.TaskStackBuilder
|
||||
import com.simplemobiletools.gallery.R
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
|
||||
class SettingsActivity : SimpleActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
|
||||
setupDarkTheme()
|
||||
setupSameSorting()
|
||||
setupShowHiddenFolders()
|
||||
setupAutoplayVideos()
|
||||
}
|
||||
|
||||
private fun setupDarkTheme() {
|
||||
settings_dark_theme.isChecked = mConfig.isDarkTheme
|
||||
settings_dark_theme_holder.setOnClickListener {
|
||||
settings_dark_theme.toggle()
|
||||
mConfig.isDarkTheme = settings_dark_theme.isChecked
|
||||
restartActivity()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSameSorting() {
|
||||
settings_same_sorting.isChecked = mConfig.isSameSorting
|
||||
settings_same_sorting_holder.setOnClickListener {
|
||||
settings_same_sorting.toggle()
|
||||
mConfig.isSameSorting = settings_same_sorting.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupShowHiddenFolders() {
|
||||
settings_show_hidden_folders.isChecked = mConfig.showHiddenFolders
|
||||
settings_show_hidden_folders_holder.setOnClickListener {
|
||||
settings_show_hidden_folders.toggle()
|
||||
mConfig.showHiddenFolders = settings_show_hidden_folders.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAutoplayVideos() {
|
||||
settings_autoplay_videos_holder.setOnClickListener {
|
||||
settings_autoplay_videos.toggle()
|
||||
mConfig.autoplayVideos = settings_autoplay_videos.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun restartActivity() {
|
||||
TaskStackBuilder.create(applicationContext).addNextIntentWithParentStack(intent).startActivities()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.filepicker.extensions.isShowingWritePermissions
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.hideSystemUI
|
||||
import com.simplemobiletools.gallery.extensions.showSystemUI
|
||||
import java.io.File
|
||||
|
||||
open class SimpleActivity : AppCompatActivity() {
|
||||
lateinit var mConfig: Config
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mConfig = Config.newInstance(applicationContext)
|
||||
var theme = if (mConfig.isDarkTheme) R.style.AppTheme_Dark else R.style.AppTheme
|
||||
if (this is ViewPagerActivity || this is PhotoActivity || this is VideoActivity) {
|
||||
theme = if (mConfig.isDarkTheme) R.style.FullScreenTheme_Dark else R.style.FullScreenTheme
|
||||
}
|
||||
setTheme(theme)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
finish()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
if (requestCode == Constants.OPEN_DOCUMENT_TREE && resultCode == Activity.RESULT_OK && resultData != null) {
|
||||
saveTreeUri(resultData)
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
fun saveTreeUri(resultData: Intent) {
|
||||
val treeUri = resultData.data
|
||||
mConfig.treeUri = treeUri.toString()
|
||||
|
||||
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
contentResolver.takePersistableUriPermission(treeUri, takeFlags)
|
||||
}
|
||||
|
||||
fun isShowingPermDialog(file: File) = isShowingWritePermissions(file, mConfig.treeUri, Constants.OPEN_DOCUMENT_TREE)
|
||||
|
||||
fun hideUI() = hideSystemUI(supportActionBar, window)
|
||||
|
||||
fun showUI() = showSystemUI(supportActionBar, window)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.os.Bundle
|
||||
|
||||
class VideoActivity : PhotoVideoActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
PhotoVideoActivity.mIsVideo = true
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
package com.simplemobiletools.gallery.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
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.MyPagerAdapter
|
||||
import com.simplemobiletools.gallery.dialogs.CopyDialog
|
||||
import com.simplemobiletools.gallery.dialogs.RenameFileDialog
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import kotlinx.android.synthetic.main.activity_medium.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View.OnSystemUiVisibilityChangeListener, ViewPagerFragment.FragmentClickListener {
|
||||
private var mMedia: MutableList<Medium>? = null
|
||||
private var mPath = ""
|
||||
private var mDirectory = ""
|
||||
private var mToBeDeleted = ""
|
||||
private var mBeingDeleted = ""
|
||||
|
||||
private var mIsFullScreen = false
|
||||
private var mIsUndoShown = false
|
||||
private var mPos = 0
|
||||
|
||||
companion object {
|
||||
private val EDIT_IMAGE = 1
|
||||
private val SET_WALLPAPER = 2
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_medium)
|
||||
|
||||
if (!hasStoragePermission()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
val uri = intent.data
|
||||
if (uri != null) {
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
val proj = arrayOf(MediaStore.Images.Media.DATA)
|
||||
cursor = contentResolver.query(uri, proj, null, null, null)
|
||||
if (cursor != null) {
|
||||
val dataIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
|
||||
cursor.moveToFirst()
|
||||
mPath = cursor.getString(dataIndex)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
} else {
|
||||
mPath = intent.getStringExtra(Constants.MEDIUM)
|
||||
}
|
||||
|
||||
if (mPath.isEmpty()) {
|
||||
toast(R.string.unknown_error)
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
mPos = 0
|
||||
mIsFullScreen = true
|
||||
mToBeDeleted = ""
|
||||
mBeingDeleted = ""
|
||||
hideUI()
|
||||
|
||||
scanPath(mPath) {}
|
||||
addUndoMargin()
|
||||
mDirectory = File(mPath).parent
|
||||
mMedia = getMedia()
|
||||
if (isDirEmpty())
|
||||
return
|
||||
|
||||
val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, mMedia!!)
|
||||
view_pager.apply {
|
||||
adapter = pagerAdapter
|
||||
currentItem = mPos
|
||||
addOnPageChangeListener(this@ViewPagerActivity)
|
||||
}
|
||||
|
||||
window.decorView.setOnSystemUiVisibilityChangeListener(this)
|
||||
updateActionbarTitle()
|
||||
undo_delete.setOnClickListener { undoDeletion() }
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!hasStoragePermission()) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
fun undoDeletion() {
|
||||
mIsUndoShown = false
|
||||
mToBeDeleted = ""
|
||||
mBeingDeleted = ""
|
||||
undo_delete.visibility = View.GONE
|
||||
reloadViewPager()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.viewpager_menu, menu)
|
||||
menu.findItem(R.id.menu_set_as_wallpaper).isVisible = getCurrentMedium().isImage
|
||||
menu.findItem(R.id.menu_edit).isVisible = getCurrentMedium().isImage
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
deleteFile()
|
||||
return when (item.itemId) {
|
||||
R.id.menu_set_as_wallpaper -> {
|
||||
setAsWallpaper()
|
||||
true
|
||||
}
|
||||
R.id.menu_copy_move -> {
|
||||
displayCopyDialog()
|
||||
true
|
||||
}
|
||||
R.id.menu_open_with -> {
|
||||
openWith()
|
||||
true
|
||||
}
|
||||
R.id.menu_share -> {
|
||||
shareMedium()
|
||||
true
|
||||
}
|
||||
R.id.menu_delete -> {
|
||||
notifyDeletion()
|
||||
true
|
||||
}
|
||||
R.id.menu_rename -> {
|
||||
editMedium()
|
||||
true
|
||||
}
|
||||
R.id.menu_edit -> {
|
||||
openEditor()
|
||||
true
|
||||
}
|
||||
R.id.menu_properties -> {
|
||||
showProperties()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
val adapter = view_pager.adapter as MyPagerAdapter
|
||||
adapter.updateItems(mPos)
|
||||
}
|
||||
|
||||
private fun displayCopyDialog() {
|
||||
val files = ArrayList<File>()
|
||||
files.add(getCurrentFile())
|
||||
CopyDialog(this, files, object : CopyMoveTask.CopyMoveListener {
|
||||
override fun copySucceeded(deleted: Boolean, copiedAll: Boolean) {
|
||||
if (deleted) {
|
||||
reloadViewPager()
|
||||
toast(if (copiedAll) R.string.moving_success else R.string.moving_success_partial)
|
||||
} else {
|
||||
toast(if (copiedAll) R.string.copying_success else R.string.copying_success_partial)
|
||||
}
|
||||
}
|
||||
|
||||
override fun copyFailed() {
|
||||
toast(R.string.copy_move_failed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun openEditor() {
|
||||
val intent = Intent(Intent.ACTION_EDIT)
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), "image/*")
|
||||
val chooser = Intent.createChooser(intent, getString(R.string.edit_image_with))
|
||||
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
startActivityForResult(chooser, EDIT_IMAGE)
|
||||
} else {
|
||||
toast(R.string.no_editor_found)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setAsWallpaper() {
|
||||
val intent = Intent(Intent.ACTION_ATTACH_DATA)
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), "image/jpeg")
|
||||
val chooser = Intent.createChooser(intent, getString(R.string.set_as_wallpaper_with))
|
||||
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
startActivityForResult(chooser, SET_WALLPAPER)
|
||||
} else {
|
||||
toast(R.string.no_wallpaper_setter_found)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openWith() {
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(Uri.fromFile(getCurrentFile()), getCurrentMedium().getMimeType())
|
||||
val chooser = Intent.createChooser(intent, getString(R.string.open_with))
|
||||
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
startActivity(chooser)
|
||||
} else {
|
||||
toast(R.string.no_app_found)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showProperties() {
|
||||
PropertiesDialog(this, getCurrentFile().absolutePath, false)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
||||
if (requestCode == EDIT_IMAGE) {
|
||||
if (resultCode == Activity.RESULT_OK && resultData != null) {
|
||||
val adapter = view_pager.adapter as MyPagerAdapter
|
||||
adapter.updateItems(mPos)
|
||||
}
|
||||
} else if (requestCode == SET_WALLPAPER) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
toast(R.string.wallpaper_set_successfully)
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, resultData)
|
||||
}
|
||||
|
||||
private fun shareMedium() {
|
||||
Utils.shareMedium(getCurrentMedium(), this)
|
||||
}
|
||||
|
||||
private fun notifyDeletion() {
|
||||
if (isShowingPermDialog(File(mPath)))
|
||||
return
|
||||
|
||||
mToBeDeleted = getCurrentFile().absolutePath
|
||||
if (mMedia!!.size <= 1) {
|
||||
deleteFile()
|
||||
} else {
|
||||
toast(R.string.file_deleted)
|
||||
undo_delete.visibility = View.VISIBLE
|
||||
mIsUndoShown = true
|
||||
reloadViewPager()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteFile() {
|
||||
if (mToBeDeleted.isEmpty())
|
||||
return
|
||||
|
||||
mIsUndoShown = false
|
||||
mBeingDeleted = ""
|
||||
var mWasFileDeleted = false
|
||||
|
||||
val file = File(mToBeDeleted)
|
||||
if (needsStupidWritePermissions(mToBeDeleted)) {
|
||||
if (!isShowingPermDialog(file)) {
|
||||
val document = getFileDocument(mToBeDeleted, mConfig.treeUri)
|
||||
if (document.canWrite()) {
|
||||
mWasFileDeleted = document.delete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mWasFileDeleted = file.delete()
|
||||
}
|
||||
|
||||
if (mWasFileDeleted) {
|
||||
mBeingDeleted = mToBeDeleted
|
||||
scanPath(mToBeDeleted) { scanCompleted() }
|
||||
}
|
||||
|
||||
mToBeDeleted = ""
|
||||
undo_delete.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun isDirEmpty(): Boolean {
|
||||
return if (mMedia!!.size <= 0) {
|
||||
deleteDirectoryIfEmpty()
|
||||
finish()
|
||||
true
|
||||
} else
|
||||
false
|
||||
}
|
||||
|
||||
private fun editMedium() {
|
||||
RenameFileDialog(this, getCurrentFile(), object : RenameFileDialog.OnRenameFileListener {
|
||||
override fun onRenameFileSuccess(newFile: File) {
|
||||
mMedia!![view_pager.currentItem].path = newFile.absolutePath
|
||||
updateActionbarTitle()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun reloadViewPager() {
|
||||
val adapter = view_pager.adapter as MyPagerAdapter
|
||||
val curPos = view_pager.currentItem
|
||||
mMedia = getMedia()
|
||||
if (isDirEmpty())
|
||||
return
|
||||
|
||||
view_pager.adapter = null
|
||||
adapter.updateItems(mMedia!!)
|
||||
view_pager.adapter = adapter
|
||||
|
||||
val newPos = Math.min(curPos, adapter.count)
|
||||
view_pager.currentItem = newPos
|
||||
updateActionbarTitle()
|
||||
}
|
||||
|
||||
private fun deleteDirectoryIfEmpty() {
|
||||
val file = File(mDirectory)
|
||||
if (file.isDirectory && file.listFiles().size == 0) {
|
||||
file.delete()
|
||||
}
|
||||
|
||||
scanPath(mDirectory) {}
|
||||
}
|
||||
|
||||
private fun getMedia(): MutableList<Medium> {
|
||||
val media = ArrayList<Medium>()
|
||||
val invalidFiles = ArrayList<File>()
|
||||
for (i in 0..1) {
|
||||
var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
if (i == 1) {
|
||||
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
}
|
||||
|
||||
val where = "${MediaStore.Images.Media.DATA} like ? "
|
||||
val args = arrayOf("$mDirectory%")
|
||||
val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED, MediaStore.Images.Media.SIZE)
|
||||
val cursor = contentResolver.query(uri, columns, where, args, null)
|
||||
val pattern = "${Pattern.quote(mDirectory)}/[^/]*"
|
||||
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
|
||||
do {
|
||||
val curPath = cursor.getString(pathIndex) ?: continue
|
||||
|
||||
val file = File(curPath)
|
||||
if (!file.exists()) {
|
||||
invalidFiles.add(file)
|
||||
continue
|
||||
}
|
||||
|
||||
if (curPath.matches(pattern.toRegex()) && curPath != mToBeDeleted && curPath != mBeingDeleted) {
|
||||
val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)
|
||||
val timestamp = cursor.getLong(dateIndex)
|
||||
|
||||
val sizeIndex = cursor.getColumnIndex(MediaStore.Images.Media.SIZE)
|
||||
val size = cursor.getLong(sizeIndex)
|
||||
media.add(Medium(file.name, curPath, i == 1, timestamp, size))
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
scanFiles(invalidFiles) {}
|
||||
Medium.sorting = mConfig.sorting
|
||||
Collections.sort(media)
|
||||
var j = 0
|
||||
for (medium in media) {
|
||||
if (medium.path == mPath) {
|
||||
mPos = j
|
||||
break
|
||||
}
|
||||
j++
|
||||
}
|
||||
return media
|
||||
}
|
||||
|
||||
override fun fragmentClicked() {
|
||||
deleteFile()
|
||||
mIsFullScreen = !mIsFullScreen
|
||||
if (mIsFullScreen) {
|
||||
hideUI()
|
||||
} else {
|
||||
showUI()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateActionbarTitle() {
|
||||
title = mMedia!![view_pager.currentItem].path.getFilenameFromPath()
|
||||
}
|
||||
|
||||
private fun getCurrentMedium(): Medium {
|
||||
if (mPos >= mMedia!!.size)
|
||||
mPos = mMedia!!.size - 1
|
||||
return mMedia!![mPos]
|
||||
}
|
||||
|
||||
private fun getCurrentFile() = File(getCurrentMedium().path)
|
||||
|
||||
private fun addUndoMargin() {
|
||||
val res = resources
|
||||
val params = undo_delete.layoutParams as RelativeLayout.LayoutParams
|
||||
val topMargin = Utils.getStatusBarHeight(res) + Utils.getActionBarHeight(applicationContext, res)
|
||||
var rightMargin = params.rightMargin
|
||||
|
||||
if (res.configuration.orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||
rightMargin += Utils.getNavBarHeight(res)
|
||||
}
|
||||
|
||||
params.setMargins(params.leftMargin, topMargin, rightMargin, params.bottomMargin)
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
updateActionbarTitle()
|
||||
mPos = position
|
||||
supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
|
||||
val adapter = view_pager.adapter as MyPagerAdapter
|
||||
adapter.itemDragged(mPos)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSystemUiVisibilityChange(visibility: Int) {
|
||||
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
|
||||
mIsFullScreen = false
|
||||
}
|
||||
|
||||
val adapter = view_pager.adapter as MyPagerAdapter
|
||||
adapter.updateUiVisibility(mIsFullScreen, mPos)
|
||||
}
|
||||
|
||||
private fun scanCompleted() {
|
||||
mBeingDeleted = ""
|
||||
runOnUiThread {
|
||||
if (mMedia != null && mMedia!!.size <= 1) {
|
||||
reloadViewPager()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
deleteFile()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
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 com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.signature.StringSignature
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.directory_item.view.*
|
||||
import kotlinx.android.synthetic.main.directory_tmb.view.*
|
||||
|
||||
class DirectoryAdapter(private val mContext: Context, private val mDirs: MutableList<Directory>) : BaseAdapter() {
|
||||
private val mInflater: LayoutInflater
|
||||
|
||||
init {
|
||||
mInflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
|
||||
return convertView
|
||||
}
|
||||
|
||||
private fun formatDirectoryName(dir: Directory): String {
|
||||
return dir.name
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return mDirs.size
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return mDirs[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
internal class ViewHolder(view: View) {
|
||||
val dirName: TextView = view.dir_name
|
||||
val photoCnt: TextView = view.photo_cnt
|
||||
val dirThumbnail: ImageView = view.dir_thumbnail
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
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 com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.signature.StringSignature
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.extensions.beVisibleIf
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import kotlinx.android.synthetic.main.photo_video_item.view.*
|
||||
import kotlinx.android.synthetic.main.photo_video_tmb.view.*
|
||||
|
||||
class MediaAdapter(private val context: Context, private val media: MutableList<Medium>) : BaseAdapter() {
|
||||
private val mInflater: LayoutInflater
|
||||
var displayFilenames = false
|
||||
|
||||
init {
|
||||
mInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
displayFilenames = Config.newInstance(context).displayFileNames
|
||||
}
|
||||
|
||||
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
|
||||
var convertView = view
|
||||
val medium = media[position]
|
||||
val viewHolder: ViewHolder
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.photo_video_item, parent, false)
|
||||
viewHolder = ViewHolder(convertView)
|
||||
convertView!!.tag = viewHolder
|
||||
} else {
|
||||
viewHolder = convertView.tag as ViewHolder
|
||||
}
|
||||
|
||||
viewHolder.playOutline.visibility = if (medium.isVideo) View.VISIBLE else View.GONE
|
||||
|
||||
viewHolder.fileName.beVisibleIf(displayFilenames)
|
||||
if (displayFilenames)
|
||||
viewHolder.fileName.text = medium.name
|
||||
val path = medium.path
|
||||
val timestampSignature = StringSignature(medium.timestamp.toString())
|
||||
if (medium.isGif) {
|
||||
Glide.with(context).load(path).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature).into(viewHolder.photoThumbnail)
|
||||
} else {
|
||||
Glide.with(context).load(path).diskCacheStrategy(DiskCacheStrategy.NONE).signature(timestampSignature)
|
||||
.placeholder(R.color.tmb_background).centerCrop().crossFade().into(viewHolder.photoThumbnail)
|
||||
}
|
||||
|
||||
return convertView
|
||||
}
|
||||
|
||||
fun updateDisplayFilenames(display: Boolean) {
|
||||
displayFilenames = display
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return media.size
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return media[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return 0
|
||||
}
|
||||
|
||||
fun updateItems(newPhotos: List<Medium>) {
|
||||
media.clear()
|
||||
media.addAll(newPhotos)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
internal class ViewHolder(view: View) {
|
||||
val photoThumbnail: ImageView = view.medium_thumbnail
|
||||
val playOutline: View = view.play_outline
|
||||
val fileName: TextView = view.file_name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.simplemobiletools.gallery.adapters
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.app.FragmentStatePagerAdapter
|
||||
import android.util.SparseArray
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
import com.simplemobiletools.gallery.activities.ViewPagerActivity
|
||||
import com.simplemobiletools.gallery.fragments.PhotoFragment
|
||||
import com.simplemobiletools.gallery.fragments.VideoFragment
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
|
||||
class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val media: MutableList<Medium>) : FragmentStatePagerAdapter(fm) {
|
||||
private val mFragments: SparseArray<ViewPagerFragment>
|
||||
|
||||
init {
|
||||
mFragments = SparseArray<ViewPagerFragment>()
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return media.size
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val medium = media[position]
|
||||
val bundle = Bundle()
|
||||
bundle.putSerializable(Constants.MEDIUM, medium)
|
||||
val fragment: ViewPagerFragment
|
||||
|
||||
if (medium.isVideo) {
|
||||
fragment = VideoFragment()
|
||||
} else {
|
||||
fragment = PhotoFragment()
|
||||
}
|
||||
|
||||
mFragments.put(position, fragment)
|
||||
fragment.arguments = bundle
|
||||
fragment.setListener(activity)
|
||||
return fragment
|
||||
}
|
||||
|
||||
fun itemDragged(pos: Int) {
|
||||
mFragments[pos]?.itemDragged()
|
||||
}
|
||||
|
||||
fun updateUiVisibility(isFullscreen: Boolean, pos: Int) {
|
||||
for (i in -1..1) {
|
||||
val fragment = mFragments[pos + i]
|
||||
fragment?.systemUiVisibilityChanged(isFullscreen)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateItems(pos: Int) {
|
||||
for (i in -1..1) {
|
||||
val fragment = mFragments[pos + i]
|
||||
fragment?.updateItem()
|
||||
}
|
||||
}
|
||||
|
||||
fun updateItems(newPaths: List<Medium>) {
|
||||
media.clear()
|
||||
media.addAll(newPaths)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.simplemobiletools.gallery.asynctasks
|
||||
|
||||
import android.content.Context
|
||||
import android.os.AsyncTask
|
||||
import android.provider.MediaStore
|
||||
import com.simplemobiletools.filepicker.extensions.scanFiles
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.Utils
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
||||
class GetDirectoriesAsynctask(val context: Context, val isPickVideo: Boolean, val isPickImage: Boolean,
|
||||
val mToBeDeleted: List<String>, val listener: GetDirectoriesListener) : AsyncTask<Void, Void, ArrayList<Directory>>() {
|
||||
lateinit var mConfig: Config
|
||||
lateinit var mListener: WeakReference<GetDirectoriesListener>
|
||||
|
||||
override fun onPreExecute() {
|
||||
super.onPreExecute()
|
||||
mConfig = Config.newInstance(context)
|
||||
mListener = WeakReference(listener)
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Void): ArrayList<Directory> {
|
||||
val directories = LinkedHashMap<String, Directory>()
|
||||
val invalidFiles = ArrayList<File>()
|
||||
for (i in 0..1) {
|
||||
if ((isPickVideo) && i == 0)
|
||||
continue
|
||||
|
||||
var uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
if (i == 1) {
|
||||
if (isPickImage)
|
||||
continue
|
||||
|
||||
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
}
|
||||
val columns = arrayOf(MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_MODIFIED)
|
||||
val order = getSortOrder()
|
||||
val cursor = context.contentResolver.query(uri, columns, null, null, order)
|
||||
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
val pathIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
|
||||
do {
|
||||
val fullPath: String = cursor.getString(pathIndex) ?: continue
|
||||
val file = File(fullPath)
|
||||
val parentDir = file.parent
|
||||
|
||||
if (!file.exists()) {
|
||||
invalidFiles.add(file)
|
||||
continue
|
||||
}
|
||||
|
||||
val dateIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED)
|
||||
val timestamp = cursor.getLong(dateIndex)
|
||||
if (directories.containsKey(parentDir)) {
|
||||
val directory: Directory = directories[parentDir]!!
|
||||
val newImageCnt = directory.mediaCnt + 1
|
||||
directory.mediaCnt = newImageCnt
|
||||
directory.addSize(file.length())
|
||||
} else if (!mToBeDeleted.contains(parentDir)) {
|
||||
var dirName = Utils.getFilename(context, parentDir)
|
||||
if (mConfig.getIsFolderHidden(parentDir)) {
|
||||
dirName += " ${context.resources.getString(R.string.hidden)}"
|
||||
}
|
||||
|
||||
directories.put(parentDir, Directory(parentDir, fullPath, dirName, 1, timestamp, file.length()))
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
}
|
||||
|
||||
val dirs = ArrayList(directories.values)
|
||||
filterDirectories(dirs)
|
||||
Directory.sorting = mConfig.directorySorting
|
||||
Collections.sort<Directory>(dirs)
|
||||
|
||||
context.scanFiles(invalidFiles) {}
|
||||
return dirs
|
||||
}
|
||||
|
||||
override fun onPostExecute(dirs: ArrayList<Directory>) {
|
||||
super.onPostExecute(dirs)
|
||||
val listener = mListener.get()
|
||||
listener?.gotDirectories(dirs)
|
||||
}
|
||||
|
||||
// sort the files at querying too, just to get the correct thumbnail
|
||||
private fun getSortOrder(): String {
|
||||
val sorting = mConfig.directorySorting
|
||||
var sortBy = MediaStore.Images.Media.DATE_MODIFIED
|
||||
if (sorting and Constants.SORT_BY_NAME != 0) {
|
||||
sortBy = MediaStore.Images.Media.DATA
|
||||
}
|
||||
|
||||
if (sorting and Constants.SORT_DESCENDING != 0) {
|
||||
sortBy += " DESC"
|
||||
}
|
||||
return sortBy
|
||||
}
|
||||
|
||||
private fun filterDirectories(dirs: MutableList<Directory>) {
|
||||
if (!mConfig.showHiddenFolders)
|
||||
removeHiddenFolders(dirs)
|
||||
|
||||
removeNoMediaFolders(dirs)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
dirs.removeAll(ignoreDirs)
|
||||
}
|
||||
|
||||
private fun removeNoMediaFolders(dirs: MutableList<Directory>) {
|
||||
val ignoreDirs = ArrayList<Directory>()
|
||||
for (d in dirs) {
|
||||
val dir = File(d.path)
|
||||
if (dir.exists() && dir.isDirectory) {
|
||||
val res = dir.list { file, filename -> filename == ".nomedia" }
|
||||
|
||||
if (res != null && res.size > 0)
|
||||
ignoreDirs.add(d)
|
||||
}
|
||||
}
|
||||
|
||||
dirs.removeAll(ignoreDirs)
|
||||
}
|
||||
|
||||
interface GetDirectoriesListener {
|
||||
fun gotDirectories(dirs: ArrayList<Directory>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.support.v4.util.Pair
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask
|
||||
import com.simplemobiletools.filepicker.extensions.humanizePath
|
||||
import com.simplemobiletools.filepicker.extensions.isPathOnSD
|
||||
import com.simplemobiletools.filepicker.extensions.scanFiles
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import kotlinx.android.synthetic.main.dialog_copy_move.view.*
|
||||
import java.io.File
|
||||
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 sourcePath = files[0].parent.trimEnd('/')
|
||||
var destinationPath = ""
|
||||
|
||||
view.source.text = context.humanizePath(sourcePath)
|
||||
|
||||
view.destination.setOnClickListener {
|
||||
PickAlbumDialog(activity, object : PickAlbumDialog.OnPickAlbumListener {
|
||||
override fun onSuccess(path: String) {
|
||||
destinationPath = path
|
||||
view.destination.text = context.humanizePath(path)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.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)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener({
|
||||
if (destinationPath == context.resources.getString(R.string.select_destination) || destinationPath.isEmpty()) {
|
||||
context.toast(R.string.please_select_destination)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (view.source.text.trimEnd('/') == destinationPath.trimEnd('/')) {
|
||||
context.toast(R.string.source_and_destination_same)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val destinationDir = File(destinationPath)
|
||||
if (!destinationDir.exists()) {
|
||||
context.toast(R.string.invalid_destination)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (files.size == 1) {
|
||||
val newFile = File(files[0].path)
|
||||
if (File(destinationPath, newFile.name).exists()) {
|
||||
context.toast(R.string.already_exists)
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
|
||||
if (activity.isShowingPermDialog(destinationDir)) {
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val config = Config.newInstance(context)
|
||||
if (view.dialog_radio_group.checkedRadioButtonId == R.id.dialog_radio_copy) {
|
||||
context.toast(R.string.copying)
|
||||
val pair = Pair<ArrayList<File>, File>(files, destinationDir)
|
||||
CopyMoveTask(context, false, config.treeUri, true, copyMoveListener).execute(pair)
|
||||
dismiss()
|
||||
} else {
|
||||
if (context.isPathOnSD(sourcePath) || context.isPathOnSD(destinationPath)) {
|
||||
context.toast(R.string.moving)
|
||||
val pair = Pair<ArrayList<File>, File>(files, destinationDir)
|
||||
CopyMoveTask(context, true, config.treeUri, true, copyMoveListener).execute(pair)
|
||||
dismiss()
|
||||
} else {
|
||||
val updatedFiles = ArrayList<File>(files.size * 2)
|
||||
updatedFiles.addAll(files)
|
||||
for (file in files) {
|
||||
val destination = File(destinationDir, file.name)
|
||||
if (file.renameTo(destination))
|
||||
updatedFiles.add(destination)
|
||||
}
|
||||
|
||||
context.scanFiles(updatedFiles) {}
|
||||
dismiss()
|
||||
copyMoveListener.copySucceeded(true, files.size * 2 == updatedFiles.size)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
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.adapters.DirectoryAdapter
|
||||
import com.simplemobiletools.gallery.asynctasks.GetDirectoriesAsynctask
|
||||
import com.simplemobiletools.gallery.models.Directory
|
||||
import kotlinx.android.synthetic.main.activity_main.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
|
||||
|
||||
init {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_album_picker, null)
|
||||
grid = view.directories_grid
|
||||
|
||||
dialog = AlertDialog.Builder(activity)
|
||||
.setTitle(context.resources.getString(R.string.select_destination))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
show()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
override fun gotDirectories(dirs: ArrayList<Directory>) {
|
||||
this.dirs = dirs
|
||||
|
||||
val adapter = DirectoryAdapter(context, dirs)
|
||||
|
||||
grid?.adapter = adapter
|
||||
grid?.onItemClickListener = this
|
||||
}
|
||||
|
||||
interface OnPickAlbumListener {
|
||||
fun onSuccess(path: String)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import kotlinx.android.synthetic.main.rename_directory.view.*
|
||||
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)
|
||||
|
||||
view.directory_name.setText(dir.name)
|
||||
view.directory_path.text = "${context.humanizePath(dir.parent)}/"
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.rename_folder))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener({
|
||||
val newDirName = view.directory_name.value
|
||||
|
||||
if (newDirName.isEmpty()) {
|
||||
context.toast(R.string.rename_folder_empty)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val updatedFiles = ArrayList<String>()
|
||||
updatedFiles.add(dir.absolutePath)
|
||||
val newDir = File(dir.parent, newDirName)
|
||||
|
||||
if (newDir.exists()) {
|
||||
context.toast(R.string.rename_folder_exists)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (context.needsStupidWritePermissions(dir.absolutePath)) {
|
||||
if (activity.isShowingPermDialog(dir))
|
||||
return@setOnClickListener
|
||||
|
||||
val document = context.getFileDocument(dir.absolutePath, Config.newInstance(context).treeUri)
|
||||
if (document.canWrite())
|
||||
document.renameTo(newDirName)
|
||||
sendSuccess(updatedFiles, newDir)
|
||||
dismiss()
|
||||
} else if (dir.renameTo(newDir)) {
|
||||
sendSuccess(updatedFiles, newDir)
|
||||
dismiss()
|
||||
} else {
|
||||
context.toast(R.string.rename_folder_error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendSuccess(updatedFiles: ArrayList<String>, newDir: File) {
|
||||
context.toast(R.string.renaming_folder)
|
||||
val files = newDir.listFiles()
|
||||
for (file in files) {
|
||||
updatedFiles.add(file.absolutePath)
|
||||
}
|
||||
|
||||
updatedFiles.add(newDir.absolutePath)
|
||||
val changedFiles = updatedFiles.toTypedArray()
|
||||
listener.onRenameDirSuccess(changedFiles)
|
||||
}
|
||||
|
||||
interface OnRenameDirListener {
|
||||
fun onRenameDirSuccess(changedFiles: Array<String>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
import com.simplemobiletools.gallery.Config
|
||||
import com.simplemobiletools.gallery.R
|
||||
import com.simplemobiletools.gallery.activities.SimpleActivity
|
||||
import kotlinx.android.synthetic.main.rename_file.view.*
|
||||
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 fullName = file.name
|
||||
val dotAt = fullName.lastIndexOf(".")
|
||||
var name = fullName
|
||||
|
||||
if (dotAt > 0) {
|
||||
name = fullName.substring(0, dotAt)
|
||||
val extension = fullName.substring(dotAt + 1)
|
||||
view.file_extension.setText(extension)
|
||||
}
|
||||
|
||||
view.file_name.setText(name)
|
||||
view.file_path.text = "${context.humanizePath(file.parent)}/"
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.rename_file))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener({
|
||||
val fileName = view.file_name.value
|
||||
val extension = view.file_extension.value
|
||||
|
||||
if (fileName.isEmpty() || extension.isEmpty()) {
|
||||
context.toast(R.string.filename_cannot_be_empty)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val newFile = File(file.parent, "$fileName.$extension")
|
||||
|
||||
if (context.needsStupidWritePermissions(file.absolutePath)) {
|
||||
if (activity.isShowingPermDialog(file))
|
||||
return@setOnClickListener
|
||||
|
||||
val document = context.getFileDocument(file.absolutePath, Config.newInstance(context).treeUri)
|
||||
if (document.canWrite())
|
||||
document.renameTo(newFile.name)
|
||||
sendSuccess(file, newFile)
|
||||
dismiss()
|
||||
} else if (file.renameTo(newFile)) {
|
||||
sendSuccess(file, newFile)
|
||||
dismiss()
|
||||
} else {
|
||||
context.toast(R.string.rename_file_error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendSuccess(currFile: File, newFile: File) {
|
||||
val changedFiles = arrayListOf(currFile, newFile)
|
||||
activity.scanFiles(changedFiles) {}
|
||||
listener.onRenameFileSuccess(newFile)
|
||||
}
|
||||
|
||||
interface OnRenameFileListener {
|
||||
fun onRenameFileSuccess(newFile: File)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.simplemobiletools.gallery.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.filepicker.extensions.getFilenameFromPath
|
||||
import com.simplemobiletools.filepicker.extensions.isAValidFilename
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import com.simplemobiletools.filepicker.extensions.value
|
||||
import com.simplemobiletools.gallery.R
|
||||
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)
|
||||
view.file_name.setText(path.getFilenameFromPath())
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(context.resources.getString(R.string.save_as))
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener({
|
||||
val filename = view.file_name.value
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
context.toast(R.string.filename_cannot_be_empty)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (!filename.isAValidFilename()) {
|
||||
context.toast(R.string.filename_invalid_characters)
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
listener.onSaveAsSuccess(filename)
|
||||
dismiss()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
interface OnSaveAsListener {
|
||||
fun onSaveAsSuccess(filename: String)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.simplemobiletools.gallery.extensions
|
||||
|
||||
import android.app.Activity
|
||||
import android.support.v7.app.ActionBar
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
|
||||
fun Activity.showSystemUI(actionbar: ActionBar?, window: Window) {
|
||||
actionbar?.show()
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
}
|
||||
|
||||
fun Activity.hideSystemUI(actionbar: ActionBar?, window: Window) {
|
||||
actionbar?.hide()
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE or
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.simplemobiletools.gallery.extensions
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
|
||||
fun Context.toast(msg: String, duration: Int = Toast.LENGTH_SHORT) = Toast.makeText(this, msg, duration).show()
|
||||
|
||||
fun Context.toast(msgId: Int, duration: Int = Toast.LENGTH_SHORT) = Toast.makeText(this, resources.getString(msgId), duration).show()
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.simplemobiletools.gallery.extensions
|
||||
|
||||
import android.view.View
|
||||
|
||||
fun View.beVisibleIf(beVisible: Boolean) = if (beVisible) visibility = View.VISIBLE else visibility = View.GONE
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.simplemobiletools.gallery.models
|
||||
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
|
||||
class Directory(val path: String, val thumbnail: String, val name: String, var mediaCnt: Int, val timestamp: Long, var size: Long) : Comparable<Directory> {
|
||||
fun addSize(bytes: Long) {
|
||||
size += bytes
|
||||
}
|
||||
|
||||
override fun compareTo(other: Directory): Int {
|
||||
var res: Int
|
||||
if (sorting and Constants.SORT_BY_NAME != 0) {
|
||||
res = path.compareTo(other.path)
|
||||
} else if (sorting and Constants.SORT_BY_DATE != 0) {
|
||||
res = if (timestamp > other.timestamp) 1 else -1
|
||||
} else {
|
||||
res = if (size > other.size) 1 else -1
|
||||
}
|
||||
|
||||
if (sorting and Constants.SORT_DESCENDING != 0) {
|
||||
res *= -1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
override fun toString() = "Directory {path=$path, thumbnail=$thumbnail, name=$name, mediaCnt=$mediaCnt, timestamp=$timestamp, size $size}"
|
||||
|
||||
companion object {
|
||||
var sorting: Int = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.simplemobiletools.gallery.models
|
||||
|
||||
import com.simplemobiletools.gallery.Constants
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
class Medium(val name: String, var path: String, val isVideo: Boolean, val timestamp: Long, val size: Long) : Serializable, Comparable<Medium> {
|
||||
val isGif: Boolean
|
||||
get() = path.toLowerCase().endsWith(".gif")
|
||||
|
||||
val isImage: Boolean
|
||||
get() = !isGif && !isVideo
|
||||
|
||||
fun getMimeType() = if (isVideo) "video/*" else "image/*"
|
||||
|
||||
override fun compareTo(other: Medium): Int {
|
||||
var res: Int
|
||||
if (sorting and Constants.SORT_BY_NAME != 0) {
|
||||
res = path.compareTo(other.path)
|
||||
} else if (sorting and Constants.SORT_BY_DATE != 0) {
|
||||
res = if (timestamp > other.timestamp) 1 else -1
|
||||
} else {
|
||||
res = if (size > other.size) 1 else -1
|
||||
}
|
||||
|
||||
if (sorting and Constants.SORT_DESCENDING != 0) {
|
||||
res *= -1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
override fun toString() = "Medium {name=$name, path=$path, isVideo=$isVideo, timestamp=$timestamp, size=$size}"
|
||||
|
||||
companion object {
|
||||
private val serialVersionUID = -6543139465975455L
|
||||
var sorting: Int = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.simplemobiletools.gallery.views
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.ImageView
|
||||
|
||||
class MyImageView : ImageView {
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
setMeasuredDimension(measuredWidth, measuredWidth)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.simplemobiletools.gallery.views
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
|
||||
import com.booking.rtlviewpager.RtlViewPager
|
||||
|
||||
class MyViewPager : RtlViewPager {
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||
try {
|
||||
return super.onInterceptTouchEvent(ev)
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
ex.printStackTrace()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
||||
try {
|
||||
return super.onTouchEvent(ev)
|
||||
} catch (ex: IllegalArgumentException) {
|
||||
ex.printStackTrace()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
7
app/src/main/res/drawable/gradient_background.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="@android:color/transparent"
|
||||
android:startColor="#BB000000"/>
|
||||
</shape>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.gallery.MyImageView
|
||||
<com.simplemobiletools.gallery.views.MyImageView
|
||||
android:id="@+id/dir_thumbnail"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.gallery.MyImageView
|
||||
<com.simplemobiletools.gallery.views.MyImageView
|
||||
android:id="@+id/medium_thumbnail"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.theartofdev.edmodo.cropper.CropImageView
|
||||
android:id="@+id/crop_image_view"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
android:id="@+id/license_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/license_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@@ -73,5 +73,32 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cropper_text"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/license_filepicker_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/filepicker_title"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/license_filepicker_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/filepicker_text"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/license_fileproperties_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/fileproperties_title"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/license_fileproperties_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/fileproperties_text"/>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/directories_holder"
|
||||
@@ -15,7 +14,6 @@
|
||||
android:id="@+id/directories_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:choiceMode="multipleChoiceModal"
|
||||
android:columnWidth="@dimen/dir_tmb_size"
|
||||
android:horizontalSpacing="1dp"
|
||||
android:numColumns="auto_fit"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/media_holder"
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
android:id="@+id/fragment_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.simplemobiletools.gallery.MyViewPager
|
||||
<com.simplemobiletools.gallery.views.MyViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.theartofdev.edmodo.cropper.CropImageView
|
||||
android:id="@+id/crop_image_view"
|
||||
|
||||
@@ -94,5 +94,33 @@
|
||||
android:clickable="false"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_autoplay_videos_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/settings_padding"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="@dimen/activity_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_autoplay_videos_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/settings_padding"
|
||||
android:paddingStart="@dimen/settings_padding"
|
||||
android:text="@string/autoplay_videos"/>
|
||||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/settings_autoplay_videos"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="@null"
|
||||
android:clickable="false"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
12
app/src/main/res/layout/dialog_album_picker.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<GridView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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"/>
|
||||
65
app/src/main/res/layout/dialog_copy_move.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/source_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/source"
|
||||
android:textSize="@dimen/details_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/source"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:layout_marginLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/small_padding"
|
||||
android:paddingTop="@dimen/small_padding"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destination_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/destination"
|
||||
android:textSize="@dimen/details_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destination"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:layout_marginLeft="@dimen/activity_margin"
|
||||
android:paddingBottom="@dimen/small_padding"
|
||||
android:paddingRight="@dimen/small_padding"
|
||||
android:paddingTop="@dimen/small_padding"
|
||||
android:text="@string/select_destination"/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/dialog_radio_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checkedButton="@+id/dialog_radio_copy">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/dialog_radio_copy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/medium_padding"
|
||||
android:text="@string/copy"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/dialog_radio_move"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/move"/>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
16
app/src/main/res/layout/dialog_save_as.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/save_as_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/activity_margin">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/file_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:singleLine="true"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
android:id="@+id/dir_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dir_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/tmb_shadow_height"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@color/actionbar_grey"
|
||||
android:background="@drawable/gradient_background"
|
||||
android:gravity="bottom"
|
||||
android:paddingBottom="@dimen/small_padding"
|
||||
android:paddingLeft="@dimen/medium_padding"
|
||||
android:paddingRight="@dimen/medium_padding"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="@drawable/selector">
|
||||
|
||||
<com.simplemobiletools.gallery.MyImageView
|
||||
<com.simplemobiletools.gallery.views.MyImageView
|
||||
android:id="@+id/dir_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/fragment_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"/>
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
android:id="@+id/photo_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/photo_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
android:id="@+id/photo_view"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/photo_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/video_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/video_surface"
|
||||
@@ -25,7 +24,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@color/actionbar_grey"
|
||||
android:background="@drawable/gradient_background"
|
||||
android:paddingLeft="@dimen/timer_padding"
|
||||
android:paddingRight="@dimen/timer_padding">
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
android:id="@+id/media_item_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/media_item_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@@ -11,9 +11,24 @@
|
||||
android:id="@+id/play_outline"
|
||||
android:layout_width="@dimen/play_outline_size"
|
||||
android:layout_height="@dimen/play_outline_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:src="@mipmap/play_outline"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/file_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@drawable/gradient_background"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="3"
|
||||
android:minHeight="@dimen/play_outline_size"
|
||||
android:paddingBottom="@dimen/small_padding"
|
||||
android:paddingLeft="@dimen/small_padding"
|
||||
android:paddingRight="@dimen/small_padding"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/details_text_size"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<merge>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/medium_thumbnail_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/medium_thumbnail_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="@drawable/selector">
|
||||
|
||||
<com.simplemobiletools.gallery.MyImageView
|
||||
<com.simplemobiletools.gallery.views.MyImageView
|
||||
android:id="@+id/medium_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout android:id="@+id/rename_directory_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rename_directory_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout android:id="@+id/rename_file_holder"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rename_file_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
@@ -19,13 +19,13 @@
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/extension_label"
|
||||
android:id="@+id/file_extension_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/extension"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/extension"
|
||||
android:id="@+id/file_extension"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/cab_properties"
|
||||
android:icon="@mipmap/info"
|
||||
android:title="@string/properties"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_edit"
|
||||
android:icon="@mipmap/rename"
|
||||
@@ -16,6 +21,10 @@
|
||||
android:icon="@mipmap/unhide"
|
||||
android:title="@string/unhide_folder"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_copy_move"
|
||||
android:title="@string/copy_move"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/cab_delete"
|
||||
android:icon="@mipmap/delete"
|
||||
@@ -1,11 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/cab_properties"
|
||||
android:icon="@mipmap/info"
|
||||
android:title="@string/properties"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_share"
|
||||
android:icon="@mipmap/share"
|
||||
android:title="@string/share"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_copy_move"
|
||||
android:title="@string/copy_move"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/cab_delete"
|
||||
android:icon="@mipmap/delete"
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
android:title="@string/rotate"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/save"
|
||||
android:id="@+id/save_as"
|
||||
android:icon="@mipmap/check"
|
||||
android:title="@string/save"
|
||||
android:title="@string/save_as"
|
||||
app:showAsAction="ifRoom"/>
|
||||
</menu>
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
android:icon="@mipmap/sort"
|
||||
android:title="@string/sort_by"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/toggle_filename"
|
||||
android:icon="@mipmap/toggle_filename"
|
||||
android:title="@string/toggle_filename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/hide_folder"
|
||||
android:title="@string/hide_folder"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/menu_copy_move"
|
||||
android:title="@string/copy_move"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/menu_set_as_wallpaper"
|
||||
android:title="@string/set_as_wallpaper"
|
||||
@@ -24,6 +28,11 @@
|
||||
android:icon="@mipmap/rename"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_properties"
|
||||
android:icon="@mipmap/info"
|
||||
android:title="@string/properties"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/menu_delete"
|
||||
android:icon="@mipmap/delete"
|
||||
|
||||
BIN
app/src/main/res/mipmap-hdpi/info.png
Normal file
|
After Width: | Height: | Size: 755 B |
BIN
app/src/main/res/mipmap-hdpi/toggle_filename.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/mipmap-mdpi/info.png
Normal file
|
After Width: | Height: | Size: 433 B |
BIN
app/src/main/res/mipmap-mdpi/toggle_filename.png
Normal file
|
After Width: | Height: | Size: 206 B |
BIN
app/src/main/res/mipmap-xhdpi/info.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/toggle_filename.png
Normal file
|
After Width: | Height: | Size: 322 B |
BIN
app/src/main/res/mipmap-xxhdpi/info.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/toggle_filename.png
Normal file
|
After Width: | Height: | Size: 516 B |
BIN
app/src/main/res/mipmap-xxxhdpi/info.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/toggle_filename.png
Normal file
|
After Width: | Height: | Size: 293 B |
@@ -1,22 +1,26 @@
|
||||
<resources>
|
||||
<string name="app_name">Simple Gallery</string>
|
||||
<string name="app_launcher_name">Gallery</string>
|
||||
<string name="app_name">Schlichte Galerie</string>
|
||||
<string name="app_launcher_name">Galerie</string>
|
||||
<string name="share_via">Teilen via</string>
|
||||
<string name="no_permissions">Ohne Zugriff auf deinen Speicher gibt es hier nicht viel zu tun</string>
|
||||
<string name="delete">Löschen</string>
|
||||
<string name="deleting">Lösche</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="rename">Umbenennen</string>
|
||||
<string name="edit">Bearbeiten</string>
|
||||
<string name="undo">Rückgängig</string>
|
||||
<string name="share">Teilen</string>
|
||||
<string name="properties">Eigenschaften</string>
|
||||
<string name="rename_file">Datei umbenennen</string>
|
||||
<string name="rename_folder">Ordner umbenennen</string>
|
||||
<string name="rename_file_error">Konnte die Datei nicht umbenennen</string>
|
||||
<string name="rename_file_empty">Dateiname darf nicht leer sein</string>
|
||||
<string name="rename_folder_error">Konnte den Ordner nicht umbenennen</string>
|
||||
<string name="rename_folder_empty">Ordnername darf nicht leer sein</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">Ordner erfolgreich umbenannt</string>
|
||||
<string name="renaming_folder">Benenne Ordner um</string>
|
||||
<string name="filename_cannot_be_empty">Dateiname darf nicht leer sein</string>
|
||||
<string name="filename_invalid_characters">Filename contains invalid characters</string>
|
||||
<string name="extension">Dateiendung</string>
|
||||
<string name="file_deleted">Datei gelöscht</string>
|
||||
<string name="open_camera">Kamera öffnen</string>
|
||||
@@ -29,11 +33,33 @@
|
||||
<string name="descending">Absteigend</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="open_with">Open with</string>
|
||||
<string name="no_app_found">No valid app found</string>
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="open_with">Öffnen mit</string>
|
||||
<string name="no_app_found">Keine zulässige App gefunden</string>
|
||||
<string name="hide_folder">Ordner verstecken</string>
|
||||
<string name="unhide_folder">Ordner sichtbar machen</string>
|
||||
<string name="hidden">(versteckt)</string>
|
||||
<string name="save_as">Save as</string>
|
||||
<string name="file_saved">File saved successfully</string>
|
||||
<string name="copy">Kopieren</string>
|
||||
<string name="move">Verschieben</string>
|
||||
<string name="copy_move">Kopieren/Verschieben</string>
|
||||
<string name="copy_item">Datei/Ordner kopieren</string>
|
||||
<string name="copy_items">Dateien/Ordner kopieren</string>
|
||||
<string name="source">Quelle</string>
|
||||
<string name="destination">Ziel</string>
|
||||
<string name="select_destination">Ziel auswählen</string>
|
||||
<string name="invalid_destination">Konnte nicht an ausgewähltes Ziel schreiben</string>
|
||||
<string name="please_select_destination">Bitte wähle ein Ziel</string>
|
||||
<string name="source_and_destination_same">Source and destination cannot be the same</string>
|
||||
<string name="copy_failed">Konnte die Datei nicht kopieren</string>
|
||||
<string name="copying">Kopiere…</string>
|
||||
<string name="copying_success">Files copied successfully</string>
|
||||
<string name="copy_move_failed">An error occurred</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 Ordner gelöscht</item>
|
||||
@@ -47,23 +73,23 @@
|
||||
|
||||
<!-- Editor -->
|
||||
<string name="editor">Editor</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="rotate">Rotate</string>
|
||||
<string name="invalid_image_path">Invalid image path</string>
|
||||
<string name="image_editing_failed">Image editing failed</string>
|
||||
<string name="edit_image_with">Edit image with:</string>
|
||||
<string name="no_editor_found">No image editor found</string>
|
||||
<string name="unknown_file_location">Unknown file location</string>
|
||||
<string name="error_saving_file">Could not overwrite the source file</string>
|
||||
<string name="save">Speichern</string>
|
||||
<string name="rotate">Drehen</string>
|
||||
<string name="invalid_image_path">Ungültiger Dateipfad</string>
|
||||
<string name="image_editing_failed">Bildbearbeitung fehlgeschlagen</string>
|
||||
<string name="edit_image_with">Bearbeite Bild mit:</string>
|
||||
<string name="no_editor_found">Kein Bildeditor gefunden</string>
|
||||
<string name="unknown_file_location">Unbekannter Dateiort</string>
|
||||
<string name="error_saving_file">Konnte Quelldatei nicht überschreiben</string>
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
<string name="set_as_wallpaper">Als Hintergrundbild setzen</string>
|
||||
<string name="set_as_wallpaper">Als Hintergrundbild festlegen</string>
|
||||
<string name="set_as_wallpaper_failed">Setzen des Hintergrundbildes fehlgeschlagen</string>
|
||||
<string name="set_as_wallpaper_with">Set as wallpaper with:</string>
|
||||
<string name="no_wallpaper_setter_found">No app capable of it has been found</string>
|
||||
<string name="set_as_wallpaper_with">Als Hintergrundbild festlegen mit:</string>
|
||||
<string name="no_wallpaper_setter_found">Keine passende App gefunden</string>
|
||||
<string name="setting_wallpaper">Setze Hintergrundbild…</string>
|
||||
<string name="wallpaper_set_successfully">Wallpaper set successfully</string>
|
||||
<string name="wallpaper_set_successfully">Hintergrundbild erfolgreich festgelegt</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about">Über</string>
|
||||
@@ -79,15 +105,19 @@
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="dark_theme">Dunkles Thema</string>
|
||||
<string name="dark_theme">Dunkles Design</string>
|
||||
<string name="same_sorting">Selbe Sortierung für Dateien und Ordner</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="show_hidden_folders">Zeige versteckte Ordner</string>
|
||||
<string name="autoplay_videos">Play videos automatically</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">Diese App nutzt die folgenden Drittanbieterbilbiotheken, die mein Leben einfacher machen. Danke.</string>
|
||||
<string name="third_party_licences">Drittanbieterlizenzen</string>
|
||||
<string name="butterknife_title"><u>Butter Knife (view injector)</u></string>
|
||||
<string name="photoview_title"><u>PhotoView (zoomable imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (image loading and caching)</u></string>
|
||||
<string name="butterknife_title"><u>Butter Knife (View Injector)</u></string>
|
||||
<string name="photoview_title"><u>PhotoView (Zoomable Imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (Bilder laden und zwischenspeichern)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
@@ -5,18 +5,22 @@
|
||||
<string name="no_permissions">No hay mucho que hacer en una galería sin acceso al almacenamiento</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="deleting">Eliminando</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="rename">Renombrar</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="undo">Deshacer</string>
|
||||
<string name="share">Compartir</string>
|
||||
<string name="properties">Propiedades</string>
|
||||
<string name="rename_file">Renombrar archivo</string>
|
||||
<string name="rename_folder">Renombrar carpeta</string>
|
||||
<string name="rename_file_error">No se pudo renombrar el archivo</string>
|
||||
<string name="rename_file_empty">El nombre de archivo no puede estar vacío</string>
|
||||
<string name="rename_folder_error">No se pudo renombrar la carpeta</string>
|
||||
<string name="rename_folder_empty">El nombre de carpeta no puede estar vacío</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">Carpeta renombrada correctamente</string>
|
||||
<string name="renaming_folder">Renombrando carpeta</string>
|
||||
<string name="filename_cannot_be_empty">El nombre de archivo no puede estar vacío</string>
|
||||
<string name="filename_invalid_characters">Filename contains invalid characters</string>
|
||||
<string name="extension">Extensión</string>
|
||||
<string name="file_deleted">Archivo eliminado</string>
|
||||
<string name="open_camera">Abrir cámara</string>
|
||||
@@ -29,11 +33,33 @@
|
||||
<string name="descending">Descendente</string>
|
||||
<string name="ok">Aceptar</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="open_with">Open with</string>
|
||||
<string name="open_with">Abrir con…</string>
|
||||
<string name="no_app_found">No valid app found</string>
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="hide_folder">Ocultar carpeta</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="save_as">Salvar como</string>
|
||||
<string name="file_saved">Archivo guardado con éxito</string>
|
||||
<string name="copy">Copy</string>
|
||||
<string name="move">Move</string>
|
||||
<string name="copy_move">Copy/Move</string>
|
||||
<string name="copy_item">Copy item</string>
|
||||
<string name="copy_items">Copy items</string>
|
||||
<string name="source">Source</string>
|
||||
<string name="destination">Destination</string>
|
||||
<string name="select_destination">Select destination</string>
|
||||
<string name="invalid_destination">Could not write to the selected destination</string>
|
||||
<string name="please_select_destination">Please select a destination</string>
|
||||
<string name="source_and_destination_same">Source and destination cannot be the same</string>
|
||||
<string name="copy_failed">Could not copy the files</string>
|
||||
<string name="copying">Copying…</string>
|
||||
<string name="copying_success">Files copied successfully</string>
|
||||
<string name="copy_move_failed">An error occurred</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 carpeta eliminada</item>
|
||||
@@ -51,7 +77,7 @@
|
||||
<string name="rotate">Rotate</string>
|
||||
<string name="invalid_image_path">Invalid image path</string>
|
||||
<string name="image_editing_failed">Image editing failed</string>
|
||||
<string name="edit_image_with">Edit image with:</string>
|
||||
<string name="edit_image_with">Editar image usando:</string>
|
||||
<string name="no_editor_found">No image editor found</string>
|
||||
<string name="unknown_file_location">Unknown file location</string>
|
||||
<string name="error_saving_file">Could not overwrite the source file</string>
|
||||
@@ -81,7 +107,9 @@
|
||||
<string name="settings">Ajustes</string>
|
||||
<string name="dark_theme">Tema oscuro</string>
|
||||
<string name="same_sorting">Ordenar del mismo modo los archivos y las carpetas</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="show_hidden_folders">Mostrar carpetas ocultas</string>
|
||||
<string name="autoplay_videos">Reproducir vídeos automáticamente</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">Esta aplicación usa las siguientes bibliotecas de terceros que hacen mi vida más fácil. Gracias.</string>
|
||||
@@ -90,4 +118,6 @@
|
||||
<string name="photoview_title"><u>PhotoView (zoomable imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (image loading and caching)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
<string name="edit">Edit</string>
|
||||
<string name="undo">Annulla</string>
|
||||
<string name="share">Condividi</string>
|
||||
<string name="properties">Proprietà</string>
|
||||
<string name="rename_file">Rinomina file</string>
|
||||
<string name="rename_folder">Rinomina cartella</string>
|
||||
<string name="rename_file_error">Impossibile rinominare il file</string>
|
||||
<string name="rename_file_empty">Il nome del file non deve essere vuoto</string>
|
||||
<string name="rename_folder_error">Impossibile rinominare la cartella</string>
|
||||
<string name="rename_folder_empty">Il nome della cartella non deve essere vuoto</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">Cartella rinominata correttamente</string>
|
||||
<string name="renaming_folder">Rinominazione cartella</string>
|
||||
<string name="filename_cannot_be_empty">Il nome del file non deve essere vuoto</string>
|
||||
<string name="filename_invalid_characters">Filename contains invalid characters</string>
|
||||
<string name="extension">Estensione</string>
|
||||
<string name="file_deleted">File eliminato</string>
|
||||
<string name="open_camera">Apri fotocamera</string>
|
||||
@@ -34,6 +38,28 @@
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="save_as">Save as</string>
|
||||
<string name="file_saved">File saved successfully</string>
|
||||
<string name="copy">Copia</string>
|
||||
<string name="move">Sposta</string>
|
||||
<string name="copy_move">Copia/Sposta</string>
|
||||
<string name="copy_item">Copia elemento</string>
|
||||
<string name="copy_items">Copia elementi</string>
|
||||
<string name="source">Fonte</string>
|
||||
<string name="destination">Destinazione</string>
|
||||
<string name="select_destination">Seleziona destinazione</string>
|
||||
<string name="invalid_destination">Impossibile scrivere nella destinazione selezionata</string>
|
||||
<string name="please_select_destination">Seleziona una destinazione</string>
|
||||
<string name="source_and_destination_same">Source and destination cannot be the same</string>
|
||||
<string name="copy_failed">Impossibile copiare i file</string>
|
||||
<string name="copying">Copia in corso…</string>
|
||||
<string name="copying_success">Files copied successfully</string>
|
||||
<string name="copy_move_failed">An error occurred</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 cartella eliminata</item>
|
||||
@@ -82,6 +108,8 @@
|
||||
<string name="dark_theme">Tema scuro</string>
|
||||
<string name="same_sorting">Same sorting for files and folders</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="autoplay_videos">Play videos automatically</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">Questa app usa le seguenti librerie di terze parti per semplificarmi la vita. Grazie.</string>
|
||||
@@ -90,4 +118,6 @@
|
||||
<string name="photoview_title"><u>PhotoView (zoomable imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (image loading and caching)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
<string name="edit">Edit</string>
|
||||
<string name="undo">元に戻す</string>
|
||||
<string name="share">共有</string>
|
||||
<string name="properties">Properties</string>
|
||||
<string name="rename_file">ファイルの名前を変更</string>
|
||||
<string name="rename_folder">フォルダーの名前を変更</string>
|
||||
<string name="rename_file_error">ファイルの名前を変更できませんでした</string>
|
||||
<string name="rename_file_empty">ファイル名は空にできません</string>
|
||||
<string name="rename_folder_error">フォルダーの名前を変更できませんでした</string>
|
||||
<string name="rename_folder_empty">フォルダー名は空にできません</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">フォルダーの名前を正常に変更しました</string>
|
||||
<string name="renaming_folder">フォルダーの名前を変更中</string>
|
||||
<string name="filename_cannot_be_empty">ファイル名は空にできません</string>
|
||||
<string name="filename_invalid_characters">Filename contains invalid characters</string>
|
||||
<string name="extension">拡張</string>
|
||||
<string name="file_deleted">ファイルを削除しました</string>
|
||||
<string name="open_camera">カメラを開く</string>
|
||||
@@ -34,6 +38,28 @@
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="save_as">Save as</string>
|
||||
<string name="file_saved">File saved successfully</string>
|
||||
<string name="copy">コピー</string>
|
||||
<string name="move">移動</string>
|
||||
<string name="copy_move">Copy/Move</string>
|
||||
<string name="copy_item">アイテムをコピー</string>
|
||||
<string name="copy_items">アイテムをコピー</string>
|
||||
<string name="source">元</string>
|
||||
<string name="destination">先</string>
|
||||
<string name="select_destination">宛先を選択</string>
|
||||
<string name="invalid_destination">選択した宛先に書き込みできませんでした</string>
|
||||
<string name="please_select_destination">宛先を選択してください</string>
|
||||
<string name="source_and_destination_same">Source and destination cannot be the same</string>
|
||||
<string name="copy_failed">ファイルをコピーできませんでした</string>
|
||||
<string name="copying">コピー中…</string>
|
||||
<string name="copying_success">Files copied successfully</string>
|
||||
<string name="copy_move_failed">An error occurred</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 フォルダーを削除しました</item>
|
||||
@@ -82,6 +108,8 @@
|
||||
<string name="dark_theme">ダークテーマ</string>
|
||||
<string name="same_sorting">Same sorting for files and folders</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="autoplay_videos">Play videos automatically</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">このアプリは、私の人生を容易にするために、次のサードパーティのライブラリーを使用しています。 ありがとうございます。</string>
|
||||
@@ -90,4 +118,6 @@
|
||||
<string name="photoview_title"><u>PhotoView (ズーム可能イメージビュー)</u></string>
|
||||
<string name="glide_title"><u>Glide (イメージ ローディングとキャッシング)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
@@ -3,22 +3,26 @@
|
||||
<string name="app_launcher_name">Galeria</string>
|
||||
<string name="share_via">Partilhar via</string>
|
||||
<string name="no_permissions">É necessário o acesso ao armazenamento para a galeria ter utilidade</string>
|
||||
<string name="delete">Eliminar</string>
|
||||
<string name="deleting">A eliminar</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="delete">Apagar</string>
|
||||
<string name="deleting">A apagar</string>
|
||||
<string name="rename">Renomear</string>
|
||||
<string name="edit">Editar</string>
|
||||
<string name="undo">Desfazer</string>
|
||||
<string name="share">Partilhar</string>
|
||||
<string name="properties">Propriedades</string>
|
||||
<string name="rename_file">Renomear ficheiro</string>
|
||||
<string name="rename_folder">Renomear pasta</string>
|
||||
<string name="rename_file_error">Não foi possível renomear o ficheiro</string>
|
||||
<string name="rename_file_empty">O nome do ficheiro não pode ficar em branco</string>
|
||||
<string name="rename_folder_error">Não foi possível renomear a pasta</string>
|
||||
<string name="rename_folder_empty">O nome da pasta não pode ficar em branco</string>
|
||||
<string name="rename_folder_empty">O nome da pasta não pode estar vazio</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">A pasta foi renomeada com sucesso</string>
|
||||
<string name="renaming_folder">A renomear pasta</string>
|
||||
<string name="filename_cannot_be_empty">O nome do ficheiro não pode estar vazio</string>
|
||||
<string name="filename_invalid_characters">O nome do ficheiro contém caracteres inválidos</string>
|
||||
<string name="extension">Extensão</string>
|
||||
<string name="file_deleted">Ficheiro eliminado</string>
|
||||
<string name="file_deleted">Ficheiro apagado</string>
|
||||
<string name="open_camera">Abrir câmara</string>
|
||||
<string name="unknown_error">Ocorreu um erro desconhecido</string>
|
||||
<string name="sort_by">Ordenar por</string>
|
||||
@@ -29,65 +33,91 @@
|
||||
<string name="descending">Descendente</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Cancelar</string>
|
||||
<string name="open_with">Open with</string>
|
||||
<string name="no_app_found">No valid app found</string>
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="open_with">Abrir com</string>
|
||||
<string name="no_app_found">Nenhuma aplicação encontrada</string>
|
||||
<string name="hide_folder">Ocultar pasta</string>
|
||||
<string name="unhide_folder">Mostrar pasta</string>
|
||||
<string name="hidden">(oculta)</string>
|
||||
<string name="save_as">Guardar como</string>
|
||||
<string name="file_saved">Ficheiro guardado com sucesso</string>
|
||||
<string name="copy">Copiar</string>
|
||||
<string name="move">Mover</string>
|
||||
<string name="copy_move">Copiar/mover para</string>
|
||||
<string name="copy_item">Copiar item</string>
|
||||
<string name="copy_items">Copiar itens</string>
|
||||
<string name="source">Origem</string>
|
||||
<string name="destination">Destino</string>
|
||||
<string name="select_destination">Selecione o destino</string>
|
||||
<string name="invalid_destination">Não foi possível escrever no destino selecionado</string>
|
||||
<string name="please_select_destination">Por favor selecione um destino</string>
|
||||
<string name="source_and_destination_same">A origem e o destino não podem ser iguais</string>
|
||||
<string name="copy_failed">Não foi possível copiar os ficheiros</string>
|
||||
<string name="copying">A copiar…</string>
|
||||
<string name="copying_success">Ficheiros copiados com sucesso</string>
|
||||
<string name="copy_move_failed">Ocorreu um erro ao copiar</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<string name="already_exists">Já existe um ficheiro com este nome</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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 pasta eliminada</item>
|
||||
<item quantity="other">%1$d pastas eliminadas</item>
|
||||
<item quantity="one">1 pasta apagada</item>
|
||||
<item quantity="other">%1$d pastas apagadas</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="files_deleted">
|
||||
<item quantity="one">1 ficheiro eliminado</item>
|
||||
<item quantity="other">%1$d ficheiros eliminados</item>
|
||||
<item quantity="one">1 ficheiro apagado</item>
|
||||
<item quantity="other">%1$d ficheiros apagadas</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Editor -->
|
||||
<string name="editor">Editor</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="rotate">Rotate</string>
|
||||
<string name="invalid_image_path">Invalid image path</string>
|
||||
<string name="image_editing_failed">Image editing failed</string>
|
||||
<string name="edit_image_with">Edit image with:</string>
|
||||
<string name="no_editor_found">No image editor found</string>
|
||||
<string name="unknown_file_location">Unknown file location</string>
|
||||
<string name="error_saving_file">Could not overwrite the source file</string>
|
||||
<string name="save">Guardar</string>
|
||||
<string name="rotate">Rodar</string>
|
||||
<string name="invalid_image_path">Caminho inválido</string>
|
||||
<string name="image_editing_failed">Falha de edição de imagem</string>
|
||||
<string name="edit_image_with">Editar imagem com:</string>
|
||||
<string name="no_editor_found">Editor não encontrado</string>
|
||||
<string name="unknown_file_location">Localização desconhecida</string>
|
||||
<string name="error_saving_file">Não foi possível substituir o ficheiro original</string>
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
<string name="set_as_wallpaper">Definir como fundo de ecrã</string>
|
||||
<string name="set_as_wallpaper">Definir como fundo do ecrã</string>
|
||||
<string name="set_as_wallpaper_failed">Falha ao definir como fundo de ecrã</string>
|
||||
<string name="set_as_wallpaper_with">Set as wallpaper with:</string>
|
||||
<string name="no_wallpaper_setter_found">No app capable of it has been found</string>
|
||||
<string name="set_as_wallpaper_with">Definir como fundo com:</string>
|
||||
<string name="no_wallpaper_setter_found">Aplicação não encontrada</string>
|
||||
<string name="setting_wallpaper">A definir como fundo de ecrã…</string>
|
||||
<string name="wallpaper_set_successfully">Wallpaper set successfully</string>
|
||||
<string name="wallpaper_set_successfully">Fundo definido com sucesso</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about">Sobre</string>
|
||||
<string name="website">Mais aplicações simples e código de fonte em:\nhttp://simplemobiletools.com</string>
|
||||
<string name="about">Acerca</string>
|
||||
<string name="website">Mais aplicações Simple e código fonte em:\nhttp://simplemobiletools.com</string>
|
||||
<string name="email_label">Envie os seus comentários ou sugestões para:</string>
|
||||
<string name="third_party_licences_underlined"><u>Licenças de terceiros</u></string>
|
||||
<string name="invite_friends_underlined"><u>Convidar amigos</u></string>
|
||||
<string name="share_text">Olá, experimente %1$s em %2$s</string>
|
||||
<string name="share_text">Olá, experimenta %1$s em %2$s</string>
|
||||
<string name="invite_via">Convidar via</string>
|
||||
<string name="rate_us_underlined"><u>Classifique-nos na Play Store</u></string>
|
||||
<string name="rate_us_underlined"><u>Avalie-nos na Play Store</u></string>
|
||||
<string name="follow_us">Siga-nos:</string>
|
||||
<string name="copyright">v %1$s\nCopyright © Simple Mobile Tools %2$d</string>
|
||||
<string name="copyright">V %1$s\nCopyright © Simple Mobile Tools %2$d</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="settings">Definições</string>
|
||||
<string name="dark_theme">Tema escuro</string>
|
||||
<string name="same_sorting">A mesma ordenação para ficheiros e pastas</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="same_sorting">Mesma ordenação para ficheiros e pastas</string>
|
||||
<string name="show_hidden_folders">Mostrar pastas ocultas</string>
|
||||
<string name="autoplay_videos">Reproduzir vídeos automaticamente</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">Esta aplicação usa as seguintes bibliotecas de terceiros para facilitar a minha vida. Obrigado.</string>
|
||||
<string name="third_party_licences">Licenças de terceiros</string>
|
||||
<string name="butterknife_title"><u>Butter Knife (injetor de \"views\")</u></string>
|
||||
<string name="photoview_title"><u>PhotoView (\"imageviews\" ampliáveis)</u></string>
|
||||
<string name="butterknife_title"><u>Butter Knife (injetor de vistas)</u></string>
|
||||
<string name="photoview_title"><u>PhotoView (ampliação de imagens)</u></string>
|
||||
<string name="glide_title"><u>Glide (carregamento e cache de imagens)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
@@ -9,14 +9,18 @@
|
||||
<string name="edit">Edit</string>
|
||||
<string name="undo">Ångra</string>
|
||||
<string name="share">Dela</string>
|
||||
<string name="properties">Properties</string>
|
||||
<string name="rename_file">Döp om fil</string>
|
||||
<string name="rename_folder">Döp om mapp</string>
|
||||
<string name="rename_file_error">Det gick inte att döpa om filen</string>
|
||||
<string name="rename_file_empty">Du måste ange ett filnamn</string>
|
||||
<string name="rename_folder_error">Det gick inte att döpa om mappen</string>
|
||||
<string name="rename_folder_empty">Du måste ange ett mappnamn</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_ok">Mappen döptes om</string>
|
||||
<string name="renaming_folder">Döper om mappen</string>
|
||||
<string name="filename_cannot_be_empty">Du måste ange ett filnamn</string>
|
||||
<string name="filename_invalid_characters">Filename contains invalid characters</string>
|
||||
<string name="extension">Filändelse</string>
|
||||
<string name="file_deleted">Fil borttagen</string>
|
||||
<string name="open_camera">Starta kameran</string>
|
||||
@@ -34,6 +38,28 @@
|
||||
<string name="hide_folder">Hide folder</string>
|
||||
<string name="unhide_folder">Unhide folder</string>
|
||||
<string name="hidden">(hidden)</string>
|
||||
<string name="save_as">Save as</string>
|
||||
<string name="file_saved">File saved successfully</string>
|
||||
<string name="copy">Kopiera</string>
|
||||
<string name="move">Flytta</string>
|
||||
<string name="copy_move">Copy/Move</string>
|
||||
<string name="copy_item">Kopiera objekt</string>
|
||||
<string name="copy_items">Kopiera objekt</string>
|
||||
<string name="source">Källa</string>
|
||||
<string name="destination">Mål</string>
|
||||
<string name="select_destination">Välj mål</string>
|
||||
<string name="invalid_destination">Det gick inte att skriva till målet</string>
|
||||
<string name="please_select_destination">Please select a destination</string>
|
||||
<string name="source_and_destination_same">Source and destination cannot be the same</string>
|
||||
<string name="copy_failed">Kunde inte kopiera filen</string>
|
||||
<string name="copying">Kopierar…</string>
|
||||
<string name="copying_success">Files copied successfully</string>
|
||||
<string name="copy_move_failed">An error occurred</string>
|
||||
<string name="moving">Moving…</string>
|
||||
<string name="moving_success">Files moved successfully</string>
|
||||
<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>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 mapp borttagen</item>
|
||||
@@ -82,6 +108,8 @@
|
||||
<string name="dark_theme">Mörkt tema</string>
|
||||
<string name="same_sorting">Same sorting for files and folders</string>
|
||||
<string name="show_hidden_folders">Show hidden folders</string>
|
||||
<string name="autoplay_videos">Play videos automatically</string>
|
||||
<string name="toggle_filename">Toggle filename visibility</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">Denna app använder följande tredjepartsbibliotek för att göra mitt liv enklare. Tack.</string>
|
||||
@@ -90,4 +118,6 @@
|
||||
<string name="photoview_title"><u>PhotoView (zoomable imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (image loading and caching)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||
|
||||
124
app/src/main/res/values-zh/strings.xml
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">相册</string>
|
||||
<string name="app_launcher_name">相册</string>
|
||||
<string name="share_via">分享到</string>
|
||||
<string name="no_permissions">需要访问储存权限</string>
|
||||
<string name="delete">删除</string>
|
||||
<string name="deleting">删除中</string>
|
||||
<string name="rename">重命名</string>
|
||||
<string name="edit">编辑</string>
|
||||
<string name="undo">撤销</string>
|
||||
<string name="share">分享</string>
|
||||
<string name="properties">信息</string>
|
||||
<string name="rename_file">重命名文件</string>
|
||||
<string name="rename_file_error">文件不能重命名</string>
|
||||
<string name="rename_folder">重命名文件夹</string>
|
||||
<string name="rename_folder_empty">文件夹名不能为空</string>
|
||||
<string name="rename_folder_exists">A folder with that name already exists</string>
|
||||
<string name="rename_folder_root">Cannot rename the root folder of a storage</string>
|
||||
<string name="rename_folder_error">文件夹不能重命名</string>
|
||||
<string name="rename_folder_ok">文件夹重命名成功</string>
|
||||
<string name="renaming_folder">重命名中..</string>
|
||||
<string name="filename_cannot_be_empty">文件名不能为空</string>
|
||||
<string name="filename_invalid_characters">文件名包含非法字符</string>
|
||||
<string name="extension">扩展名</string>
|
||||
<string name="file_deleted">文件删除成功</string>
|
||||
<string name="open_camera">打开相机</string>
|
||||
<string name="unknown_error">未知错误</string>
|
||||
<string name="sort_by">排序方式</string>
|
||||
<string name="name">名称</string>
|
||||
<string name="size">大小</string>
|
||||
<string name="date">日期</string>
|
||||
<string name="ascending">递增</string>
|
||||
<string name="descending">递减</string>
|
||||
<string name="ok">确认</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="open_with">打开方式</string>
|
||||
<string name="no_app_found">没有可用的软件</string>
|
||||
<string name="hide_folder">隐藏文件夹</string>
|
||||
<string name="unhide_folder">显示文件夹</string>
|
||||
<string name="hidden">(隐藏)</string>
|
||||
<string name="save_as">保存</string>
|
||||
<string name="file_saved">文件保存成功</string>
|
||||
<string name="copy">复制</string>
|
||||
<string name="move">移动</string>
|
||||
<string name="copy_move">复制/移动</string>
|
||||
<string name="copy_item">复制</string>
|
||||
<string name="copy_items">复制多个</string>
|
||||
<string name="source">原路径</string>
|
||||
<string name="destination">目标</string>
|
||||
<string name="select_destination">选择目标</string>
|
||||
<string name="invalid_destination">不能写入选中目标</string>
|
||||
<string name="please_select_destination">请选择先目标</string>
|
||||
<string name="source_and_destination_same">原路径和目标不能相同</string>
|
||||
<string name="copy_failed">不能复制文件</string>
|
||||
<string name="copying">正在复制…</string>
|
||||
<string name="copying_success">复制成功</string>
|
||||
<string name="copy_move_failed">操作失败</string>
|
||||
<string name="moving">移动中…</string>
|
||||
<string name="moving_success">文件移动成功</string>
|
||||
<string name="already_exists">相同的文件名已经存在</string>
|
||||
<string name="moving_success_partial">相同文件不能移动</string>
|
||||
<string name="copying_success_partial">相同文件不能复制</string>
|
||||
|
||||
<plurals name="folders_deleted">
|
||||
<item quantity="one">1 folder deleted</item>
|
||||
<item quantity="other">%1$d folders deleted</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="files_deleted">
|
||||
<item quantity="one">1 file deleted</item>
|
||||
<item quantity="other">%1$d files deleted</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Editor -->
|
||||
<string name="editor">编辑器</string>
|
||||
<string name="save">保存</string>
|
||||
<string name="rotate">旋转</string>
|
||||
<string name="invalid_image_path">错误图片路径</string>
|
||||
<string name="image_editing_failed">图像编辑失败</string>
|
||||
<string name="edit_image_with">编辑方式:</string>
|
||||
<string name="no_editor_found">没有可用的图片编辑器</string>
|
||||
<string name="unknown_file_location">未知文件路径</string>
|
||||
<string name="error_saving_file">不能覆盖源文件</string>
|
||||
|
||||
<!-- Set wallpaper -->
|
||||
<string name="simple_wallpaper">Simple Wallpaper</string>
|
||||
<string name="set_as_wallpaper">设为壁纸</string>
|
||||
<string name="set_as_wallpaper_failed">壁纸设置失败</string>
|
||||
<string name="set_as_wallpaper_with">设为壁纸..</string>
|
||||
<string name="no_wallpaper_setter_found">没有可用的软件</string>
|
||||
<string name="setting_wallpaper">壁纸应用中…</string>
|
||||
<string name="wallpaper_set_successfully">壁纸应用成功</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about">关于</string>
|
||||
<string name="website">更多软件请访问: http://simplemobiletools.com</string>
|
||||
<string name="email_label">反馈您的意见到:</string>
|
||||
<string name="third_party_licences_underlined"><u>开放源代码</u></string>
|
||||
<string name="invite_friends_underlined"><u>分享给好友</u></string>
|
||||
<string name="share_text">Hey, come check out %1$s at %2$s</string>
|
||||
<string name="invite_via">分享到</string>
|
||||
<string name="rate_us_underlined"><u>为我们打分</u></string>
|
||||
<string name="follow_us">关注我们:</string>
|
||||
<string name="copyright">v %1$s Copyright © Simple Mobile Tools %2$d</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="settings">设置</string>
|
||||
<string name="dark_theme">暗主题</string>
|
||||
<string name="same_sorting">全局排序</string>
|
||||
<string name="show_hidden_folders">显示所有</string>
|
||||
<string name="autoplay_videos">自动播放</string>
|
||||
<string name="toggle_filename">显示文件名</string>
|
||||
|
||||
<!-- License -->
|
||||
<string name="notice">This app uses the following third party libraries to make my life easier. Thank you.</string>
|
||||
<string name="third_party_licences">开放源代码</string>
|
||||
<string name="butterknife_title"><u>Butter Knife (view injector)</u></string>
|
||||
<string name="photoview_title"><u>PhotoView (zoomable imageviews)</u></string>
|
||||
<string name="glide_title"><u>Glide (image loading and caching)</u></string>
|
||||
<string name="cropper_title"><u>Android Image Cropper</u></string>
|
||||
<string name="filepicker_title"><u>Simple File Picker (filepicker dialog)</u></string>
|
||||
<string name="fileproperties_title"><u>Simple File Properties (properties dialog)</u></string>
|
||||
</resources>
|
||||