Browse Source

Merge pull request #746 from owncloud/thumbnailForUpload

Thumbnails added to Upload activity
David A. Velasco 10 years ago
parent
commit
9bf4e0f7b9

+ 189 - 133
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -29,10 +29,8 @@ import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.media.ExifInterface;
 import android.media.ThumbnailUtils;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -76,7 +74,7 @@ public class ThumbnailsCacheManager {
     public static Bitmap mDefaultImg = 
             BitmapFactory.decodeResource(
                     MainApp.getAppContext().getResources(), 
-                    DisplayUtils.getResourceId("image/png", "default.png")
+                    DisplayUtils.getFileTypeIconId("image/png", "default.png")
             );
 
     
@@ -139,44 +137,15 @@ public class ThumbnailsCacheManager {
         return null;
     }
 
-    
-    public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
-        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
-        if (bitmapWorkerTask != null) {
-            final OCFile bitmapData = bitmapWorkerTask.mFile;
-            // If bitmapData is not yet set or it differs from the new data
-            if (bitmapData == null || bitmapData != file) {
-                // Cancel previous task
-                bitmapWorkerTask.cancel(true);
-            } else {
-                // The same work is already in progress
-                return false;
-            }
-        }
-        // No task associated with the ImageView, or an existing task was cancelled
-        return true;
-    }
-    
-    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
-        if (imageView != null) {
-            final Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AsyncDrawable) {
-                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
-                return asyncDrawable.getBitmapWorkerTask();
-            }
-         }
-         return null;
-     }
-
-    public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
+    public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
         private static Account mAccount;
-        private OCFile mFile;
+        private Object mFile;
         private FileDataStorageManager mStorageManager;
-        
+
+
         public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
-         // Use a WeakReference to ensure the ImageView can be garbage collected
+            // Use a WeakReference to ensure the ImageView can be garbage collected
             mImageViewReference = new WeakReference<ImageView>(imageView);
             if (storageManager == null)
                 throw new IllegalArgumentException("storageManager must not be NULL");
@@ -184,95 +153,46 @@ public class ThumbnailsCacheManager {
             mAccount = account;
         }
 
-        // Decode image in background.
+        public ThumbnailGenerationTask(ImageView imageView) {
+            // Use a WeakReference to ensure the ImageView can be garbage collected
+            mImageViewReference = new WeakReference<ImageView>(imageView);
+        }
+
         @Override
-        protected Bitmap doInBackground(OCFile... params) {
+        protected Bitmap doInBackground(Object... params) {
             Bitmap thumbnail = null;
-            
+
             try {
                 if (mAccount != null) {
                     AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
-                    
+
                     mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
                     OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
                     mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
                             getClientFor(ocAccount, MainApp.getAppContext());
                 }
-                
+
                 mFile = params[0];
-                final String imageKey = String.valueOf(mFile.getRemoteId());
-    
-                // Check disk cache in background thread
-                thumbnail = getBitmapFromDiskCache(imageKey);
-    
-                // Not found in disk cache
-                if (thumbnail == null || mFile.needsUpdateThumbnail()) { 
-                    // Converts dp to pixel
-                    Resources r = MainApp.getAppContext().getResources();
-                    
-                    int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
-                    
-                    if (mFile.isDown()){
-                        Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
-                                mFile.getStoragePath(), px, px);
-                        
-                        if (bitmap != null) {
-                            thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-                            
-                            // Rotate image, obeying exif tag
-                            thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());
-    
-                            // Add thumbnail to cache
-                            addBitmapToCache(imageKey, thumbnail);
 
-                            mFile.setNeedsUpdateThumbnail(false);
-                            mStorageManager.saveFile(mFile);
-                        }
-    
-                    } else {
-                        // Download thumbnail from server
-                        if (mClient != null && mServerVersion != null) {
-                            OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
-                            if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
-                                try {
-                                    int status = -1;
-
-                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + 
-                                            px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
-                                    Log_OC.d("Thumbnail", "URI: " + uri);
-                                    GetMethod get = new GetMethod(uri);
-                                    status = mClient.executeMethod(get);
-                                    if (status == HttpStatus.SC_OK) {
-                                        byte[] bytes = get.getResponseBody();
-                                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
-                                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-
-                                        // Add thumbnail to cache
-                                        if (thumbnail != null) {
-                                            addBitmapToCache(imageKey, thumbnail);
-                                        }
-                                    }
-                                } catch (Exception e) {
-                                    e.printStackTrace();
-                                }
-                            } else {
-                                Log_OC.d(TAG, "Server too old");
-                            }
-                        }
-                    }
+                if (mFile instanceof OCFile) {
+                    thumbnail = doOCFileInBackground();
+                }  else if (mFile instanceof File) {
+                    thumbnail = doFileInBackground();
+                } else {
+                    // do nothing
                 }
-                
-            } catch (Throwable t) {
-                // the app should never break due to a problem with thumbnails
-                Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
-                if (t instanceof OutOfMemoryError) {
-                    System.gc();
+
+                }catch(Throwable t){
+                    // the app should never break due to a problem with thumbnails
+                    Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
+                    if (t instanceof OutOfMemoryError) {
+                        System.gc();
+                    }
                 }
-            }
-            
+
             return thumbnail;
         }
