-## 1.7.2 (July 2015)
-- New navigation drawer
-- Improved Passcode
-- Automatic grid view just for folders full of images
-- More characters allowed in file names
-- Support for servers in same domain, different path
-- Bugs fixed:
- + Frequent crashes in folder with several images
- + Sync error in servers with huge quota and external storage enable
- + Share by link error
- + Some other crashes and minor bugs
++# 2015-11-01
++- PR [#1236](https://github.com/owncloud/android/pull/1236) "Streaming video/audio" merged
++- PR [#1035](https://github.com/owncloud/android/pull/1035) "Enable video thumbnail" merged
+
-## 1.7.1 (April 2015)
+# 2015-10-31
+- updated all PR
+- bugfix: #1234, #1230
+- implement Crash Handler
+- implement direct download of latest apk in settings -> last item on bottom
-- Share link even with password enforced by server
-- Get the app ready for oc 8.1 servers
-- Added option to create new folder in uploads from external apps
-- Improved management of deleted users
-- Bugs fixed
- + Fixed crash on Android 2.x devices
- + Improvements on uploads
-
-## 1.7.0 (February 2015)
-
-- Download full folders
-- Grid view for images
-- Remote thumbnails (OC Server 8.0+)
-- Added number of files and folders at the end of the list
-- "Open with" in contextual menu
-- Downloads added to Media Provider
-- Uploads:
- + Local thumbnails in section "Files"
- + Multiple selection in "Content from other apps" (Android 4.3+)
-- Gallery:
- + proper handling of EXIF
- + obey sorting in the list of files
-- Settings view updated
-- Improved subjects in e-mails
-- Bugs fixed
+# 2015-10-30
+- fixed problem with Authority
+# 2015-10-29
+- PR [#1099](https://github.com/owncloud/android/pull/1099) "Switch list vs grid" merged
+- PR [#1100](https://github.com/owncloud/android/pull/1100) "Material FAB with speed dial implementation" merged
+- PR [#1209](https://github.com/owncloud/android/pull/1209) "Material buttons - before in #1090" merged
+- PR [#1205](https://github.com/owncloud/android/pull/1205) "Switch between online and offline files" merged
+- PR [#1195](https://github.com/owncloud/android/pull/1195) "Resize Cache" merged
+- PR [#1187](https://github.com/owncloud/android/pull/1187) "Video: Big thumbnails" merged
+- PR [#1058](https://github.com/owncloud/android/pull/1058) "add sort to UploadFileActiviy" merged
+- PR [#1168](https://github.com/owncloud/android/pull/1168) "Avoid duplicate files" merged
+- PR [#1176](https://github.com/owncloud/android/pull/1176) "Multi select" merged
+# 2015-10-26
+- start of branch
+- PR [#745](https://github.com/owncloud/android/pull/745) merged
+- PR [#1044](https://github.com/owncloud/android/pull/1044) merged: < 8.1: GalleryPlus app needed, >= 8.2 Gallery app needed
+- PR [#1111](https://github.com/owncloud/android/pull/1111) merged
import java.io.File;
import java.io.InputStream;
import java.lang.ref.WeakReference;
+ import java.net.FileNameMap;
+ import java.net.URLConnection;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Point;
++import android.graphics.Canvas;
+ import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManager;
import android.widget.ImageView;
+import android.widget.ProgressBar;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.ui.adapter.DiskLruImageCache;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
+ import com.owncloud.android.utils.FileStorageUtils;
/**
* Manager for concurrent access to thumbnails cache.
public static Bitmap mDefaultImg =
BitmapFactory.decodeResource(
- MainApp.getAppContext().getResources(),
- DisplayUtils.getFileTypeIconId("image/png", "default.png")
+ MainApp.getAppContext().getResources(),
+ R.drawable.file_image
);
return null;
}
+ /**
+ * Sets max size of cache
+ * @param maxSize in MB
+ * @return
+ */
+ public static boolean setMaxSize(long maxSize){
+ if (mThumbnailCache != null){
+ mThumbnailCache.setMaxSize(maxSize * 1024 * 1024);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static long getMaxSize(){
+ if (mThumbnailCache != null) {
+ return mThumbnailCache.getMaxSize();
+ } else {
+ return -1l;
+ }
+ }
+
public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
+ private WeakReference<ProgressBar> mProgressWheelRef;
private static Account mAccount;
private Object mFile;
+ private Boolean mIsThumbnail;
private FileDataStorageManager mStorageManager;
-
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
Account account) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mAccount = account;
}
+ public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
+ Account account, ProgressBar progressWheel) {
+ this(imageView, storageManager, account);
+ mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
+ }
+
public ThumbnailGenerationTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
}
mFile = params[0];
+ mIsThumbnail = (Boolean) params[1];
+
if (mFile instanceof OCFile) {
- thumbnail = doOCFileInBackground();
+ thumbnail = doOCFileInBackground(mIsThumbnail);
+
+ if (((OCFile) mFile).isVideo()){
+ thumbnail = addVideoOverlay(thumbnail);
+ }
} else if (mFile instanceof File) {
- thumbnail = doFileInBackground();
+ thumbnail = doFileInBackground(mIsThumbnail);
- } else {
- // do nothing
+
+ String url = ((File) mFile).getAbsolutePath();
+ String mMimeType = FileStorageUtils.getMimeTypeFromName(url);
+
+ if (mMimeType != null && mMimeType.startsWith("video/")){
+ thumbnail = addVideoOverlay(thumbnail);
+ }
+ //} else { do nothing
}
}catch(Throwable t){
}
protected void onPostExecute(Bitmap bitmap){
- if (isCancelled()) {
- bitmap = null;
- }
-
if (bitmap != null) {
final ImageView imageView = mImageViewReference.get();
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
tagId = String.valueOf(mFile.hashCode());
}
if (String.valueOf(imageView.getTag()).equals(tagId)) {
+ if (mProgressWheelRef != null) {
+ final ProgressBar progressWheel = mProgressWheelRef.get();
+ if (progressWheel != null) {
+ progressWheel.setVisibility(View.GONE);
+ }
+ }
imageView.setImageBitmap(bitmap);
+ imageView.setVisibility(View.VISIBLE);
}
}
}
* @param imageKey: thumb key
* @param bitmap: image for extracting thumbnail
* @param path: image path
- * @param px: thumbnail dp
+ * @param pxW: thumbnail width
+ * @param pxH: thumbnail height
* @return Bitmap
*/
- private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
+ private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int pxW, int pxH){
- Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+ Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
// Rotate image, obeying exif tag
thumbnail = BitmapUtils.rotateImage(thumbnail,path);
return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
}
- private Bitmap doOCFileInBackground() {
+ private Point getScreenDimension(){
+ WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Point test = new Point();
+ display.getSize(test);
+ return test;
+ }
+
+ private Bitmap doOCFileInBackground(Boolean isThumbnail) {
+ Bitmap thumbnail = null;
OCFile file = (OCFile)mFile;
- final String imageKey = String.valueOf(file.getRemoteId());
+ // distinguish between thumbnail and resized image
+ String temp = String.valueOf(file.getRemoteId());
+ if (isThumbnail){
+ temp = "t" + temp;
+ } else {
+ temp = "r" + temp;
+ }
+
+ final String imageKey = temp;
// Check disk cache in background thread
- Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
+ thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null || file.needsUpdateThumbnail()) {
-
- int px = getThumbnailDimension();
+ int pxW = 0;
+ int pxH = 0;
+ if (mIsThumbnail) {
+ pxW = pxH = getThumbnailDimension();
+ } else {
+ Point p = getScreenDimension();
+ pxW = p.x;
+ pxH = p.y;
+ }
if (file.isDown()) {
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
- file.getStoragePath(), px, px);
+ Bitmap tempBitmap = BitmapUtils.decodeSampledBitmapFromFile(
+ file.getStoragePath(), pxW, pxH);
+ Bitmap bitmap = ThumbnailUtils.extractThumbnail(tempBitmap, pxW, pxH);
if (bitmap != null) {
- thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
+ // Handle PNG
+ if (file.getMimetype().equalsIgnoreCase("image/png")) {
+ bitmap = handlePNG(bitmap, pxW);
+ }
+
+ thumbnail = addThumbnailToCache(imageKey, bitmap,
+ file.getStoragePath(), pxW, pxH);
file.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(file);
if (mClient != null && serverOCVersion != null) {
if (serverOCVersion.supportsRemoteThumbnails()) {
try {
- String uri = mClient.getBaseUri() + "" +
- "/index.php/apps/files/api/v1/thumbnail/" +
- px + "/" + px + Uri.encode(file.getRemotePath(), "/");
- Log_OC.d("Thumbnail", "URI: " + uri);
- GetMethod get = new GetMethod(uri);
- int status = mClient.executeMethod(get);
- if (status == HttpStatus.SC_OK) {
-// byte[] bytes = get.getResponseBody();
-// Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
-// bytes.length);
- InputStream inputStream = get.getResponseBodyAsStream();
- Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
- thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-
- // Add thumbnail to cache
- if (thumbnail != null) {
- addBitmapToCache(imageKey, thumbnail);
+ if (mIsThumbnail) {
+ String uri = mClient.getBaseUri() + "" +
+ "/index.php/apps/files/api/v1/thumbnail/" +
+ pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/");
+ Log_OC.d("Thumbnail", "Download URI: " + uri);
+ GetMethod get = new GetMethod(uri);
+ int status = mClient.executeMethod(get);
+ if (status == HttpStatus.SC_OK) {
+ InputStream inputStream = get.getResponseBodyAsStream();
+ Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
+ } else {
+ Log_OC.d(TAG, "Status: " + status);
+ }
+ } else {
+ String gallery = "";
+ if (serverOCVersion.supportsNativeGallery()){
+ gallery = "gallery";
+ } else {
+ gallery = "galleryplus";
}
+
+ String uri = mClient.getBaseUri() +
+ "/index.php/apps/" + gallery + "/api/preview/" + Integer.parseInt(file.getRemoteId().substring(0,8)) +
+ "/" + pxW + "/" + pxH;
+ Log_OC.d("Thumbnail", "FileName: " + file.getFileName() + " Download URI: " + uri);
+ GetMethod get = new GetMethod(uri);
+ int status = mClient.executeMethod(get);
+ if (status == HttpStatus.SC_OK) {
+ InputStream inputStream = get.getResponseBodyAsStream();
+ Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
+ // Download via gallery app
+ thumbnail = bitmap;
+ }
+ }
+
+ // Handle PNG
+ if (thumbnail != null && file.getMimetype().equalsIgnoreCase("image/png")) {
+ thumbnail = handlePNG(thumbnail, pxW);
+ }
+
+ // Add thumbnail to cache
+ if (thumbnail != null) {
+ addBitmapToCache(imageKey, thumbnail);
}
} catch (Exception e) {
e.printStackTrace();
}
- private Bitmap doFileInBackground() {
+ private Bitmap handlePNG(Bitmap bitmap, int px){
+ Bitmap resultBitmap = Bitmap.createBitmap(px,
+ px,
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(resultBitmap);
+
+ c.drawColor(MainApp.getAppContext().getResources().
+ getColor(R.color.background_color));
+ c.drawBitmap(bitmap, 0, 0, null);
+
+ return resultBitmap;
+ }
+
+ private Bitmap doFileInBackground(Boolean mIsThumbnail) {
File file = (File)mFile;
- final String imageKey = String.valueOf(file.hashCode());
+ // distinguish between thumbnail and resized image
+ String temp = String.valueOf(file.hashCode());
+ if (mIsThumbnail){
+ temp = "t" + temp;
+ } else {
+ temp = "r" + temp;
+ }
+
+ final String imageKey = temp;
// Check disk cache in background thread
Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null) {
-
- int px = getThumbnailDimension();
+ int pxW = 0;
+ int pxH = 0;
+ if (mIsThumbnail) {
+ pxW = pxH = getThumbnailDimension();
+ } else {
+ Point p = getScreenDimension();
+ pxW = p.x;
+ pxH = p.y;
+ }
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
- file.getAbsolutePath(), px, px);
+ file.getAbsolutePath(), pxW, pxH);
if (bitmap != null) {
- thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
+ thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH);
}
}
return thumbnail;
if (bitmapData == null || bitmapData != file) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
+ Log_OC.v(TAG, "Cancelled generation of thumbnail for a reused imageView");
} else {
// The same work is already in progress
return false;
return null;
}
+ public static Bitmap addVideoOverlay(Bitmap thumbnail){
+ Bitmap playButton = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
+ R.drawable.view_play);
+
+ Bitmap resizedPlayButton = Bitmap.createScaledBitmap(playButton,
+ (int) (thumbnail.getWidth() * 0.3),
+ (int) (thumbnail.getHeight() * 0.3), true);
+
+ Bitmap resultBitmap = Bitmap.createBitmap(thumbnail.getWidth(),
+ thumbnail.getHeight(),
+ Bitmap.Config.ARGB_8888);
+
+ Canvas c = new Canvas(resultBitmap);
+
+ // compute visual center of play button, according to resized image
+ int x1 = resizedPlayButton.getWidth();
+ int y1 = resizedPlayButton.getHeight() / 2;
+ int x2 = 0;
+ int y2 = resizedPlayButton.getWidth();
+ int x3 = 0;
+ int y3 = 0;
+
+ double ym = ( ((Math.pow(x3,2) - Math.pow(x1,2) + Math.pow(y3,2) - Math.pow(y1,2)) *
+ (x2 - x1)) - (Math.pow(x2,2) - Math.pow(x1,2) + Math.pow(y2,2) -
+ Math.pow(y1,2)) * (x3 - x1) ) / (2 * ( ((y3 - y1) * (x2 - x1)) -
+ ((y2 - y1) * (x3 - x1)) ));
+ double xm = ( (Math.pow(x2,2) - Math.pow(x1,2)) + (Math.pow(y2,2) - Math.pow(y1,2)) -
+ (2*ym*(y2 - y1)) ) / (2*(x2 - x1));
+
+ // offset to top left
+ double ox = - xm;
+ double oy = thumbnail.getHeight() - ym;
+
+
+ c.drawBitmap(thumbnail, 0, 0, null);
+
+ Paint p = new Paint();
+ p.setAlpha(230);
+
+ c.drawBitmap(resizedPlayButton, (float) ((thumbnail.getWidth() / 2) + ox),
+ (float) ((thumbnail.getHeight() / 2) - ym), p);
+
+ return resultBitmap;
+ }
+
public static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
* @author Bartek Przybylski\r
* @author Tobias Kaminsky\r
* @author David A. Velasco\r
+ * @author masensio\r
* Copyright (C) 2011 Bartek Przybylski\r
* Copyright (C) 2015 ownCloud Inc.\r
*\r
\r
\r
import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
import java.util.Vector;\r
\r
import android.accounts.Account;\r
import android.content.Context;\r
import android.content.SharedPreferences;\r
import android.graphics.Bitmap;\r
+import android.graphics.Color;\r
+ import android.graphics.BitmapFactory;\r
+ import android.graphics.Canvas;\r
+ import android.graphics.Paint;\r
import android.os.Build;\r
import android.preference.PreferenceManager;\r
import android.text.format.DateUtils;\r
import com.owncloud.android.ui.activity.ComponentsGetter;\r
import com.owncloud.android.utils.DisplayUtils;\r
import com.owncloud.android.utils.FileStorageUtils;\r
+import com.owncloud.android.utils.MimetypeIconUtil;\r
\r
\r
/**\r
private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };\r
\r
private SharedPreferences mAppPreferences;\r
+\r
+ private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();\r
\r
public FileListListAdapter(\r
boolean justFolders, \r
ViewType viewType;\r
if (!mGridMode){\r
viewType = ViewType.LIST_ITEM;\r
- } else if (file.isImage()){\r
+ } else if (file.isImage() || file.isVideo()){\r
viewType = ViewType.GRID_IMAGE;\r
} else {\r
viewType = ViewType.GRID_ITEM;\r
switch (viewType){\r
case LIST_ITEM:\r
TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
+ TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator);\r
TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
- ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+\r
\r
lastModV.setVisibility(View.VISIBLE);\r
lastModV.setText(showRelativeTimestamp(file));\r
\r
- checkBoxV.setVisibility(View.GONE);\r
\r
+ fileSizeSeparatorV.setVisibility(View.VISIBLE);\r
fileSizeV.setVisibility(View.VISIBLE);\r
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
\r
- if (!file.isFolder()) {\r
- AbsListView parentList = (AbsListView)parent;\r
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
- if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
- checkBoxV.setVisibility(View.GONE);\r
- } else {\r
- if (parentList.isItemChecked(position)) {\r
- checkBoxV.setImageResource(\r
- android.R.drawable.checkbox_on_background);\r
- } else {\r
- checkBoxV.setImageResource(\r
- android.R.drawable.checkbox_off_background);\r
- }\r
- checkBoxV.setVisibility(View.VISIBLE);\r
- }\r
- }\r
-\r
- } else { //Folder\r
+// if (!file.isFolder()) {\r
+// AbsListView parentList = (AbsListView)parent;\r
+// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+// if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+// checkBoxV.setVisibility(View.GONE);\r
+// } else {\r
+// if (parentList.isItemChecked(position)) {\r
+// checkBoxV.setImageResource(\r
+// R.drawable.ic_checkbox_marked);\r
+// } else {\r
+// checkBoxV.setImageResource(\r
+// R.drawable.ic_checkbox_blank_outline);\r
+// }\r
+// checkBoxV.setVisibility(View.VISIBLE);\r
+// }\r
+// }\r
+\r
+ if (file.isFolder()) {\r
+ fileSizeSeparatorV.setVisibility(View.INVISIBLE);\r
fileSizeV.setVisibility(View.INVISIBLE);\r
}\r
\r
mTransferServiceGetter.getFileDownloaderBinder();\r
FileUploaderBinder uploaderBinder =\r
mTransferServiceGetter.getFileUploaderBinder();\r
- boolean downloading = (downloaderBinder != null &&\r
- downloaderBinder.isDownloading(mAccount, file));\r
OperationsServiceBinder opsBinder =\r
mTransferServiceGetter.getOperationsServiceBinder();\r
- downloading |= (opsBinder != null &&\r
- opsBinder.isSynchronizing(mAccount, file.getRemotePath()));\r
- if (downloading) {\r
- localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+\r
+ localStateView.setVisibility(View.INVISIBLE); // default first\r
+\r
+ if ( //synchronizing\r
+ opsBinder != null &&\r
+ opsBinder.isSynchronizing(mAccount, file.getRemotePath())\r
+ ) {\r
+ localStateView.setImageResource(R.drawable.synchronizing_file_indicator);\r
localStateView.setVisibility(View.VISIBLE);\r
- } else if (uploaderBinder != null &&\r
- uploaderBinder.isUploading(mAccount, file)) {\r
- localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+\r
+ } else if ( // downloading\r
+ downloaderBinder != null &&\r
+ downloaderBinder.isDownloading(mAccount, file)\r
+ ) {\r
+ localStateView.setImageResource(\r
+ file.isFolder() ?\r
+ R.drawable.synchronizing_file_indicator :\r
+ R.drawable.downloading_file_indicator\r
+ );\r
localStateView.setVisibility(View.VISIBLE);\r
+\r
+ } else if ( //uploading\r
+ uploaderBinder != null &&\r
+ uploaderBinder.isUploading(mAccount, file)\r
+ ) {\r
+ localStateView.setImageResource(\r
+ file.isFolder() ?\r
+ R.drawable.synchronizing_file_indicator :\r
+ R.drawable.uploading_file_indicator\r
+ );\r
+ localStateView.setVisibility(View.VISIBLE);\r
+\r
+ } else if (file.getEtagInConflict() != null) { // conflict\r
+ localStateView.setImageResource(R.drawable.conflict_file_indicator);\r
+ localStateView.setVisibility(View.VISIBLE);\r
+\r
} else if (file.isDown()) {\r
localStateView.setImageResource(R.drawable.local_file_indicator);\r
localStateView.setVisibility(View.VISIBLE);\r
- } else {\r
- localStateView.setVisibility(View.INVISIBLE);\r
}\r
\r
// share with me icon\r
\r
break;\r
}\r
+\r
+ ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+ checkBoxV.setVisibility(View.GONE);\r
+\r
+ AbsListView parentList = (AbsListView)parent;\r
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+ if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+ checkBoxV.setVisibility(View.GONE);\r
+ } else if (parentList.getCheckedItemCount() > 0){\r
+ if (parentList.isItemChecked(position)) {\r
+ checkBoxV.setImageResource(\r
+ android.R.drawable.checkbox_on_background);\r
+ } else {\r
+ checkBoxV.setImageResource(\r
+ android.R.drawable.checkbox_off_background);\r
+ }\r
+ checkBoxV.setVisibility(View.VISIBLE);\r
+ }\r
+ }\r
\r
// For all Views\r
\r
\r
// No Folder\r
if (!file.isFolder()) {\r
- if (file.isImage() && file.getRemoteId() != null){\r
+ if ((file.isImage() || file.isVideo()) && file.getRemoteId() != null){\r
// Thumbnail in Cache?\r
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
- String.valueOf(file.getRemoteId())\r
- );\r
+ "t" + String.valueOf(file.getRemoteId()));\r
if (thumbnail != null && !file.needsUpdateThumbnail()){\r
- fileIcon.setImageBitmap(thumbnail);\r
+ \r
+ if (file.isVideo()) {\r
+ Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);\r
+ fileIcon.setImageBitmap(withOverlay);\r
+ } else {\r
+ fileIcon.setImageBitmap(thumbnail);\r
+ }\r
} else {\r
// generate new Thumbnail\r
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
task\r
);\r
fileIcon.setImageDrawable(asyncDrawable);\r
- task.execute(file);\r
+ task.execute(file, true);\r
}\r
}\r
+\r
+ if (file.getMimetype().equalsIgnoreCase("image/png")) {\r
+ fileIcon.setBackgroundColor(mContext.getResources()\r
+ .getColor(R.color.background_color));\r
+ }\r
+\r
+\r
} else {\r
- fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(),\r
+ fileIcon.setImageResource(MimetypeIconUtil.getFileTypeIconId(file.getMimetype(),\r
file.getFileName()));\r
}\r
\r
} else {\r
// Folder\r
- if (checkIfFileIsSharedWithMe(file)) {\r
- fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
- } else if (file.isShareByLink()) {\r
- // If folder is sharedByLink, icon folder must be changed to\r
- // folder-public one\r
- fileIcon.setImageResource(R.drawable.folder_public);\r
- } else {\r
- fileIcon.setImageResource(\r
- DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())\r
- );\r
- }\r
+ fileIcon.setImageResource(\r
+ MimetypeIconUtil.getFolderTypeIconId(\r
+ checkIfFileIsSharedWithMe(file), file.isShareByLink()));\r
}\r
}\r
\r
- return view;\r
- }\r
-\r
- /**\r
- * Local Folder size in human readable format\r
- * \r
- * @param path\r
- * String\r
- * @return Size in human readable format\r
- */\r
- private String getFolderSizeHuman(String path) {\r
-\r
- File dir = new File(path);\r
-\r
- if (dir.exists()) {\r
- long bytes = FileStorageUtils.getFolderSize(dir);\r
- return DisplayUtils.bytesToHumanReadable(bytes);\r
+ if (mSelection.get(position) != null) {\r
+ view.setBackgroundColor(Color.rgb(248, 248, 248));\r
+ } else {\r
+ view.setBackgroundColor(Color.WHITE);\r
}\r
\r
- return "0 B";\r
+ return view;\r
}\r
\r
- /**\r
- * Local Folder size\r
- * @param dir File\r
- * @return Size in bytes\r
- */\r
- private long getFolderSize(File dir) {\r
- if (dir.exists()) {\r
- long result = 0;\r
- File[] fileList = dir.listFiles();\r
- for(int i = 0; i < fileList.length; i++) {\r
- if(fileList[i].isDirectory()) {\r
- result += getFolderSize(fileList[i]);\r
- } else {\r
- result += fileList[i].length();\r
- }\r
- }\r
- return result;\r
- }\r
- return 0;\r
- } \r
-\r
@Override\r
public int getViewTypeCount() {\r
return 1;\r
* mStorageManager if is different (and not NULL)\r
*/\r
public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager\r
- /*, boolean onlyOnDevice*/) {\r
+ , boolean onlyOnDevice) {\r
mFile = directory;\r
if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
mStorageManager = updatedStorageManager;\r
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
}\r
if (mStorageManager != null) {\r
- // TODO Enable when "On Device" is recovered ?\r
- mFiles = mStorageManager.getFolderContent(mFile/*, onlyOnDevice*/);\r
+ mFiles = mStorageManager.getFolderContent(mFile, onlyOnDevice);\r
mFilesOrig.clear();\r
mFilesOrig.addAll(mFiles);\r
\r
mFiles = null;\r
}\r
\r
- mFiles = FileStorageUtils.sortFolder(mFiles);\r
+ mFiles = FileStorageUtils.sortOcFolder(mFiles);\r
notifyDataSetChanged();\r
}\r
\r
FileStorageUtils.mSortAscending = ascending;\r
\r
\r
- mFiles = FileStorageUtils.sortFolder(mFiles);\r
+ mFiles = FileStorageUtils.sortOcFolder(mFiles);\r
notifyDataSetChanged();\r
\r
}\r
public void setGridMode(boolean gridMode) {\r
mGridMode = gridMode;\r
}\r
+\r
+ public boolean isGridMode() {\r
+ return mGridMode;\r
+ }\r
+\r
+ public void setNewSelection(int position, boolean checked) {\r
+ mSelection.put(position, checked);\r
+ notifyDataSetChanged();\r
+ }\r
+\r
+ public void removeSelection(int position) {\r
+ mSelection.remove(position);\r
+ notifyDataSetChanged();\r
+ }\r
+\r
+ public void removeSelection(){\r
+ mSelection.clear();\r
+ notifyDataSetChanged();\r
+ }\r
+\r
+ public ArrayList<Integer> getCheckedItemPositions() {\r
+ ArrayList<Integer> ids = new ArrayList<Integer>();\r
+\r
+ for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+ if (entry.getValue()){\r
+ ids.add(entry.getKey());\r
+ }\r
+ }\r
+ return ids;\r
+ }\r
+\r
+ public ArrayList<OCFile> getCheckedItems() {\r
+ ArrayList<OCFile> files = new ArrayList<OCFile>();\r
+\r
+ for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+ if (entry.getValue()){\r
+ files.add((OCFile) getItem(entry.getKey()));\r
+ }\r
+ }\r
+ return files;\r
+ }\r
}\r
*/
package com.owncloud.android.ui.fragment;
-import java.io.File;
-
+import android.accounts.Account;
import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.net.Uri;
import android.os.Bundle;
+import android.preference.PreferenceManager;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.ActionMode;
+import android.support.v7.app.AlertDialog;
import android.view.ContextMenu;
+import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.PopupMenu;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.files.FileMenuFilter;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+import com.owncloud.android.media.MediaService;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.activity.FolderPickerActivity;
import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
+import com.owncloud.android.ui.activity.UploadFilesActivity;
import com.owncloud.android.ui.adapter.FileListListAdapter;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
+import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
+import com.owncloud.android.ui.dialog.FileActionsDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
+import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
+import com.owncloud.android.ui.dialog.UploadSourceDialogFragment;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.ExceptionHandler;
+import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.ui.preview.PreviewTextFragment;
import com.owncloud.android.utils.FileStorageUtils;
+import java.io.File;
+import java.util.ArrayList;
+
/**
* A Fragment that lists all files and folders in a given path.
- *
+ *
* TODO refactor to get rid of direct dependency on FileDisplayActivity
*/
public class OCFileListFragment extends ExtendedListFragment {
private static final String MY_PACKAGE = OCFileListFragment.class.getPackage() != null ?
OCFileListFragment.class.getPackage().getName() : "com.owncloud.android.ui.fragment";
-
+
public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS";
public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL";
-
+ public final static String ARG_HIDE_FAB = MY_PACKAGE + ".HIDE_FAB";
+
private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
+ private static final String KEY_FAB_EVER_CLICKED = "FAB_EVER_CLICKED";
+
+ private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
private FileFragment.ContainerActivity mContainerActivity;
-
+
private OCFile mFile = null;
private FileListListAdapter mAdapter;
private boolean mJustFolders;
private OCFile mTargetFile;
-
-
+
+ private boolean miniFabClicked = false;
/**
* {@inheritDoc}
Log_OC.e(TAG, "onAttach");
try {
mContainerActivity = (FileFragment.ContainerActivity) activity;
-
+
} catch (ClassCastException e) {
- throw new ClassCastException(activity.toString() + " must implement " +
+ throw new ClassCastException(activity.toString() + " must implement " +
FileFragment.ContainerActivity.class.getSimpleName());
}
try {
setOnRefreshListener((OnEnforceableRefreshListener) activity);
} catch (ClassCastException e) {
- throw new ClassCastException(activity.toString() + " must implement " +
+ throw new ClassCastException(activity.toString() + " must implement " +
SwipeRefreshLayout.OnRefreshListener.class.getSimpleName());
}
}
-
+
@Override
public void onDetach() {
setOnRefreshListener(null);
mJustFolders,
getActivity(),
mContainerActivity
- );
+ );
setListAdapter(mAdapter);
- registerForContextMenu();
+ registerLongClickListener();
+
+ boolean hideFab = (args != null) && args.getBoolean(ARG_HIDE_FAB, false);
+ if (hideFab) {
+ setFabEnabled(false);
+ } else {
+ setFabEnabled(true);
+ registerFabListeners();
+
+ // detect if a mini FAB has ever been clicked
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ if(prefs.getLong(KEY_FAB_EVER_CLICKED, 0) > 0) {
+ miniFabClicked = true;
+ }
+
+ // add labels to the min FABs when none of them has ever been clicked on
+ if(!miniFabClicked) {
+ setFabLabels();
+ } else {
+ removeFabLabels();
+ }
+ }
}
/**
+ * adds labels to all mini FABs.
+ */
+ private void setFabLabels() {
+ getFabUpload().setTitle(getResources().getString(R.string.actionbar_upload));
+ getFabMkdir().setTitle(getResources().getString(R.string.actionbar_mkdir));
+ getFabUploadFromApp().setTitle(getResources().getString(R.string.actionbar_upload_from_apps));
+ }
+
+ /**
+ * registers all listeners on all mini FABs.
+ */
+ private void registerFabListeners() {
+ registerFabUploadListeners();
+ registerFabMkDirListeners();
+ registerFabUploadFromAppListeners();
+ }
+
+ /**
+ * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
+ * on the Upload mini FAB for the linked action and {@link Toast} showing the underlying action.
+ */
+ private void registerFabUploadListeners() {
+ getFabUpload().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent action = new Intent(getActivity(), UploadFilesActivity.class);
+ action.putExtra(
+ UploadFilesActivity.EXTRA_ACCOUNT,
+ ((FileActivity) getActivity()).getAccount()
+ );
+ getActivity().startActivityForResult(action, UploadSourceDialogFragment.ACTION_SELECT_MULTIPLE_FILES);
+ getFabMain().collapse();
+ recordMiniFabClick();
+ }
+ });
+
+ getFabUpload().setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ Toast.makeText(getActivity(), R.string.actionbar_upload, Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ });
+ }
+
+ /**
+ * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
+ * on the 'Create Dir' mini FAB for the linked action and {@link Toast} showing the underlying action.
+ */
+ private void registerFabMkDirListeners() {
+ getFabMkdir().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CreateFolderDialogFragment dialog =
+ CreateFolderDialogFragment.newInstance(mFile);
+ dialog.show(getActivity().getSupportFragmentManager(), FileDisplayActivity.DIALOG_CREATE_FOLDER);
+ getFabMain().collapse();
+ recordMiniFabClick();
+ }
+ });
+
+ getFabMkdir().setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ Toast.makeText(getActivity(), R.string.actionbar_mkdir, Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ });
+ }
+
+ /**
+ * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
+ * on the Upload from App mini FAB for the linked action and {@link Toast} showing the underlying action.
+ */
+ private void registerFabUploadFromAppListeners() {
+ getFabUploadFromApp().setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent action = new Intent(Intent.ACTION_GET_CONTENT);
+ action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
+
+ //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ }
+
+ getActivity().startActivityForResult(
+ Intent.createChooser(action, getString(R.string.upload_chooser_title)),
+ UploadSourceDialogFragment.ACTION_SELECT_CONTENT_FROM_APPS
+ );
+ getFabMain().collapse();
+ recordMiniFabClick();
+ }
+ });
+
+ getFabUploadFromApp().setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ Toast.makeText(getActivity(),
+ R.string.actionbar_upload_from_apps,
+ Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ });
+ }
+
+ /**
+ * records a click on a mini FAB and thus:
+ * <ol>
+ * <li>persists the click fact</li>
+ * <li>removes the mini FAB labels</li>
+ * </ol>
+ */
+ private void recordMiniFabClick() {
+ // only record if it hasn't been done already at some other time
+ if(!miniFabClicked) {
+ final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ sp.edit().putLong(KEY_FAB_EVER_CLICKED, 1).commit();
+ miniFabClicked = true;
+ }
+ }
+
+ /**
+ * removes the labels on all known min FABs.
+ */
+ private void removeFabLabels() {
+ getFabUpload().setTitle(null);
+ getFabMkdir().setTitle(null);
+ getFabUploadFromApp().setTitle(null);
+ ((TextView) getFabUpload().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
+ ((TextView) getFabMkdir().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
+ ((TextView) getFabUploadFromApp().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
+ }
+
+ private void registerLongClickListener() {
+ getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
+ private Menu menu;
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+ final int checkedCount = getListView().getCheckedItemCount();
+ // TODO Tobi extract to values
+ mode.setTitle(checkedCount + " selected");
+
+ if (checked) {
+ mAdapter.setNewSelection(position, checked);
+ } else {
+ mAdapter.removeSelection(position);
+ }
+
+ // TODO maybe change: only recreate menu if count changes
+ menu.clear();
+ if (checkedCount == 1) {
+ createContextMenu(menu);
+ } else {
+ // download, move, copy, delete
+ getActivity().getMenuInflater().inflate(R.menu.multiple_file_actions_menu, menu);
+ }
+
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ this.menu = menu;
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return onFileActionChosen(item.getItemId());
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ mAdapter.removeSelection();
+ }
+ });
+ }
+
+
+ private void showFileAction(int fileIndex) {
+ Bundle args = getArguments();
+ PopupMenu pm = new PopupMenu(getActivity(),null);
+ Menu menu = pm.getMenu();
+
+ boolean allowContextualActions =
+ (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
+
+ if (allowContextualActions) {
+ MenuInflater inflater = getActivity().getMenuInflater();
+
+ inflater.inflate(R.menu.file_actions_menu, menu);
+ OCFile targetFile = (OCFile) mAdapter.getItem(fileIndex);
+
+ if (mContainerActivity.getStorageManager() != null) {
+ FileMenuFilter mf = new FileMenuFilter(
+ targetFile,
+ mContainerActivity.getStorageManager().getAccount(),
+ mContainerActivity,
+ getActivity()
+ );
+ mf.filter(menu);
+ }
+
+ /// TODO break this direct dependency on FileDisplayActivity... if possible
+ MenuItem item = menu.findItem(R.id.action_open_file_with);
+ FileFragment frag = ((FileDisplayActivity)getActivity()).getSecondFragment();
+ if (frag != null && frag instanceof FileDetailFragment &&
+ frag.getFile().getFileId() == targetFile.getFileId()) {
+ item = menu.findItem(R.id.action_see_details);
+ if (item != null) {
+ item.setVisible(false);
+ item.setEnabled(false);
+ }
+ }
+
+ FileActionsDialogFragment dialog = FileActionsDialogFragment.newInstance(menu, fileIndex, targetFile.getFileName());
+ dialog.setTargetFragment(this, 0);
+ dialog.show(getFragmentManager(), FileActionsDialogFragment.FTAG_FILE_ACTIONS);
+ }
+ }
+
+ /**
* Saves the current listed folder.
*/
@Override
- public void onSaveInstanceState (Bundle outState) {
+ public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(KEY_FILE, mFile);
}
-
+
/**
* Call this, when the user presses the up button.
- *
- * Tries to move up the current folder one level. If the parent folder was removed from the
- * database, it continues browsing up until finding an existing folders.
- *
- * return Count of folder levels browsed up.
+ * <p>
+ * Tries to move up the current folder one level. If the parent folder was removed from the
+ * database, it continues browsing up until finding an existing folders.
+ * </p>
+ * @return Count of folder levels browsed up.
*/
public int onBrowseUp() {
OCFile parentDir = null;
int moveCount = 0;
-
- if(mFile != null){
+
+ if (mFile != null) {
FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-
+
String parentPath = null;
if (mFile.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) {
parentPath = new File(mFile.getRemotePath()).getParent();
- parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
- parentPath + OCFile.PATH_SEPARATOR;
+ parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
+ parentPath + OCFile.PATH_SEPARATOR;
parentDir = storageManager.getFileByPath(parentPath);
moveCount++;
} else {
}
while (parentDir == null) {
parentPath = new File(parentPath).getParent();
- parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
- parentPath + OCFile.PATH_SEPARATOR;
+ parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :
+ parentPath + OCFile.PATH_SEPARATOR;
parentDir = storageManager.getFileByPath(parentPath);
moveCount++;
} // exit is granted because storageManager.getFileByPath("/") never returns null
mFile = parentDir;
- // TODO Enable when "On Device" is recovered ?
- listDirectory(mFile /*, MainApp.getOnlyOnDevice()*/);
+ listDirectory(mFile, MainApp.getOnlyOnDevice());
onRefresh(false);
-
+
// restore index and top position
restoreIndexAndTopPosition();
-
+
} // else - should never happen now
-
+
return moveCount;
}
-
+
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
OCFile file = (OCFile) mAdapter.getItem(position);
if (file != null) {
- if (file.isFolder()) {
+ if (file.isFolder()) {
// update state and view of this fragment
- // TODO Enable when "On Device" is recovered ?
- listDirectory(file/*, MainApp.getOnlyOnDevice()*/);
+ listDirectory(file, MainApp.getOnlyOnDevice());
// then, notify parent activity to let it update its state and view
mContainerActivity.onBrowsedDownTo(file);
// save index and top position
saveIndexAndTopPosition(position);
-
+
} else { /// Click on a file
if (PreviewImageFragment.canBePreviewed(file)) {
// preview image - it handles the download, if needed
((FileDisplayActivity)mContainerActivity).startImagePreview(file);
-
- } else if (file.isDown()) {
- if (PreviewMediaFragment.canBePreviewed(file)) {
+ } else if (PreviewTextFragment.canBePreviewed(file)){
+ ((FileDisplayActivity)mContainerActivity).startTextPreview(file);
+ } else if (PreviewMediaFragment.canBePreviewed(file)) {
// media preview
- ((FileDisplayActivity)mContainerActivity).startMediaPreview(file, 0, true);
- } else {
+ ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true);
+ } else if (file.isDown()) {
mContainerActivity.getFileOperationsHelper().openFile(file);
- }
-
} else {
// automatic download, preview on finish
- ((FileDisplayActivity)mContainerActivity).startDownloadForPreview(file);
+ ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file);
}
-
}
-
} else {
Log_OC.d(TAG, "Null object in ListAdapter!!");
}
-
}
-
+
/**
* {@inheritDoc}
*/
- @Override
- public void onCreateContextMenu (
- ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
+ // TODO Tobi needed?
+ public void createContextMenu(Menu menu) {
Bundle args = getArguments();
- boolean allowContextualActions =
- (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
+ boolean allowContextualActions =
+ (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
if (allowContextualActions) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.file_actions_menu, menu);
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
- OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
-
+ OCFile targetFile = null;
+ if (mAdapter.getCheckedItems().size() == 1){
+ targetFile = mAdapter.getCheckedItems().get(0);
+ }
+
if (mContainerActivity.getStorageManager() != null) {
FileMenuFilter mf = new FileMenuFilter(
targetFile,
item.setEnabled(false);
}
}
+
+// String.format(mContext.getString(R.string.subject_token),
+// getClient().getCredentials().getUsername(), file.getFileName()));
}
}
-
+
+ public boolean onFileActionChosen(int menuId) {
+ if (mAdapter.getCheckedItems().size() == 1){
+ OCFile mTargetFile = mAdapter.getCheckedItems().get(0);
+
+ switch (menuId) {
+ case R.id.action_share_file: {
+ mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
+ return true;
+ }
+ case R.id.action_open_file_with: {
+ mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
+ return true;
+ }
+ case R.id.action_unshare_file: {
+ mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
+ return true;
+ }
+ case R.id.action_rename_file: {
+ RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
+ dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
+ return true;
+ }
+ case R.id.action_remove_file: {
+ RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
+ dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+ return true;
+ }
+ case R.id.action_download_file:
+ case R.id.action_sync_file: {
+ mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
+ return true;
+ }
+ case R.id.action_cancel_sync: {
+ ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
+ return true;
+ }
+ case R.id.action_see_details: {
+ mContainerActivity.showDetails(mTargetFile);
+ return true;
+ }
+ case R.id.action_send_file: {
+ // Obtain the file
+ if (!mTargetFile.isDown()) { // Download the file
+ Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
+ ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
+ return true;
+ } else {
+ mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
+ }
+ }
+ case R.id.action_stream_file: {
+ Account account = ((FileActivity)mContainerActivity).getAccount();
+ Context context = MainApp.getAppContext();
+ String uri = PreviewMediaFragment.generateUrlWithCredentials(account, context, mTargetFile);
+ MediaService.streamWithExternalApp(uri, getActivity()).show();
+ return true;
+ }
+ case R.id.action_move: {
+ Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+ ArrayList files = new ArrayList();
+ files.add(mTargetFile);
+ action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, files);
+ getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+ return true;
+ }
+ case R.id.action_favorite_file: {
+ mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
+ return true;
+ }
+ case R.id.action_unfavorite_file: {
+ mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
+ return true;
+ }
+ case R.id.action_copy:
+ Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+
+ // Pass mTargetFile that contains info of selected file/folder
+ action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
+ getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ ArrayList<OCFile> mTargetFiles = mAdapter.getCheckedItems();
+
+ switch (menuId) {
+ case R.id.action_remove_file: {
+ RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(mTargetFiles);
+ dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+ return true;
+ }
+ case R.id.action_download_file:
+ case R.id.action_sync_file: {
+ mContainerActivity.getFileOperationsHelper().syncFiles(mTargetFiles);
+ return true;
+ }
+ case R.id.action_move: {
+ Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+ action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+ getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+ return true;
+ }
+ case R.id.action_favorite_file: {
+ mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, true);
+ return true;
+ }
+ case R.id.action_unfavorite_file: {
+ mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, false);
+ return true;
+ }
+ case R.id.action_copy:
+ Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+ action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+ getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ }
/**
* {@inhericDoc}
*/
@Override
public boolean onContextItemSelected (MenuItem item) {
- AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
- mTargetFile = (OCFile) mAdapter.getItem(info.position);
- switch (item.getItemId()) {
- case R.id.action_share_file: {
- mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
- return true;
- }
- case R.id.action_open_file_with: {
- mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
- return true;
- }
- case R.id.action_unshare_file: {
- mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
- return true;
- }
- case R.id.action_rename_file: {
- RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
- dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
- return true;
- }
- case R.id.action_remove_file: {
- RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
- dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
- return true;
- }
- case R.id.action_download_file:
- case R.id.action_sync_file: {
- mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
- return true;
- }
- case R.id.action_cancel_download:
- case R.id.action_cancel_upload: {
- ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile);
- return true;
- }
- case R.id.action_see_details: {
- mContainerActivity.showDetails(mTargetFile);
- return true;
- }
- case R.id.action_send_file: {
- // Obtain the file
- if (!mTargetFile.isDown()) { // Download the file
- Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
- ((FileDisplayActivity)mContainerActivity).startDownloadForSending(mTargetFile);
-
- } else {
- mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
- }
- return true;
- }
- case R.id.action_move: {
- Intent action = new Intent(getActivity(), FolderPickerActivity.class);
-
- // Pass mTargetFile that contains info of selected file/folder
- action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
- getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
- return true;
- }
- case R.id.action_favorite_file:{
- mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
- return true;
- }
- case R.id.action_unfavorite_file:{
- mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
- return true;
- }
- default:
- return super.onContextItemSelected(item);
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+ boolean matched = onFileActionChosen(item.getItemId());
+ if(!matched) {
+ return super.onContextItemSelected(item);
+ } else {
+ return matched;
}
}
/**
* Use this to query the {@link OCFile} that is currently
* being displayed by this fragment
+ *
* @return The currently viewed OCFile
*/
- public OCFile getCurrentFile(){
+ public OCFile getCurrentFile() {
return mFile;
}
-
+
/**
- * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter
+ * Calls {@link OCFileListFragment#listDirectory(OCFile, boolean)} with a null parameter
*/
- public void listDirectory(/*boolean onlyOnDevice*/){
- listDirectory(null);
- // TODO Enable when "On Device" is recovered ?
- // listDirectory(null, onlyOnDevice);
+ public void listDirectory(boolean onlyOnDevice){
+ listDirectory(null, onlyOnDevice);
}
public void refreshDirectory(){
- // TODO Enable when "On Device" is recovered ?
- listDirectory(getCurrentFile()/*, MainApp.getOnlyOnDevice()*/);
+ listDirectory(getCurrentFile(), MainApp.getOnlyOnDevice());
}
-
+
/**
* Lists the given directory on the view. When the input parameter is null,
* it will either refresh the last known directory. list the root
* if there never was a directory.
- *
+ *
* @param directory File to be listed
*/
- public void listDirectory(OCFile directory/*, boolean onlyOnDevice*/) {
+ public void listDirectory(OCFile directory, boolean onlyOnDevice) {
FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
if (storageManager != null) {
// Check input parameters for null
- if(directory == null){
- if(mFile != null){
+ if (directory == null) {
+ if (mFile != null) {
directory = mFile;
} else {
directory = storageManager.getFileByPath("/");
if (directory == null) return; // no files, wait for sync
}
}
-
-
+
+
// If that's not a directory -> List its parent
- if(!directory.isFolder()){
+ if (!directory.isFolder()) {
Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString());
directory = storageManager.getFileById(directory.getParentId());
}
- // TODO Enable when "On Device" is recovered ?
- mAdapter.swapDirectory(directory, storageManager/*, onlyOnDevice*/);
+ mAdapter.swapDirectory(directory, storageManager, onlyOnDevice);
if (mFile == null || !mFile.equals(directory)) {
mCurrentListView.setSelection(0);
}
if (file.isFolder()) {
foldersCount++;
} else {
- filesCount++;
- if (file.isImage() || file.isVideo()){
- imagesCount++;
+ if (!file.isHidden()) {
+ filesCount++;
+
- if (file.isImage()) {
++ if (file.isImage() || file.isVideo()) {
+ imagesCount++;
+ }
}
}
}
OwnCloudVersion version = AccountUtils.getServerVersion(
((FileActivity)mContainerActivity).getAccount());
if (version != null && version.supportsRemoteThumbnails() &&
- imagesCount > 0 && imagesCount == filesCount) {
+ DisplayUtils.isGridView(mFile, mContainerActivity.getStorageManager())) {
switchToGridView();
+ registerLongClickListener();
} else {
switchToListView();
+ // switchToGridView();
}
}
}
return output;
}
-
public void sortByName(boolean descending) {
mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
}
public void sortBySize(boolean descending) {
mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
}
-
-
}