From: tobiasKaminsky Date: Sun, 1 Nov 2015 08:14:09 +0000 (+0100) Subject: Merge remote-tracking branch 'remotes/upstream/video_thumbnail' into beta X-Git-Tag: beta-20151122~54 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/ec83a9f100897cf93df8aba990ab348ddfaaf05e?ds=inline;hp=-c Merge remote-tracking branch 'remotes/upstream/video_thumbnail' into beta --- ec83a9f100897cf93df8aba990ab348ddfaaf05e diff --combined CHANGELOG.md index 607bdf05,6934155f..5e8ca43f --- a/CHANGELOG.md +++ b/CHANGELOG.md @@@ -1,26 -1,42 +1,30 @@@ -## 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 diff --combined src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 56c9063d,5806a408..10dfbd71 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@@ -24,30 -24,25 +24,34 @@@ package com.owncloud.android.datamodel 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; @@@ -60,6 -55,7 +64,7 @@@ import com.owncloud.android.lib.resourc 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. @@@ -81,8 -77,8 +86,8 @@@ public class ThumbnailsCacheManager public static Bitmap mDefaultImg = BitmapFactory.decodeResource( - MainApp.getAppContext().getResources(), - DisplayUtils.getFileTypeIconId("image/png", "default.png") + MainApp.getAppContext().getResources(), + R.drawable.file_image ); @@@ -147,36 -143,13 +152,36 @@@ 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 { private final WeakReference mImageViewReference; + private WeakReference 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 @@@ -187,12 -160,6 +192,12 @@@ mAccount = account; } + public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, + Account account, ProgressBar progressWheel) { + this(imageView, storageManager, account); + mProgressWheelRef = new WeakReference(progressWheel); + } + public ThumbnailGenerationTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage collected mImageViewReference = new WeakReference(imageView); @@@ -211,15 -178,23 +216,25 @@@ } 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){ @@@ -234,6 -209,10 +249,6 @@@ } protected void onPostExecute(Bitmap bitmap){ - if (isCancelled()) { - bitmap = null; - } - if (bitmap != null) { final ImageView imageView = mImageViewReference.get(); final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); @@@ -245,14 -224,7 +260,14 @@@ 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); } } } @@@ -263,13 -235,12 +278,13 @@@ * @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); @@@ -290,56 -261,25 +305,56 @@@ 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); @@@ -351,50 -291,24 +366,50 @@@ 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(); @@@ -410,52 -324,24 +425,52 @@@ } - 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; @@@ -472,7 -358,6 +487,7 @@@ 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; @@@ -493,6 -378,51 +508,51 @@@ 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 bitmapWorkerTaskReference; diff --combined src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 956c7d1f,26d77db5..40372e38 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@@ -4,7 -4,6 +4,7 @@@ * @author Bartek Przybylski * @author Tobias Kaminsky * @author David A. Velasco + * @author masensio * Copyright (C) 2011 Bartek Przybylski * Copyright (C) 2015 ownCloud Inc. * @@@ -25,16 -24,15 +25,19 @@@ package com.owncloud.android.ui.adapter import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.util.Vector; import android.accounts.Account; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; +import android.graphics.Color; + import android.graphics.BitmapFactory; + import android.graphics.Canvas; + import android.graphics.Paint; import android.os.Build; import android.preference.PreferenceManager; import android.text.format.DateUtils; @@@ -59,7 -57,6 +62,7 @@@ import com.owncloud.android.services.Op import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; +import com.owncloud.android.utils.MimetypeIconUtil; /** @@@ -83,8 -80,6 +86,8 @@@ public class FileListListAdapter extend private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM }; private SharedPreferences mAppPreferences; + + private HashMap mSelection = new HashMap(); public FileListListAdapter( boolean justFolders, @@@ -160,7 -155,7 +163,7 @@@ ViewType viewType; if (!mGridMode){ viewType = ViewType.LIST_ITEM; - } else if (file.isImage()){ + } else if (file.isImage() || file.isVideo()){ viewType = ViewType.GRID_IMAGE; } else { viewType = ViewType.GRID_ITEM; @@@ -200,37 -195,35 +203,37 @@@ switch (viewType){ case LIST_ITEM: TextView fileSizeV = (TextView) view.findViewById(R.id.file_size); + TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator); TextView lastModV = (TextView) view.findViewById(R.id.last_mod); - ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox); + lastModV.setVisibility(View.VISIBLE); lastModV.setText(showRelativeTimestamp(file)); - checkBoxV.setVisibility(View.GONE); + fileSizeSeparatorV.setVisibility(View.VISIBLE); fileSizeV.setVisibility(View.VISIBLE); fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength())); - if (!file.isFolder()) { - AbsListView parentList = (AbsListView)parent; - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) { - checkBoxV.setVisibility(View.GONE); - } else { - if (parentList.isItemChecked(position)) { - checkBoxV.setImageResource( - android.R.drawable.checkbox_on_background); - } else { - checkBoxV.setImageResource( - android.R.drawable.checkbox_off_background); - } - checkBoxV.setVisibility(View.VISIBLE); - } - } - - } else { //Folder +// if (!file.isFolder()) { +// AbsListView parentList = (AbsListView)parent; +// if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { +// if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) { +// checkBoxV.setVisibility(View.GONE); +// } else { +// if (parentList.isItemChecked(position)) { +// checkBoxV.setImageResource( +// R.drawable.ic_checkbox_marked); +// } else { +// checkBoxV.setImageResource( +// R.drawable.ic_checkbox_blank_outline); +// } +// checkBoxV.setVisibility(View.VISIBLE); +// } +// } + + if (file.isFolder()) { + fileSizeSeparatorV.setVisibility(View.INVISIBLE); fileSizeV.setVisibility(View.INVISIBLE); } @@@ -257,47 -250,24 +260,47 @@@ mTransferServiceGetter.getFileDownloaderBinder(); FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder(); - boolean downloading = (downloaderBinder != null && - downloaderBinder.isDownloading(mAccount, file)); OperationsServiceBinder opsBinder = mTransferServiceGetter.getOperationsServiceBinder(); - downloading |= (opsBinder != null && - opsBinder.isSynchronizing(mAccount, file.getRemotePath())); - if (downloading) { - localStateView.setImageResource(R.drawable.downloading_file_indicator); + + localStateView.setVisibility(View.INVISIBLE); // default first + + if ( //synchronizing + opsBinder != null && + opsBinder.isSynchronizing(mAccount, file.getRemotePath()) + ) { + localStateView.setImageResource(R.drawable.synchronizing_file_indicator); localStateView.setVisibility(View.VISIBLE); - } else if (uploaderBinder != null && - uploaderBinder.isUploading(mAccount, file)) { - localStateView.setImageResource(R.drawable.uploading_file_indicator); + + } else if ( // downloading + downloaderBinder != null && + downloaderBinder.isDownloading(mAccount, file) + ) { + localStateView.setImageResource( + file.isFolder() ? + R.drawable.synchronizing_file_indicator : + R.drawable.downloading_file_indicator + ); localStateView.setVisibility(View.VISIBLE); + + } else if ( //uploading + uploaderBinder != null && + uploaderBinder.isUploading(mAccount, file) + ) { + localStateView.setImageResource( + file.isFolder() ? + R.drawable.synchronizing_file_indicator : + R.drawable.uploading_file_indicator + ); + localStateView.setVisibility(View.VISIBLE); + + } else if (file.getEtagInConflict() != null) { // conflict + localStateView.setImageResource(R.drawable.conflict_file_indicator); + localStateView.setVisibility(View.VISIBLE); + } else if (file.isDown()) { localStateView.setImageResource(R.drawable.local_file_indicator); localStateView.setVisibility(View.VISIBLE); - } else { - localStateView.setVisibility(View.INVISIBLE); } // share with me icon @@@ -313,25 -283,6 +316,25 @@@ break; } + + ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox); + checkBoxV.setVisibility(View.GONE); + + AbsListView parentList = (AbsListView)parent; + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) { + checkBoxV.setVisibility(View.GONE); + } else if (parentList.getCheckedItemCount() > 0){ + if (parentList.isItemChecked(position)) { + checkBoxV.setImageResource( + android.R.drawable.checkbox_on_background); + } else { + checkBoxV.setImageResource( + android.R.drawable.checkbox_off_background); + } + checkBoxV.setVisibility(View.VISIBLE); + } + } // For all Views @@@ -345,12 -296,19 +348,18 @@@ // No Folder if (!file.isFolder()) { - if (file.isImage() && file.getRemoteId() != null){ + if ((file.isImage() || file.isVideo()) && file.getRemoteId() != null){ // Thumbnail in Cache? Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( - String.valueOf(file.getRemoteId()) - ); + "t" + String.valueOf(file.getRemoteId())); if (thumbnail != null && !file.needsUpdateThumbnail()){ - fileIcon.setImageBitmap(thumbnail); + + if (file.isVideo()) { + Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail); + fileIcon.setImageBitmap(withOverlay); + } else { + fileIcon.setImageBitmap(thumbnail); + } } else { // generate new Thumbnail if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) { @@@ -368,38 -326,73 +377,38 @@@ task ); fileIcon.setImageDrawable(asyncDrawable); - task.execute(file); + task.execute(file, true); } } + + if (file.getMimetype().equalsIgnoreCase("image/png")) { + fileIcon.setBackgroundColor(mContext.getResources() + .getColor(R.color.background_color)); + } + + } else { - fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), + fileIcon.setImageResource(MimetypeIconUtil.getFileTypeIconId(file.getMimetype(), file.getFileName())); } } else { // Folder - if (checkIfFileIsSharedWithMe(file)) { - fileIcon.setImageResource(R.drawable.shared_with_me_folder); - } else if (file.isShareByLink()) { - // If folder is sharedByLink, icon folder must be changed to - // folder-public one - fileIcon.setImageResource(R.drawable.folder_public); - } else { - fileIcon.setImageResource( - DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()) - ); - } + fileIcon.setImageResource( + MimetypeIconUtil.getFolderTypeIconId( + checkIfFileIsSharedWithMe(file), file.isShareByLink())); } } - return view; - } - - /** - * Local Folder size in human readable format - * - * @param path - * String - * @return Size in human readable format - */ - private String getFolderSizeHuman(String path) { - - File dir = new File(path); - - if (dir.exists()) { - long bytes = FileStorageUtils.getFolderSize(dir); - return DisplayUtils.bytesToHumanReadable(bytes); + if (mSelection.get(position) != null) { + view.setBackgroundColor(Color.rgb(248, 248, 248)); + } else { + view.setBackgroundColor(Color.WHITE); } - return "0 B"; + return view; } - /** - * Local Folder size - * @param dir File - * @return Size in bytes - */ - private long getFolderSize(File dir) { - if (dir.exists()) { - long result = 0; - File[] fileList = dir.listFiles(); - for(int i = 0; i < fileList.length; i++) { - if(fileList[i].isDirectory()) { - result += getFolderSize(fileList[i]); - } else { - result += fileList[i].length(); - } - } - return result; - } - return 0; - } - @Override public int getViewTypeCount() { return 1; @@@ -423,14 -416,15 +432,14 @@@ * mStorageManager if is different (and not NULL) */ public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager - /*, boolean onlyOnDevice*/) { + , boolean onlyOnDevice) { mFile = directory; if (updatedStorageManager != null && updatedStorageManager != mStorageManager) { mStorageManager = updatedStorageManager; mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext); } if (mStorageManager != null) { - // TODO Enable when "On Device" is recovered ? - mFiles = mStorageManager.getFolderContent(mFile/*, onlyOnDevice*/); + mFiles = mStorageManager.getFolderContent(mFile, onlyOnDevice); mFilesOrig.clear(); mFilesOrig.addAll(mFiles); @@@ -441,7 -435,7 +450,7 @@@ mFiles = null; } - mFiles = FileStorageUtils.sortFolder(mFiles); + mFiles = FileStorageUtils.sortOcFolder(mFiles); notifyDataSetChanged(); } @@@ -488,7 -482,7 +497,7 @@@ FileStorageUtils.mSortAscending = ascending; - mFiles = FileStorageUtils.sortFolder(mFiles); + mFiles = FileStorageUtils.sortOcFolder(mFiles); notifyDataSetChanged(); } @@@ -501,45 -495,4 +510,45 @@@ public void setGridMode(boolean gridMode) { mGridMode = gridMode; } + + public boolean isGridMode() { + return mGridMode; + } + + public void setNewSelection(int position, boolean checked) { + mSelection.put(position, checked); + notifyDataSetChanged(); + } + + public void removeSelection(int position) { + mSelection.remove(position); + notifyDataSetChanged(); + } + + public void removeSelection(){ + mSelection.clear(); + notifyDataSetChanged(); + } + + public ArrayList getCheckedItemPositions() { + ArrayList ids = new ArrayList(); + + for (Map.Entry entry : mSelection.entrySet()){ + if (entry.getValue()){ + ids.add(entry.getKey()); + } + } + return ids; + } + + public ArrayList getCheckedItems() { + ArrayList files = new ArrayList(); + + for (Map.Entry entry : mSelection.entrySet()){ + if (entry.getValue()){ + files.add((OCFile) getItem(entry.getKey())); + } + } + return files; + } } diff --combined src/com/owncloud/android/ui/fragment/OCFileListFragment.java index 380396a9,5dfb329d..92177f4a --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@@ -22,32 -22,19 +22,32 @@@ */ 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; @@@ -55,34 -42,21 +55,34 @@@ import com.owncloud.android.datamodel.O 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 { @@@ -91,25 -65,21 +91,25 @@@ 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} @@@ -120,21 -90,21 +120,21 @@@ 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); @@@ -166,290 -136,41 +166,290 @@@ 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: + *
    + *
  1. persists the click fact
  2. + *
  3. removes the mini FAB labels
  4. + *
+ */ + 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. + *

+ * 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. */ 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 { @@@ -457,74 -178,81 +457,74 @@@ } 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, @@@ -546,146 -274,83 +546,146 @@@ 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 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; } } @@@ -693,53 -358,56 +693,53 @@@ /** * 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); } @@@ -760,12 -428,9 +760,12 @@@ 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++; + } } } } @@@ -776,11 -441,11 +776,12 @@@ 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(); } } } @@@ -825,6 -490,7 +826,6 @@@ return output; } - public void sortByName(boolean descending) { mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending); } @@@ -836,4 -502,6 +837,4 @@@ public void sortBySize(boolean descending) { mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending); } - - }