-        
+
         protected void onPostExecute(Bitmap bitmap){
             if (isCancelled()) {
                 bitmap = null;
@@ -280,47 +200,183 @@ public class ThumbnailsCacheManager {
 
             if (mImageViewReference != null && bitmap != null) {
                 final ImageView imageView = mImageViewReference.get();
-                final ThumbnailGenerationTask bitmapWorkerTask =
-                        getBitmapWorkerTask(imageView);
+                final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
                 if (this == bitmapWorkerTask && imageView != null) {
-                    if (imageView.getTag().equals(mFile.getFileId())) {
+                    String tagId = "";
+                    if (mFile instanceof OCFile){
+                        tagId = String.valueOf(((OCFile)mFile).getFileId());
+                    } else if (mFile instanceof File){
+                        tagId = String.valueOf(((File)mFile).hashCode());
+                    }
+                    if (String.valueOf(imageView.getTag()).equals(tagId)) {
                         imageView.setImageBitmap(bitmap);
                     }
                 }
             }
         }
+
+        /**
+         * Add thumbnail to cache
+         * @param imageKey: thumb key
+         * @param bitmap:   image for extracting thumbnail
+         * @param path:     image path
+         * @param px:       thumbnail dp
+         * @return Bitmap
+         */
+        private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
+
+            Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+            // Rotate image, obeying exif tag
+            thumbnail = BitmapUtils.rotateImage(thumbnail,path);
+
+            // Add thumbnail to cache
+            addBitmapToCache(imageKey, thumbnail);
+
+            return thumbnail;
+        }
+
+        /**
+         * Converts size of file icon from dp to pixel
+         * @return int
+         */
+        private int getThumbnailDimension(){
+            // Converts dp to pixel
+            Resources r = MainApp.getAppContext().getResources();
+            return (int) Math.round(r.getDimension(R.dimen.file_icon_size));
+        }
+
+        private Bitmap doOCFileInBackground() {
+            Bitmap thumbnail = null;
+            OCFile file = (OCFile)mFile;
+
+            final String imageKey = String.valueOf(file.getRemoteId());
+
+            // Check disk cache in background thread
+            thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null || file.needsUpdateThumbnail()) {
+
+                int px = getThumbnailDimension();
+
+                if (file.isDown()) {
+                    Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                            file.getStoragePath(), px, px);
+
+                    if (bitmap != null) {
+                        thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
+
+                        file.setNeedsUpdateThumbnail(false);
+                        mStorageManager.saveFile(file);
+                    }
+
+                } else {
+                    // Download thumbnail from server
+                    if (mClient != null && mServerVersion != null) {
+                        OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
+                        if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
+                            try {
+                                int status = -1;
+
+                                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);
+                                status = mClient.executeMethod(get);
+                                if (status == HttpStatus.SC_OK) {
+                                    byte[] bytes = get.getResponseBody();
+                                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+                                    thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+                                    // Add thumbnail to cache
+                                    if (thumbnail != null) {
+                                        addBitmapToCache(imageKey, thumbnail);
+                                    }
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        } else {
+                            Log_OC.d(TAG, "Server too old");
+                        }
+                    }
+                }
+            }
+
+            return thumbnail;
+
+        }
+
+        private Bitmap doFileInBackground() {
+            Bitmap thumbnail = null;
+            File file = (File)mFile;
+
+            final String imageKey = String.valueOf(file.hashCode());
+
+            // Check disk cache in background thread
+            thumbnail = getBitmapFromDiskCache(imageKey);
+
+            // Not found in disk cache
+            if (thumbnail == null) {
+
+                int px = getThumbnailDimension();
+
+                Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
+                        file.getAbsolutePath(), px, px);
+
+                if (bitmap != null) {
+                    thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
+                }
+            }
+            return thumbnail;
+        }
+
     }
