From: tobiasKaminsky Date: Mon, 26 Oct 2015 21:49:00 +0000 (+0100) Subject: Merge remote-tracking branch 'remotes/upstream/resizedImages' into beta X-Git-Tag: beta-20151122~102 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/d44c785d0727b71ab696d5a6216f00cf135867c6?ds=inline;hp=-c Merge remote-tracking branch 'remotes/upstream/resizedImages' into beta --- d44c785d0727b71ab696d5a6216f00cf135867c6 diff --combined AndroidManifest.xml index f0d59e4a,15db3df9..5d39e722 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@@ -1,4 -1,5 +1,4 @@@ - - + android:versionCode="10800000" + android:versionName="1.8.0" xmlns:android="http://schemas.android.com/apk/res/android"> @@@ -35,60 -36,70 +35,60 @@@ + android:minSdkVersion="14" + android:targetSdkVersion="22" /> - - + + android:theme="@style/Theme.ownCloud"> + android:label="@string/app_name"> - - - + + - - + - - + - - + - - + - - + - - + - + - + android:label="@string/app_name" + android:theme="@style/Theme.ownCloud.Fullscreen"> - + @@@ -98,7 -109,8 +98,7 @@@ + android:exported="true"> @@@ -112,21 -124,25 +112,26 @@@ android:name=".providers.FileContentProvider" android:authorities="@string/authority" android:enabled="true" - android:exported="false" + android:exported="true" android:label="@string/sync_string_files" - android:syncable="true" > - + android:syncable="true"> + + + + + @@@ -139,7 -155,7 +144,7 @@@ - + @@@ -151,7 -167,7 +156,7 @@@ - + @@@ -160,16 -176,12 +165,16 @@@ - + + + + + - + @@@ -179,11 -191,11 +184,11 @@@ android:label="@string/copy_link" android:icon="@drawable/copy_link"/> - - diff --combined owncloud-android-library index ecc3415e,f5fbca24..e7d9de77 --- a/owncloud-android-library +++ b/owncloud-android-library @@@ -1,1 -1,1 +1,1 @@@ - Subproject commit ecc3415e3e3c13fa8f73fdd51a88c1ab7087b199 -Subproject commit f5fbca24becbb01660abe2a7013c1b536ea8a301 ++Subproject commit e7d9de771281ae673e1b1f64983c2d7eb7dada9b diff --combined src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index f0ecf767,49bda88e..e8496951 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@@ -29,18 -29,23 +29,25 @@@ import org.apache.commons.httpclient.Ht 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.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; @@@ -74,8 -79,8 +81,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 ); @@@ -142,11 -147,12 +149,12 @@@ 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 @@@ -157,6 -163,12 +165,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); @@@ -175,12 -187,15 +189,15 @@@ } mFile = params[0]; + mIsThumbnail = (Boolean) params[1]; + if (mFile instanceof OCFile) { - thumbnail = doOCFileInBackground(); + thumbnail = doOCFileInBackground(mIsThumbnail); } else if (mFile instanceof File) { - thumbnail = doFileInBackground(); - //} else { do nothing + thumbnail = doFileInBackground(mIsThumbnail); + } else { + // do nothing } }catch(Throwable t){ @@@ -195,6 -210,10 +212,6 @@@ } protected void onPostExecute(Bitmap bitmap){ - if (isCancelled()) { - bitmap = null; - } - if (bitmap != null) { final ImageView imageView = mImageViewReference.get(); final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); @@@ -206,7 -225,14 +223,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); } } } @@@ -217,12 -243,13 +241,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); @@@ -243,31 -270,49 +268,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 temp = BitmapUtils.decodeSampledBitmapFromFile( - file.getStoragePath(), px, px); - Bitmap bitmap = ThumbnailUtils.extractThumbnail(temp, px, px); - Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( ++ Bitmap tempBitmap = BitmapUtils.decodeSampledBitmapFromFile( + file.getStoragePath(), pxW, pxH); ++ Bitmap bitmap = ThumbnailUtils.extractThumbnail(tempBitmap, pxW, pxH); if (bitmap != null) { - thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH); + // Handle PNG + if (file.getMimetype().equalsIgnoreCase("image/png")) { - bitmap = handlePNG(bitmap, px); ++ bitmap = handlePNG(bitmap, pxW); + } + - thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px); ++ thumbnail = addThumbnailToCache(imageKey, bitmap, ++ file.getStoragePath(), pxW, pxH); file.setNeedsUpdateThumbnail(false); mStorageManager.saveFile(file); @@@ -279,27 -324,44 +329,51 @@@ 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(), "/"); - pxW + "/" + pxH + 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); - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); - byte[] bytes = get.getResponseBody(); -- - // Handle PNG - if (file.getMimetype().equalsIgnoreCase("image/png")) { - thumbnail = handlePNG(thumbnail, px); - String type = ""; - if (mIsThumbnail){ - type = "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 { - type = "Resized image"; ++ Log_OC.d(TAG, "Status: " + status); + } - Log_OC.d("Thumbnail", - type + " size of " + file.getRemotePath() - + ": " + bytes.length); - - // bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); - - if (mIsThumbnail) { - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); ++ } else { ++ String gallery = ""; ++ if (serverOCVersion.supportsNativeGallery()){ ++ gallery = "gallery"; + } else { - thumbnail = bitmap; ++ gallery = "galleryplus"; } -- // Add thumbnail to cache -- if (thumbnail != null) { -- addBitmapToCache(imageKey, thumbnail); ++ 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(); } @@@ -314,37 -376,32 +388,45 @@@ } + 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() { + private Bitmap doFileInBackground(Boolean mIsThumbnail) { + Bitmap thumbnail = null; File file = (File)mFile; final String imageKey = String.valueOf(file.hashCode()); // Check disk cache in background thread - Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + 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; @@@ -361,7 -418,6 +443,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; diff --combined src/com/owncloud/android/files/FileOperationsHelper.java index fba62091,b5eeb614..88cc8843 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@@ -21,48 -21,52 +21,58 @@@ package com.owncloud.android.files; -import org.apache.http.protocol.HTTP; - import android.accounts.Account; +import android.content.ActivityNotFoundException; +import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + import android.graphics.Bitmap; import android.net.Uri; import android.support.v4.app.DialogFragment; import android.webkit.MimeTypeMap; 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.OCFile; + import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; - import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.services.OperationsService; +import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.ui.activity.FileActivity; + import com.owncloud.android.ui.adapter.DiskLruImageCacheFileProvider; import com.owncloud.android.ui.dialog.ShareLinkToDialog; +import org.apache.http.protocol.HTTP; + +import java.util.List; + + import java.io.ByteArrayOutputStream; + import java.io.File; + import java.io.FileNotFoundException; + import java.io.FileOutputStream; + import java.io.IOException; + /** * */ public class FileOperationsHelper { private static final String TAG = FileOperationsHelper.class.getName(); - - private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; + + private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; protected FileActivity mFileActivity = null; /// Identifier of operation in progress which result shouldn't be lost private long mWaitingForOpId = Long.MAX_VALUE; - + public FileOperationsHelper(FileActivity fileActivity) { mFileActivity = fileActivity; } @@@ -72,7 -76,7 +82,7 @@@ if (file != null) { String storagePath = file.getStoragePath(); String encodedStoragePath = WebdavUtils.encodePath(storagePath); - + Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW); intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype()); intentForSavedMimeType.setFlags( @@@ -92,61 -96,36 +102,61 @@@ ); } } - - Intent chooserIntent; + + Intent openFileWithIntent; if (intentForGuessedMimeType != null) { - chooserIntent = Intent.createChooser(intentForGuessedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); + openFileWithIntent = intentForGuessedMimeType; } else { - chooserIntent = Intent.createChooser(intentForSavedMimeType, mFileActivity.getString(R.string.actionbar_open_with)); + openFileWithIntent = intentForSavedMimeType; } - - mFileActivity.startActivity(chooserIntent); - + + List launchables = mFileActivity.getPackageManager(). + queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS); + + if(launchables != null && launchables.size() > 0) { + try { + mFileActivity.startActivity( + Intent.createChooser( + openFileWithIntent, mFileActivity.getString(R.string.actionbar_open_with) + ) + ); + } catch (ActivityNotFoundException anfe) { + showNoAppForFileTypeToast(mFileActivity.getApplicationContext()); + } + } else { + showNoAppForFileTypeToast(mFileActivity.getApplicationContext()); + } + } else { Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } } - - + + /** + * Displays a toast stating that no application could be found to open the file. + * + * @param context the context to be able to show a toast. + */ + private void showNoAppForFileTypeToast(Context context) { + Toast.makeText(context, + R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT) + .show(); + } + public void shareFileWithLink(OCFile file) { - + if (isSharedSupported()) { if (file != null) { String link = "https://fake.url"; Intent intent = createShareWithLinkIntent(link); - String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + String[] packagesToExclude = new String[]{mFileActivity.getPackageName()}; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file); chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); - + } else { Log_OC.wtf(TAG, "Trying to share a NULL OCFile"); } - + } else { // Show a Message Toast t = Toast.makeText( @@@ -155,13 -134,13 +165,13 @@@ t.show(); } } - - + + public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) { if (file != null) { mFileActivity.showLoadingDialog(); - + Intent service = new Intent(mFileActivity, OperationsService.class); service.setAction(OperationsService.ACTION_CREATE_SHARE); service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); @@@ -174,18 -153,18 +184,18 @@@ Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } } - - + + private Intent createShareWithLinkIntent(String link) { Intent intentToShareLink = new Intent(Intent.ACTION_SEND); intentToShareLink.putExtra(Intent.EXTRA_TEXT, link); intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE); - return intentToShareLink; + return intentToShareLink; } - - + + /** - * @return 'True' if the server supports the Share API + * @return 'True' if the server supports the Share API */ public boolean isSharedSupported() { if (mFileActivity.getAccount() != null) { @@@ -194,10 -173,10 +204,10 @@@ } return false; } - - + + public void unshareFileWithLink(OCFile file) { - + if (isSharedSupported()) { // Unshare the file Intent service = new Intent(mFileActivity, OperationsService.class); @@@ -207,27 -186,25 +217,27 @@@ mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); mFileActivity.showLoadingDialog(); - + } else { // Show a Message Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); t.show(); - + } } - + public void sendDownloadedFile(OCFile file) { if (file != null) { + String storagePath = file.getStoragePath(); + String encodedStoragePath = WebdavUtils.encodePath(storagePath); Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND); // set MimeType sendIntent.setType(file.getMimetype()); - sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + file.getStoragePath())); + sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath)); sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action - + // Show dialog, without the own app - String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + String[] packagesToExclude = new String[]{mFileActivity.getPackageName()}; DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file); chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); @@@ -236,9 -213,27 +246,27 @@@ } } + public void sendCachedImage(OCFile file) { + if (file != null) { + Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND); + // set MimeType + sendIntent.setType(file.getMimetype()); + // sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + "/#" + file.getRemoteId() + "#" + file.getFileName())); + sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + file.getRemotePath())); + sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action + + // Show dialog, without the own app + String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file); + chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); + } else { + Log_OC.wtf(TAG, "Trying to send a NULL OCFile"); + } + } - - ++ + public void syncFile(OCFile file) { - + if (!file.isFolder()){ Intent intent = new Intent(mFileActivity, OperationsService.class); intent.setAction(OperationsService.ACTION_SYNC_FILE); @@@ -256,24 -251,6 +284,24 @@@ mFileActivity.startService(intent); } } + + public void toggleFavorite(OCFile file, boolean isFavorite) { + file.setFavorite(isFavorite); + mFileActivity.getStorageManager().saveFile(file); + + /// register the OCFile instance in the observer service to monitor local updates + Intent observedFileIntent = FileObserverService.makeObservedFileIntent( + mFileActivity, + file, + mFileActivity.getAccount(), + isFavorite); + mFileActivity.startService(observedFileIntent); + + /// immediate content synchronization + if (file.isFavorite()) { + syncFile(file); + } + } public void renameFile(OCFile file, String newFilename) { // RenameFile @@@ -299,8 -276,8 +327,8 @@@ mFileActivity.showLoadingDialog(); } - - + + public void createFolder(String remotePath, boolean createFullPath) { // Create Folder Intent service = new Intent(mFileActivity, OperationsService.class); @@@ -333,8 -310,8 +361,8 @@@ downloaderBinder.cancel(account, file); // TODO - review why is this here, and solve in a better way - // Remove etag for parent, if file is a keep_in_sync - if (file.keepInSync()) { + // Remove etag for parent, if file is a favorite + if (file.isFavorite()) { OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId()); parent.setEtag(""); mFileActivity.getStorageManager().saveFile(parent); @@@ -347,9 -324,8 +375,9 @@@ /** * Start move file operation - * @param newfile File where it is going to be moved - * @param currentFile File with the previous info + * + * @param newfile File where it is going to be moved + * @param currentFile File with the previous info */ public void moveFile(OCFile newfile, OCFile currentFile) { // Move files @@@ -363,23 -339,6 +391,23 @@@ mFileActivity.showLoadingDialog(); } + /** + * Start copy file operation + * + * @param newfile File where it is going to be moved + * @param currentFile File with the previous info + */ + public void copyFile(OCFile newfile, OCFile currentFile) { + // Copy files + Intent service = new Intent(mFileActivity, OperationsService.class); + service.setAction(OperationsService.ACTION_COPY_FILE); + service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath()); + service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath()); + service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount()); + mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service); + + mFileActivity.showLoadingDialog(); + } public long getOpIdWaitingFor() { return mWaitingForOpId; @@@ -389,7 -348,7 +417,7 @@@ public void setOpIdWaitingFor(long waitingForOpId) { mWaitingForOpId = waitingForOpId; } - + /** * @return 'True' if the server doesn't need to check forbidden characters */ diff --combined src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 5e94e0f2,eb595383..5b68063c --- 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. * @@@ -55,7 -54,6 +55,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; /** @@@ -270,14 -268,15 +270,14 @@@ public class FileListListAdapter extend } // share with me icon - if (!file.isFolder()) { - ImageView sharedWithMeIconV = (ImageView) - view.findViewById(R.id.sharedWithMeIcon); - sharedWithMeIconV.bringToFront(); - if (checkIfFileIsSharedWithMe(file)) { - sharedWithMeIconV.setVisibility(View.VISIBLE); - } else { - sharedWithMeIconV.setVisibility(View.GONE); - } + ImageView sharedWithMeIconV = (ImageView) + view.findViewById(R.id.sharedWithMeIcon); + sharedWithMeIconV.bringToFront(); + if (checkIfFileIsSharedWithMe(file) && + (!file.isFolder() || !mGridMode)) { + sharedWithMeIconV.setVisibility(View.VISIBLE); + } else { + sharedWithMeIconV.setVisibility(View.GONE); } break; @@@ -287,7 -286,7 +287,7 @@@ // this if-else is needed even though favorite icon is visible by default // because android reuses views in listview - if (!file.keepInSync()) { + if (!file.isFavorite()) { view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE); } else { view.findViewById(R.id.favoriteIcon).setVisibility(View.VISIBLE); @@@ -319,26 -318,27 +319,26 @@@ 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())); } } diff --combined src/com/owncloud/android/ui/fragment/OCFileListFragment.java index 02bd845d,091549ae..02105d9e --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@@ -22,18 -22,18 +22,18 @@@ */ package com.owncloud.android.ui.fragment; -import java.io.File; - import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.view.ContextMenu; +import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; +import android.widget.PopupMenu; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; @@@ -48,35 -48,31 +48,35 @@@ import com.owncloud.android.ui.activity import com.owncloud.android.ui.activity.OnEnforceableRefreshListener; import com.owncloud.android.ui.adapter.FileListListAdapter; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.FileActionsDialogFragment; import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.dialog.RenameFileDialogFragment; import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.utils.FileStorageUtils; +import com.owncloud.android.ui.preview.PreviewTextFragment; + +import java.io.File; /** * 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 { +public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener { private static final String TAG = OCFileListFragment.class.getSimpleName(); 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"; - + private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE"; private FileFragment.ContainerActivity mContainerActivity; - + private OCFile mFile = null; private FileListListAdapter mAdapter; private boolean mJustFolders; @@@ -94,21 -90,21 +94,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); @@@ -140,94 -136,41 +140,94 @@@ mJustFolders, getActivity(), mContainerActivity - ); + ); setListAdapter(mAdapter); - registerForContextMenu(); + registerLongClickListener(); } + private void registerLongClickListener() { + getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + public boolean onItemLongClick(AdapterView arg0, View v, + int index, long arg3) { + showFileAction(index); + return true; + } + }); + } + + + 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 + * + * 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 { @@@ -235,8 -178,8 +235,8 @@@ } 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 @@@ -246,20 -189,20 +246,20 @@@ 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()*/); @@@ -267,49 -210,45 +267,45 @@@ 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 (PreviewTextFragment.canBePreviewed(file)){ + ((FileDisplayActivity)mContainerActivity).startTextPreview(file); } else if (file.isDown()) { if (PreviewMediaFragment.canBePreviewed(file)) { // media preview - ((FileDisplayActivity)mContainerActivity).startMediaPreview(file, 0, true); + ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true); } else { mContainerActivity.getFileOperationsHelper().openFile(file); } - - } else { - // automatic download, preview on finish - ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file); + } - } - + } else { Log_OC.d(TAG, "Null object in ListAdapter!!"); } - + } - + /** * {@inheritDoc} */ @Override - public void onCreateContextMenu ( + public void onCreateContextMenu( ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); 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); - + if (mContainerActivity.getStorageManager() != null) { FileMenuFilter mf = new FileMenuFilter( targetFile, @@@ -333,14 -272,16 +329,14 @@@ } } } - - + /** - * {@inhericDoc} + * {@inheritDoc} */ @Override - public boolean onContextItemSelected (MenuItem item) { - AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); - mTargetFile = (OCFile) mAdapter.getItem(info.position); - switch (item.getItemId()) { + public boolean onFileActionChosen(int menuId, int filePosition) { + mTargetFile = (OCFile) mAdapter.getItem(filePosition); + switch (menuId) { case R.id.action_share_file: { mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile); return true; @@@ -363,14 -304,14 +359,14 @@@ dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION); return true; } - case R.id.action_download_file: + 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); + ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile); return true; } case R.id.action_see_details: { @@@ -381,8 -322,8 +377,8 @@@ // Obtain the file if (!mTargetFile.isDown()) { // Download the file Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded"); - ((FileDisplayActivity)mContainerActivity).startDownloadForSending(mTargetFile); - + ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile); + } else { mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile); } @@@ -396,37 -337,8 +392,37 @@@ 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 super.onContextItemSelected(item); + return false; + } + } + + /** + * {@inhericDoc} + */ + @Override + public boolean onContextItemSelected (MenuItem item) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); + boolean matched = onFileActionChosen(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).position); + if(!matched) { + return super.onContextItemSelected(item); + } else { + return matched; } } @@@ -434,13 -346,12 +430,13 @@@ /** * 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 */ @@@ -454,12 -365,12 +450,12 @@@ // TODO Enable when "On Device" is recovered ? 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*/) { @@@ -467,18 -378,18 +463,18 @@@ 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()); } @@@ -505,12 -416,9 +501,12 @@@ if (file.isFolder()) { foldersCount++; } else { - filesCount++; - if (file.isImage()){ - imagesCount++; + if (!file.isHidden()) { + filesCount++; + + if (file.isImage()) { + imagesCount++; + } } } } @@@ -523,7 -431,6 +519,7 @@@ if (version != null && version.supportsRemoteThumbnails() && imagesCount > 0 && imagesCount == filesCount) { switchToGridView(); + registerLongClickListener(); } else { switchToListView(); } @@@ -531,45 -438,27 +527,45 @@@ } private String generateFooterText(int filesCount, int foldersCount) { - String output = ""; - if (filesCount > 0){ - if (filesCount == 1) { - output = output + filesCount + " " + getResources().getString(R.string.file_list_file); - } else { - output = output + filesCount + " " + getResources().getString(R.string.file_list_files); + String output; + if (filesCount <= 0) { + if (foldersCount <= 0) { + output = ""; + + } else if (foldersCount == 1) { + output = getResources().getString(R.string.file_list__footer__folder); + + } else { // foldersCount > 1 + output = getResources().getString(R.string.file_list__footer__folders, foldersCount); } - } - if (foldersCount > 0 && filesCount > 0){ - output = output + ", "; - } - if (foldersCount == 1) { - output = output + foldersCount + " " + getResources().getString(R.string.file_list_folder); - } else if (foldersCount > 1) { - output = output + foldersCount + " " + getResources().getString(R.string.file_list_folders); - } + } else if (filesCount == 1) { + if (foldersCount <= 0) { + output = getResources().getString(R.string.file_list__footer__file); + + } else if (foldersCount == 1) { + output = getResources().getString(R.string.file_list__footer__file_and_folder); + + } else { // foldersCount > 1 + output = getResources().getString(R.string.file_list__footer__file_and_folders, foldersCount); + } + } else { // filesCount > 1 + if (foldersCount <= 0) { + output = getResources().getString(R.string.file_list__footer__files, filesCount); + + } else if (foldersCount == 1) { + output = getResources().getString(R.string.file_list__footer__files_and_folder, filesCount); + + } else { // foldersCount > 1 + output = getResources().getString( + R.string.file_list__footer__files_and_folders, filesCount, foldersCount + ); + + } + } return output; } - public void sortByName(boolean descending) { mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending); } @@@ -580,5 -469,8 +576,5 @@@ public void sortBySize(boolean descending) { mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending); - } - - - + } } diff --combined src/com/owncloud/android/ui/preview/PreviewImageActivity.java index 5cbacfcf,bfb02d3b..4b622cbf --- a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java @@@ -26,7 -26,6 +26,7 @@@ import android.content.Context import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@@ -56,7 -55,6 +56,7 @@@ import com.owncloud.android.lib.common. import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.RemoveFileOperation; +import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; @@@ -105,6 -103,7 +105,6 @@@ public class PreviewImageActivity exten // ActionBar ActionBar actionBar = getSupportActionBar(); - actionBar.setIcon(DisplayUtils.getSeasonalIconId()); updateActionBarTitleAndHomeButton(null); actionBar.hide(); @@@ -133,9 -132,6 +133,9 @@@ } }); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setStatusBarColor(getResources().getColor(R.color.owncloud_blue_dark_transparent)); + } } if (savedInstanceState != null) { @@@ -238,9 -234,6 +238,9 @@@ } else if (operation instanceof RemoveFileOperation) { finish(); + } else if (operation instanceof SynchronizeFileOperation) { + onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result); + } } @@@ -270,14 -263,6 +270,14 @@@ } } + private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, + RemoteOperationResult result) { + if (result.isSuccess()) { + invalidateOptionsMenu(); + } + + } + @Override protected ServiceConnection newTransferenceServiceConnection() { return new PreviewImageServiceConnection(); @@@ -430,12 -415,7 +430,7 @@@ OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position); getSupportActionBar().setTitle(currentFile.getFileName()); mDrawerToggle.setDrawerIndicatorEnabled(false); - if (!currentFile.isDown()) { - if (!mPreviewImagePagerAdapter.pendingErrorAt(position)) { - requestForDownload(currentFile); - } - } - + // Call to reset image zoom to initial state ((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom(); } @@@ -613,7 -593,7 +608,7 @@@ /** * Checks if OS version is Honeycomb one or higher - * + * * @return boolean */ private boolean isHoneycombOrHigher() { diff --combined src/com/owncloud/android/ui/preview/PreviewImageFragment.java index e61e3355,bb33a9c6..160a9777 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@@ -26,7 -26,6 +26,7 @@@ import android.annotation.SuppressLint import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Point; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.FragmentStatePagerAdapter; @@@ -41,8 -40,10 +41,10 @@@ import android.widget.ImageView import android.widget.ProgressBar; import android.widget.TextView; + import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; + import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; @@@ -74,12 -75,14 +76,14 @@@ public class PreviewImageFragment exten private TextView mMessageView; private ProgressBar mProgressWheel; + private Boolean mShowResizedImage = false; + public Bitmap mBitmap = null; - + private static final String TAG = PreviewImageFragment.class.getSimpleName(); private boolean mIgnoreFirstSavedState; - + private LoadBitmapTask mLoadBitmapTask = null; @@@ -97,8 -100,10 +101,10 @@@ * {@link FragmentStatePagerAdapter} * ; TODO better solution */ - public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState){ + public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState, + boolean showResizedImage){ PreviewImageFragment frag = new PreviewImageFragment(); + frag.mShowResizedImage = showResizedImage; Bundle args = new Bundle(); args.putParcelable(ARG_FILE, imageFile); args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState); @@@ -106,7 -111,7 +112,7 @@@ return frag; } - + /** * Creates an empty fragment for image previews. @@@ -120,8 -125,8 +126,8 @@@ public PreviewImageFragment() { mIgnoreFirstSavedState = false; } - - + + /** * {@inheritDoc} */ @@@ -136,14 -141,14 +142,14 @@@ mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST); setHasOptionsMenu(true); } - + /** * {@inheritDoc} */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.preview_image_fragment, container, false); mImageView = (TouchImageViewCustom) view.findViewById(R.id.image); @@@ -179,11 -184,8 +185,8 @@@ if (getFile() == null) { throw new IllegalStateException("Instanced with a NULL OCFile"); } - if (!getFile().isDown()) { - throw new IllegalStateException("There is no local file to preview"); - } } - + /** * {@inheritDoc} @@@ -193,20 -195,53 +196,53 @@@ super.onSaveInstanceState(outState); outState.putParcelable(PreviewImageFragment.EXTRA_FILE, getFile()); } - + @Override public void onStart() { super.onStart(); if (getFile() != null) { - mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel); - //mLoadBitmapTask.execute(new String[]{getFile().getStoragePath()}); - // mLoadBitmapTask.execute(getFile().getStoragePath()); - mLoadBitmapTask.execute(getFile()); + mImageView.setTag(getFile().getFileId()); + + if (mShowResizedImage){ + Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( + String.valueOf("r" + getFile().getRemoteId()) + ); + + if (thumbnail != null && !getFile().needsUpdateThumbnail()){ + mProgressWheel.setVisibility(View.GONE); + mImageView.setImageBitmap(thumbnail); + mImageView.setVisibility(View.VISIBLE); + mBitmap = thumbnail; + } else { + // generate new Thumbnail + if (ThumbnailsCacheManager.cancelPotentialWork(getFile(), mImageView)) { + final ThumbnailsCacheManager.ThumbnailGenerationTask task = + new ThumbnailsCacheManager.ThumbnailGenerationTask( + mImageView, mContainerActivity.getStorageManager(), + mContainerActivity.getStorageManager().getAccount(), + mProgressWheel); + if (thumbnail == null) { + thumbnail = ThumbnailsCacheManager.mDefaultImg; + } + final ThumbnailsCacheManager.AsyncDrawable asyncDrawable = + new ThumbnailsCacheManager.AsyncDrawable( + MainApp.getAppContext().getResources(), + thumbnail, + task + ); + mImageView.setImageDrawable(asyncDrawable); + task.execute(getFile(), false); + } + } + } else { + mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel); - mLoadBitmapTask.execute(getFile().getStoragePath()); ++ mLoadBitmapTask.execute(getFile()); + } } } - - + + @Override public void onStop() { Log_OC.d(TAG, "onStop starts"); @@@ -216,7 -251,7 +252,7 @@@ } super.onStop(); } - + /** * {@inheritDoc} */ @@@ -232,11 -267,11 +268,11 @@@ @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - + if (mContainerActivity.getStorageManager() != null) { // Update the file setFile(mContainerActivity.getStorageManager().getFileById(getFile().getFileId())); - + FileMenuFilter mf = new FileMenuFilter( getFile(), mContainerActivity.getStorageManager().getAccount(), @@@ -245,7 -280,7 +281,7 @@@ ); mf.filter(menu); } - + // additional restriction for this fragment // TODO allow renaming in PreviewImageFragment MenuItem item = menu.findItem(R.id.action_rename_file); @@@ -253,7 -288,7 +289,7 @@@ item.setVisible(false); item.setEnabled(false); } - + // additional restriction for this fragment // TODO allow refresh file in PreviewImageFragment item = menu.findItem(R.id.action_sync_file); @@@ -268,17 -303,11 +304,17 @@@ item.setVisible(false); item.setEnabled(false); } - + + // additional restriction for this fragment + item = menu.findItem(R.id.action_copy); + if (item != null) { + item.setVisible(false); + item.setEnabled(false); + } + } - - + /** * {@inheritDoc} */ @@@ -307,29 -336,27 +343,34 @@@ return true; } case R.id.action_send_file: { - mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); - return true; + if (getFile().isImage() && !getFile().isDown()){ + mContainerActivity.getFileOperationsHelper().sendCachedImage(getFile()); + return true; + } else { + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); + return true; + } } case R.id.action_sync_file: { mContainerActivity.getFileOperationsHelper().syncFile(getFile()); return true; } - + case R.id.action_favorite_file:{ + mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true); + return true; + } + case R.id.action_unfavorite_file:{ + mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false); + return true; + } default: return false; } } - + private void seeDetails() { - mContainerActivity.showDetails(getFile()); + mContainerActivity.showDetails(getFile()); } @@@ -356,7 -383,7 +397,7 @@@ super.onDestroy(); } - + /** * Opens the previewed image with an external application. */ @@@ -364,9 -391,9 +405,9 @@@ mContainerActivity.getFileOperationsHelper().openFile(getFile()); finish(); } + - - private class LoadBitmapTask extends AsyncTask { + private class LoadBitmapTask extends AsyncTask { /** * Weak reference to the target {@link ImageView} where the bitmap will be loaded into. @@@ -384,7 -411,7 +425,7 @@@ */ private final WeakReference mMessageViewRef; - + /** * Weak reference to the target {@link ProgressBar} shown while the load is in progress. * @@@ -393,17 -420,17 +434,17 @@@ */ private final WeakReference mProgressWheelRef; - + /** - * Error message to show when a load fails + * Error message to show when a load fails */ private int mErrorMessageId; - - + + /** * Constructor. - * - * @param imageView Target {@link ImageView} where the bitmap will be loaded into. + * + * @param imageView Target {@link ImageView} where the bitmap will be loaded into. */ public LoadBitmapTask(ImageViewCustom imageView, TextView messageView, ProgressBar progressWheel) { @@@ -411,13 -438,13 +452,13 @@@ mMessageViewRef = new WeakReference(messageView); mProgressWheelRef = new WeakReference(progressWheel); } - - + @Override - protected Bitmap doInBackground(String... params) { + protected LoadImage doInBackground(OCFile... params) { Bitmap result = null; if (params.length != 1) return null; - String storagePath = params[0]; + OCFile ocFile = params[0]; + String storagePath = ocFile.getStoragePath(); try { int maxDownScale = 3; // could be a parameter passed to doInBackground(...) @@@ -430,7 -457,7 +471,7 @@@ result = BitmapUtils.decodeSampledBitmapFromFile(storagePath, minWidth, minHeight); - if (isCancelled()) return result; + if (isCancelled()) return new LoadImage(result, ocFile); if (result == null) { mErrorMessageId = R.string.preview_image_error_unknown_format; @@@ -462,56 -489,48 +503,56 @@@ } catch (NoSuchFieldError e) { mErrorMessageId = R.string.common_error_unknown; - Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " - + storagePath, e); - + Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + + storagePath, e); + } catch (Throwable t) { mErrorMessageId = R.string.common_error_unknown; Log_OC.e(TAG, "Unexpected error loading " + getFile().getStoragePath(), t); - + } - - return result; + + return new LoadImage(result, ocFile); } - + @Override - protected void onCancelled(Bitmap result) { - if (result != null) { - result.recycle(); + protected void onCancelled(LoadImage result) { + if (result != null && result.bitmap != null) { + result.bitmap.recycle(); } } @Override - protected void onPostExecute(Bitmap result) { + protected void onPostExecute(LoadImage result) { hideProgressWheel(); - if (result != null) { + if (result.bitmap != null) { showLoadedImage(result); - } else { + } + else { showErrorMessage(); } - if (result != null && mBitmap != result) { + if (result.bitmap != null && mBitmap != result.bitmap) { // unused bitmap, release it! (just in case) - result.recycle(); + result.bitmap.recycle(); } } - + @SuppressLint("InlinedApi") - private void showLoadedImage(Bitmap result) { + private void showLoadedImage(LoadImage result) { final ImageViewCustom imageView = mImageViewRef.get(); + Bitmap bitmap = result.bitmap; if (imageView != null) { - Log_OC.d(TAG, "Showing image with resolution " + result.getWidth() + "x" + - result.getHeight()); - imageView.setImageBitmap(result); + Log_OC.d(TAG, "Showing image with resolution " + bitmap.getWidth() + "x" + + bitmap.getHeight()); + + if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")){ + Drawable backrepeat = getResources().getDrawable(R.drawable.backrepeat); + imageView.setBackground(backrepeat); + } + + imageView.setImageBitmap(bitmap); imageView.setVisibility(View.VISIBLE); - mBitmap = result; // needs to be kept for recycling when not useful + mBitmap = bitmap; // needs to be kept for recycling when not useful } final TextView messageView = mMessageViewRef.get(); @@@ -519,7 -538,7 +560,7 @@@ messageView.setVisibility(View.GONE); } // else , silently finish, the fragment was destroyed } - + private void showErrorMessage() { final ImageView imageView = mImageViewRef.get(); if (imageView != null) { @@@ -533,14 -552,14 +574,14 @@@ messageView.setVisibility(View.VISIBLE); } // else , silently finish, the fragment was destroyed } - + private void hideProgressWheel() { final ProgressBar progressWheel = mProgressWheelRef.get(); if (progressWheel != null) { progressWheel.setVisibility(View.GONE); } } - + } /** @@@ -554,7 -573,7 +595,7 @@@ return (file != null && file.isImage()); } - + /** * Finishes the preview */ @@@ -562,20 -581,9 +603,20 @@@ Activity container = getActivity(); container.finish(); } - + public TouchImageViewCustom getImageView() { return mImageView; } + private class LoadImage { + private Bitmap bitmap; + private OCFile ocFile; + + public LoadImage(Bitmap bitmap, OCFile ocFile){ + this.bitmap = bitmap; + this.ocFile = ocFile; + } + + } + }