-  
-    
+
+    public static boolean cancelPotentialWork(Object file, ImageView imageView) {
+        final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+        if (bitmapWorkerTask != null) {
+            final Object bitmapData = bitmapWorkerTask.mFile;
+            // If bitmapData is not yet set or it differs from the new data
+            if (bitmapData == null || bitmapData != file) {
+                // Cancel previous task
+                bitmapWorkerTask.cancel(true);
+            } else {
+                // The same work is already in progress
+                return false;
+            }
+        }
+        // No task associated with the ImageView, or an existing task was cancelled
+        return true;
+    }
+
+    public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
+        if (imageView != null) {
+            final Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AsyncDrawable) {
+                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+                return asyncDrawable.getBitmapWorkerTask();
+            }
+        }
+        return null;
+    }
+
     public static class AsyncDrawable extends BitmapDrawable {
         private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
 
         public AsyncDrawable(
                 Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
-            ) {
-            
+        ) {
+
             super(res, bitmap);
             bitmapWorkerTaskReference =
-                new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
+                    new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
         }
 
         public ThumbnailGenerationTask getBitmapWorkerTask() {
             return bitmapWorkerTaskReference.get();
         }
     }
-
-    
-    /**
-     * Remove from cache the remoteId passed
-     * @param fileRemoteId: remote id of mFile passed
-     */
-    public static void removeFileFromCache(String fileRemoteId){
-        synchronized (mThumbnailsDiskCacheLock) {
-            if (mThumbnailCache != null) {
-                mThumbnailCache.removeKey(fileRemoteId);
-            }
-            mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
-        }
-    }
-    
 }

+ 43 - 26
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -17,7 +17,7 @@
  */
 package com.owncloud.android.ui.adapter;
 
-
+
 import java.io.File;
 import java.util.Collections;
 import java.util.Comparator;
@@ -44,13 +44,12 @@ import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
-
+
 
 /**
  * This Adapter populates a ListView with all files and folders in an ownCloud
@@ -60,7 +59,7 @@ import com.owncloud.android.utils.FileStorageUtils;
  * @author Tobias Kaminsky
  * @author David A. Velasco
  */
-public class FileListListAdapter extends BaseAdapter implements ListAdapter {
+public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private final static String PERMISSION_SHARED_WITH_ME = "S";
     
     private Context mContext;
@@ -68,8 +67,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private Vector<OCFile> mFiles = null;
     private boolean mJustFolders;
 
-    private FileDataStorageManager mStorageManager;
-    private Account mAccount;
+    private FileDataStorageManager mStorageManager;
+    private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;
     
     private SharedPreferences mAppPreferences;
@@ -83,22 +82,22 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         mJustFolders = justFolders;
         mContext = context;
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
-
-        mTransferServiceGetter = transferServiceGetter;
+
+        mTransferServiceGetter = transferServiceGetter;
         
         mAppPreferences = PreferenceManager
                 .getDefaultSharedPreferences(mContext);
         
         // Read sorting order, default to sort by name ascending
-        FileStorageUtils.mSortOrder = mAppPreferences
-                .getInt("sortOrder", 0);
-        FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+        FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);
+        FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+
         
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
 
     }
-    
+    
     @Override
     public boolean areAllItemsEnabled() {
         return true;
@@ -210,16 +209,18 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     if (thumbnail != null && !file.needsUpdateThumbnail()){
                         fileIcon.setImageBitmap(thumbnail);
                     } else {
+
                         // generate new Thumbnail
                         if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
-                            final ThumbnailsCacheManager.ThumbnailGenerationTask task = 
+                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
                                     new ThumbnailsCacheManager.ThumbnailGenerationTask(
                                             fileIcon, mStorageManager, mAccount
                                     );
                             if (thumbnail == null) {
                                 thumbnail = ThumbnailsCacheManager.mDefaultImg;
                             }
-                            final AsyncDrawable asyncDrawable = new AsyncDrawable(
+                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
+                                    new ThumbnailsCacheManager.AsyncDrawable(
                                     mContext.getResources(), 
                                     thumbnail, 
                                     task
@@ -229,11 +230,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                         }
                     }
                 } else {
-                    fileIcon.setImageResource(
-                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
-                    );
+                    fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()));
                 }
-
+
                 if (checkIfFileIsSharedWithMe(file)) {
                     sharedWithMeIconV.setVisibility(View.VISIBLE);
                 }
@@ -246,7 +245,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 //                } else {
                     fileSizeV.setVisibility(View.INVISIBLE);
 //                }
-
+
                 lastModV.setVisibility(View.VISIBLE);
                 lastModV.setText(showRelativeTimestamp(file));
                 checkBoxV.setVisibility(View.GONE);
@@ -257,7 +256,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     sharedWithMeIconV.setVisibility(View.VISIBLE);
                 } else {
                     fileIcon.setImageResource(
-                            DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
+                            DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())
                     );
                 }
 
@@ -277,7 +276,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 
         return view;
     }
-
+
     /**
      * Local Folder size in human readable format
      * 
@@ -297,8 +296,27 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         return "0 B";
     }
 
-    
-
+    /**
+     * 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;
@@ -382,7 +400,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         FileStorageUtils.mSortOrder = order;
         FileStorageUtils.mSortAscending = ascending;
         
-
+
         mFiles = FileStorageUtils.sortFolder(mFiles);
         notifyDataSetChanged();
 
@@ -391,6 +409,5 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private CharSequence showRelativeTimestamp(OCFile file){
         return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
                 DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
-    }
-
+    }
 }

+ 37 - 2
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.Comparator;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,6 +33,8 @@ import android.widget.ListView;
 import android.widget.TextView;
 
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 
 /**
@@ -46,7 +49,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
     private Context mContext;
     private File mDirectory;
     private File[] mFiles = null;
-
+    
     public LocalFileListAdapter(File directory, Context context) {
         mContext = context;
         swapDirectory(directory);
@@ -105,6 +108,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             } else {
                 fileIcon.setImageResource(R.drawable.ic_menu_archive);
             }
+            fileIcon.setTag(file.hashCode());
 
             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
             TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
@@ -125,6 +129,37 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                     }
                     checkBoxV.setVisibility(View.VISIBLE);
                 }
+                
+             // get Thumbnail if file is image
+                if (BitmapUtils.isImage(file)){
+                // Thumbnail in Cache?
+                    Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
+                            String.valueOf(file.hashCode())
+                    );
+                    if (thumbnail != null){
+                        fileIcon.setImageBitmap(thumbnail);
+                    } else {
+
+                        // generate new Thumbnail
+                        if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
+                            final ThumbnailsCacheManager.ThumbnailGenerationTask task =
+                                    new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon);
+                            if (thumbnail == null) {
+                                thumbnail = ThumbnailsCacheManager.mDefaultImg;
+                            }
+                            final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
+                        		new ThumbnailsCacheManager.AsyncDrawable(
+                                    mContext.getResources(), 
+                                    thumbnail, 
+                                    task
+                		        );
+                            fileIcon.setImageDrawable(asyncDrawable);
+                            task.execute(file);
+                        }
+                    }
+                } else {
+                    fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(null, file.getName()));
+                }  
 
             } else {
                 fileSizeV.setVisibility(View.GONE);
@@ -132,7 +167,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                 checkBoxV.setVisibility(View.GONE);
             }
             
-            view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE);   // not GONE; the alignment changes; ugly way to keep it
+            view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE);   // not GONE; the alignment would change
             view.findViewById(R.id.imageView3).setVisibility(View.GONE);
             
             view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);

+ 1 - 1
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -396,7 +396,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
         }
         ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);
         if (iv != null) {
-            iv.setImageResource(DisplayUtils.getResourceId(mimetype, filename));
+            iv.setImageResource(DisplayUtils.getFileTypeIconId(mimetype, filename));
         }
     }
 

+ 17 - 1
src/com/owncloud/android/utils/BitmapUtils.java

@@ -23,6 +23,10 @@ import android.graphics.BitmapFactory;
 import android.graphics.Matrix;
 import android.graphics.BitmapFactory.Options;
 import android.media.ExifInterface;
+import android.net.Uri;
+import android.webkit.MimeTypeMap;
+
+import java.io.File;
 
 /**
  * Utility class with methods for decoding Bitmaps.
@@ -169,6 +173,18 @@ public class BitmapUtils {
         }
         return resultBitmap;
     }
-    
+
+    /**
+     * Checks if file passed is an image
+     * @param file
+     * @return true/false
+     */
+    public static boolean isImage(File file) {
+        Uri selectedUri = Uri.fromFile(file);
+        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString().toLowerCase());
+        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+
+        return (mimeType != null && mimeType.startsWith("image/"));
+    }
     
 }

+ 61 - 54
src/com/owncloud/android/utils/DisplayUtils.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.utils;
 
 import java.net.IDN;
+import java.text.DateFormat;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -30,6 +31,7 @@ import android.annotation.TargetApi;
 import android.content.Context;
 import android.os.Build;
 import android.text.format.DateUtils;
+import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -73,21 +75,28 @@ public class DisplayUtils {
     private static final String TYPE_VIDEO = "video";
     
     private static final String SUBTYPE_PDF = "pdf";
-    private static final String[] SUBTYPES_DOCUMENT = { "msword",
-                                                        "vnd.openxmlformats-officedocument.wordprocessingml.document",
-                                                        "vnd.oasis.opendocument.text",
-                                                        "rtf"
-                                                        };
+    private static final String SUBTYPE_XML = "xml";
+    private static final String[] SUBTYPES_DOCUMENT = { 
+        "msword",
+        "vnd.openxmlformats-officedocument.wordprocessingml.document",
+        "vnd.oasis.opendocument.text",
+        "rtf",
+        "javascript"
+    };
     private static Set<String> SUBTYPES_DOCUMENT_SET = new HashSet<String>(Arrays.asList(SUBTYPES_DOCUMENT));
-    private static final String[] SUBTYPES_SPREADSHEET = { "msexcel",
-                                                           "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
-                                                           "vnd.oasis.opendocument.spreadsheet"
-                                                           };
+    private static final String[] SUBTYPES_SPREADSHEET = {
+        "msexcel",
+        "vnd.ms-excel",
+        "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        "vnd.oasis.opendocument.spreadsheet"
+    };
     private static Set<String> SUBTYPES_SPREADSHEET_SET = new HashSet<String>(Arrays.asList(SUBTYPES_SPREADSHEET));
-    private static final String[] SUBTYPES_PRESENTATION = { "mspowerpoint",
-                                                            "vnd.openxmlformats-officedocument.presentationml.presentation",
-                                                            "vnd.oasis.opendocument.presentation"
-                                                            };
+    private static final String[] SUBTYPES_PRESENTATION = { 
+        "mspowerpoint",
+        "vnd.ms-powerpoint",
+        "vnd.openxmlformats-officedocument.presentationml.presentation",
+        "vnd.oasis.opendocument.presentation"
+    };
     private static Set<String> SUBTYPES_PRESENTATION_SET = new HashSet<String>(Arrays.asList(SUBTYPES_PRESENTATION));
     private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"};
     private static final Set<String> SUBTYPES_COMPRESSED_SET = new HashSet<String>(Arrays.asList(SUBTYPES_COMPRESSED));
@@ -95,6 +104,8 @@ public class DisplayUtils {
     private static final String EXTENSION_RAR = "rar";
     private static final String EXTENSION_RTF = "rtf";
     private static final String EXTENSION_3GP = "3gp";
+    private static final String EXTENSION_PY = "py";
+    private static final String EXTENSION_JS = "js";
     
     /**
      * Converts the file size in bytes to human readable output.
@@ -113,30 +124,6 @@ public class DisplayUtils {
         return result + " " + sizeSuffixes[attachedsuff];
     }
 
-    /**
-     * Removes special HTML entities from a string
-     * 
-     * @param s Input string
-     * @return A cleaned version of the string
-     */
-    public static String HtmlDecode(String s) {
-        /*
-         * TODO: Perhaps we should use something more proven like:
-         * http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#unescapeHtml%28java.lang.String%29
-         */
-
-        String ret = "";
-        for (int i = 0; i < s.length(); ++i) {
-            if (s.charAt(i) == '%') {
-                ret += (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);
-                i += 2;
-            } else {
-                ret += s.charAt(i);
-            }
-        }
-        return ret;
-    }
-
     /**
      * Converts MIME types like "image/jpg" to more end user friendly output
      * like "JPG image".
@@ -155,18 +142,25 @@ public class DisplayUtils {
     
     
     /**
-     * Returns the resource identifier of an image resource to use as icon associated to a 
-     * known MIME type.
+     * Returns the resource identifier of an image to use as icon associated to a known MIME type.
      * 
-     * @param mimetype      MIME type string.
-     * @param filename      name, with extension
-     * @return              Resource identifier of an image resource.
+     * @param mimetype      MIME type string; if NULL, the method tries to guess it from the extension in filename
+     * @param filename      Name, with extension.
+     * @return              Identifier of an image resource.
      */
-    public static int getResourceId(String mimetype, String filename) {
+    public static int getFileTypeIconId(String mimetype, String filename) {
 
-        if (mimetype == null || "DIR".equals(mimetype)) {
-            return R.drawable.ic_menu_archive;
+        if (mimetype == null) {
+            String fileExtension = getExtension(filename);
+            mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+            if (mimetype == null) {
+                mimetype = TYPE_APPLICATION + "/" + SUBTYPE_OCTET_STREAM;
+            }
+        } 
             
+        if ("DIR".equals(mimetype)) {
+            return R.drawable.ic_menu_archive;
+
         } else {
             String [] parts = mimetype.split("/");
             String type = parts[0];
@@ -189,6 +183,9 @@ public class DisplayUtils {
                 if (SUBTYPE_PDF.equals(subtype)) {
                     return R.drawable.file_pdf;
                     
+                } else if (SUBTYPE_XML.equals(subtype)) {
+                    return R.drawable.file_doc;
+
                 } else if (SUBTYPES_DOCUMENT_SET.contains(subtype)) {
                     return R.drawable.file_doc;
 
@@ -200,7 +197,7 @@ public class DisplayUtils {
 
                 } else if (SUBTYPES_COMPRESSED_SET.contains(subtype)) {
                     return R.drawable.file_zip;
-                    
+
                 } else if (SUBTYPE_OCTET_STREAM.equals(subtype) ) {
                     if (getExtension(filename).equalsIgnoreCase(EXTENSION_RAR)) {
                         return R.drawable.file_zip;
@@ -210,7 +207,10 @@ public class DisplayUtils {
                         
                     } else if (getExtension(filename).equalsIgnoreCase(EXTENSION_3GP)) {
                         return R.drawable.file_movie;
-                        
+                     
+                    } else if ( getExtension(filename).equalsIgnoreCase(EXTENSION_PY) ||
+                                getExtension(filename).equalsIgnoreCase(EXTENSION_JS)) {
+                        return R.drawable.file_doc;
                     } 
                 } 
             }
@@ -222,8 +222,7 @@ public class DisplayUtils {
 
     
     private static String getExtension(String filename) {
-        String extension = filename.substring(filename.lastIndexOf(".") + 1);
-        
+        String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
         return extension;
     }
     
@@ -234,7 +233,8 @@ public class DisplayUtils {
      */
     public static String unixTimeToHumanReadable(long milliseconds) {
         Date date = new Date(milliseconds);
-        return date.toLocaleString();
+        DateFormat df = DateFormat.getDateTimeInstance();
+        return df.format(date);
     }
     
     
@@ -295,7 +295,11 @@ public class DisplayUtils {
         return fileExtension;
     }
 
-    public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution, long transitionResolution, int flags){
+    @SuppressWarnings("deprecation")
+    public static CharSequence getRelativeDateTimeString (
+            Context c, long time, long minResolution, long transitionResolution, int flags
+            ){
+        
         CharSequence dateString = "";
         
         // in Future
@@ -307,18 +311,21 @@ public class DisplayUtils {
             return c.getString(R.string.file_list_seconds_ago);
         } else {
             // Workaround 2.x bug (see https://github.com/owncloud/android/issues/716)
-            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB && (System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000){
+            if (    Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB && 
+                    (System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000   ) {
                 Date date = new Date(time);
                 date.setHours(0);
                 date.setMinutes(0);
                 date.setSeconds(0);
-                dateString = DateUtils.getRelativeDateTimeString(c, date.getTime(), minResolution, transitionResolution, flags);
+                dateString = DateUtils.getRelativeDateTimeString(
+                        c, date.getTime(), minResolution, transitionResolution, flags
+                );
             } else {
                 dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);
             }
         }
         
-        return dateString.toString().split(",")[0];
+        return dateString.toString().split(",")[0];
     }
 
     /**