Merge branch 'develop' into accessibility
authormasensio <masensio@solidgear.es>
Tue, 10 Mar 2015 13:58:21 +0000 (14:58 +0100)
committermasensio <masensio@solidgear.es>
Tue, 10 Mar 2015 13:58:21 +0000 (14:58 +0100)
Conflicts:
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

1  2 
res/layout-land/account_setup.xml
res/layout/account_setup.xml
res/menu/main_menu.xml
res/values/strings.xml
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/Preferences.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application\r
  \r
    Copyright (C) 2012  Bartek Przybylski\r
-   Copyright (C) 2012-2013 ownCloud Inc.\r
+   Copyright (C) 2015 ownCloud Inc.\r
  \r
    This program is free software: you can redistribute it and/or modify\r
    it under the terms of the GNU General Public License version 2,\r
          android:orientation="horizontal" >\r
          \r
                <ImageView\r
-                       android:id="@+id/imageView1"\r
+                       android:id="@+id/thumbnail"\r
                        android:layout_width="0dp"\r
                        android:layout_height="wrap_content"\r
                        android:layout_weight="1"\r
                        android:layout_gravity="center"\r
                        android:background="@color/login_logo_background_color"\r
 -                      android:src="@drawable/logo" \r
 +                      android:src="@drawable/logo"\r
 +            android:contentDescription="@string/app_name"\r
                        />\r
                \r
                <ScrollView\r
@@@ -66,8 -65,7 +66,8 @@@
                                        android:layout_marginBottom="10dp"\r
                        android:onClick="onRefreshClick"\r
                                    android:text="@string/auth_check_server"\r
 -                                  android:visibility="gone" />\r
 +                                  android:visibility="gone"\r
 +                    android:contentDescription="@string/auth_check_server"/>\r
                                <TextView\r
                                    android:id="@+id/instructions_message"\r
                                    android:layout_width="wrap_content"\r
@@@ -75,8 -73,7 +75,8 @@@
                                    android:layout_gravity="fill_horizontal"\r
                                    android:text="@string/auth_expired_basic_auth_toast" \r
                                    android:visibility="gone"\r
 -                                  android:layout_marginBottom="10dp"/>\r
 +                                  android:layout_marginBottom="10dp"\r
 +                    android:contentDescription="@string/auth_expired_basic_auth_toast"/>\r
                            <FrameLayout \r
                                android:id="@+id/hostUrlFrame"\r
                                        android:layout_width="match_parent"\r
@@@ -92,7 -89,6 +92,7 @@@
                                                android:inputType="textUri"\r
                                                android:drawablePadding="5dp"\r
                                                android:paddingRight="55dp"\r
 +                                              android:contentDescription="@string/auth_host_address"\r
                                                >\r
                                                <requestFocus />\r
                                        </EditText>\r
                                android:onClick="onRefreshClick"\r
                                            android:visibility="gone"\r
                                                android:background="@android:color/transparent"\r
 +                        android:contentDescription="@string/auth_refresh_button"\r
                                            />\r
                                </FrameLayout>\r
                \r
                                        android:drawableLeft="@android:drawable/stat_notify_sync"\r
                                        android:drawablePadding="5dp"\r
                                        android:gravity="center_vertical"\r
 -                                      android:text="@string/auth_testing_connection" />\r
 +                                      android:text="@string/auth_testing_connection"\r
 +                    android:contentDescription="@string/auth_testing_connection"/>\r
                             \r
                                <CheckBox\r
                                        android:id="@+id/oauth_onOff_check"\r
                                        android:onClick="onCheckClick"\r
                                        android:text="@string/oauth_check_onoff"\r
                                        android:textAppearance="?android:attr/textAppearanceSmall"\r
 +                    android:contentDescription="@string/oauth_check_onoff"\r
                                        />\r
                \r
                                <EditText\r
                                        android:text="@string/oauth2_url_endpoint_auth"\r
                                        android:singleLine="true"\r
                                        android:inputType="textUri"\r
 -                                      android:visibility="gone" >\r
 +                                      android:visibility="gone">\r
                                </EditText>            \r
                                \r
                                <EditText\r
                                        android:text="@string/oauth2_url_endpoint_access"\r
                                        android:singleLine="true"\r
                                        android:inputType="textUri"\r
 -                                      android:visibility="gone" >\r
 +                                      android:visibility="gone">\r
                                        <requestFocus />\r
                                </EditText>            \r
                \r
                                        android:layout_height="wrap_content"\r
                                        android:ems="10"\r
                                        android:hint="@string/auth_username"\r
 -                                      android:inputType="textNoSuggestions" />\r
 +                                      android:inputType="textNoSuggestions"\r
 +                                      android:contentDescription="@string/auth_username"/>\r
                \r
                                <EditText\r
                                    android:id="@+id/account_password"\r
                                        android:hint="@string/auth_password"\r
                                        android:inputType="textPassword"\r
                                        android:drawablePadding="5dp"\r
 +                                      android:contentDescription="@string/auth_password"\r
                                        />\r
                        \r
                                <TextView\r
                                        android:text="@string/auth_unauthorized"\r
                                        android:drawableLeft="@android:drawable/stat_notify_sync"\r
                                        android:drawablePadding="5dip"\r
 +                    android:contentDescription="@string/auth_unauthorized"\r
                                        />\r
  \r
                        </LinearLayout>\r
                    android:layout_gravity="center_horizontal"\r
                    android:enabled="false"\r
                    android:onClick="onOkClick"\r
 -                  android:text="@string/setup_btn_connect" />\r
 +                  android:text="@string/setup_btn_connect"\r
 +            android:contentDescription="@string/setup_btn_connect"/>\r
                \r
                <Button\r
                    android:id="@+id/welcome_link"\r
                    android:paddingBottom="5dp"\r
                    android:paddingTop="5dp"\r
                    android:text="@string/auth_register"\r
 -                  android:textColor="#0000FF"/>\r
 +                  android:textColor="#0000FF"\r
 +            android:contentDescription="@string/auth_register"/>\r
        </LinearLayout>\r
                \r
  </RelativeLayout>\r
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application\r
  \r
    Copyright (C) 2012  Bartek Przybylski\r
-   Copyright (C) 2012-2013 ownCloud Inc.\r
+   Copyright (C) 2015 ownCloud Inc.\r
  \r
    This program is free software: you can redistribute it and/or modify\r
    it under the terms of the GNU General Public License version 2,\r
          android:padding="8dp" >\r
  \r
          <ImageView\r
-             android:id="@+id/imageView1"\r
+             android:id="@+id/thumbnail"\r
              android:layout_width="match_parent"\r
              android:layout_height="wrap_content"\r
              android:layout_marginBottom="10dp"\r
              android:layout_marginTop="10dp"\r
              android:background="@color/login_logo_background_color"\r
 -            android:src="@drawable/logo" />\r
 +            android:src="@drawable/logo"\r
 +            android:contentDescription="@string/app_name"/>\r
  \r
          <Button\r
              android:id="@+id/centeredRefreshButton"\r
@@@ -52,8 -51,7 +52,8 @@@
              android:layout_marginBottom="10dp"\r
              android:onClick="onRefreshClick"\r
              android:text="@string/auth_check_server"\r
 -            android:visibility="gone" />\r
 +            android:visibility="gone"\r
 +            android:contentDescription="@string/auth_check_server"/>\r
          \r
          <TextView\r
              android:id="@+id/instructions_message"\r
@@@ -62,8 -60,7 +62,8 @@@
              android:layout_gravity="fill_horizontal"\r
              android:text="@string/auth_expired_basic_auth_toast"\r
              android:visibility="gone"\r
 -            android:layout_marginBottom="10dp" />\r
 +            android:layout_marginBottom="10dp"\r
 +            android:contentDescription="@string/auth_expired_basic_auth_toast"/>\r
  \r
            <FrameLayout \r
                android:id="@+id/hostUrlFrame"\r
@@@ -80,7 -77,6 +80,7 @@@
                                android:inputType="textUri"\r
                                android:drawablePadding="5dp"\r
                                android:paddingRight="55dp"\r
 +                              android:contentDescription="@string/auth_host_address"\r
                                >\r
                                <requestFocus />\r
                        </EditText>\r
@@@ -96,7 -92,6 +96,7 @@@
                android:onClick="onRefreshClick"\r
                                android:visibility="gone"\r
                                android:background="@android:color/transparent"\r
 +                android:contentDescription="@string/auth_refresh_button"\r
                            />\r
                </FrameLayout>\r
  \r
              android:drawableLeft="@android:drawable/stat_notify_sync"\r
              android:drawablePadding="5dp"\r
              android:gravity="center_vertical"\r
 -            android:text="@string/auth_testing_connection" />\r
 +            android:text="@string/auth_testing_connection"\r
 +            android:contentDescription="@string/auth_testing_connection"/>\r
  \r
          <CheckBox\r
              android:id="@+id/oauth_onOff_check"\r
              android:onClick="onCheckClick"\r
              android:text="@string/oauth_check_onoff"\r
              android:textAppearance="?android:attr/textAppearanceSmall"\r
 +            android:contentDescription="@string/oauth_check_onoff"\r
              />\r
  \r
          <EditText\r
              android:text="@string/oauth2_url_endpoint_auth"\r
              android:singleLine="true"\r
              android:inputType="textUri"\r
 -            android:visibility="gone" >\r
 +            android:visibility="gone">\r
          </EditText>\r
  \r
          <EditText\r
              android:text="@string/oauth2_url_endpoint_access"\r
              android:singleLine="true"\r
              android:inputType="textUri"\r
 -            android:visibility="gone" />\r
 +            android:visibility="gone"/>\r
  \r
          <EditText\r
              android:id="@+id/account_username"\r
              android:layout_height="wrap_content"\r
              android:ems="10"\r
              android:hint="@string/auth_username"\r
 -            android:inputType="textNoSuggestions" \r
 +            android:inputType="textNoSuggestions"\r
 +            android:contentDescription="@string/auth_username"\r
                        />\r
  \r
                <EditText\r
                    android:drawablePadding="5dp"\r
                    android:ems="10"\r
                    android:hint="@string/auth_password"\r
 -                  android:inputType="textPassword" \r
 +                  android:inputType="textPassword"\r
 +                  android:contentDescription="@string/auth_password"\r
              />\r
          \r
          <TextView\r
              android:drawableLeft="@android:drawable/stat_notify_sync"\r
              android:drawablePadding="5dp"\r
              android:gravity="center_vertical"\r
 -            android:text="@string/auth_unauthorized" />\r
 +            android:text="@string/auth_unauthorized"\r
 +            android:contentDescription="@string/auth_unauthorized"/>\r
  \r
          <Button\r
              android:id="@+id/buttonOK"\r
              android:layout_gravity="center_horizontal"\r
              android:enabled="false"\r
              android:onClick="onOkClick"\r
 -            android:text="@string/setup_btn_connect" />\r
 +            android:text="@string/setup_btn_connect"\r
 +            android:contentDescription="@string/setup_btn_connect"/>\r
  \r
          <Button\r
              android:id="@+id/welcome_link"\r
              android:paddingBottom="5dp"\r
              android:paddingTop="5dp"\r
              android:text="@string/auth_register"\r
 -            android:textColor="#0000FF"/>\r
 +            android:textColor="#0000FF"\r
 +            android:contentDescription="@string/auth_register"/>\r
  \r
      </LinearLayout>\r
  \r
diff --combined res/menu/main_menu.xml
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
          android:icon="@drawable/ic_action_upload"
          android:orderInCategory="2"
          android:showAsAction="always"
 -        android:title="@string/actionbar_upload"/>
 +        android:title="@string/actionbar_upload"
 +        android:contentDescription="@string/actionbar_upload"/>
      <item
          android:id="@+id/action_create_dir"
          android:icon="@drawable/ic_action_create_dir"
          android:orderInCategory="2"
          android:showAsAction="always"
 -        android:title="@string/actionbar_mkdir"/>
 +        android:title="@string/actionbar_mkdir"
 +        android:contentDescription="@string/actionbar_mkdir"/>
      <item
          android:id="@+id/action_sync_account"
          android:icon="@drawable/ic_action_refresh"
          android:orderInCategory="2"
          android:showAsAction="never"
 -        android:title="@string/actionbar_sync"/>
 +        android:title="@string/actionbar_sync"
 +        android:contentDescription="@string/actionbar_sync"/>
      <item
          android:id="@+id/action_settings"
          android:icon="@drawable/ic_action_settings"
          android:orderInCategory="2"
          android:showAsAction="never"
 -        android:title="@string/actionbar_settings"/>
 +        android:title="@string/actionbar_settings"
 +        android:contentDescription="@string/actionbar_settings"/>
      <item
          android:id="@+id/action_logger"
          android:icon="@drawable/ic_action_settings"
          android:orderInCategory="2"
          android:showAsAction="never"
 -        android:title="@string/actionbar_logger"/>
 +        android:title="@string/actionbar_logger"
 +        android:contentDescription="@string/actionbar_logger"/>
        <item
          android:id="@+id/action_sort"
          android:icon="@android:drawable/ic_menu_sort_alphabetically"
          android:orderInCategory="2"
          android:showAsAction="never"
 -        android:title="@string/actionbar_sort"/>
 +        android:title="@string/actionbar_sort"
 +        android:contentDescription="@string/actionbar_sort"/>
  
      <!-- <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item> -->
  
diff --combined res/values/strings.xml
        <string name="auth_no_net_conn_title">No network connection</string>
        <string name="auth_nossl_plain_ok_title">Secure connection unavailable.</string>
        <string name="auth_connection_established">Connection established</string>
 -      <string name="auth_testing_connection">Testing connection&#8230;</string>
 +      <string name="auth_testing_connection">Testing connection</string>
        <string name="auth_not_configured_title">Malformed server configuration</string>
        <string name="auth_account_not_new">An account for the same user and server already exists in the device</string>
        <string name="auth_account_not_the_same">The entered user does not match the user of this account</string>
        <string name="auth_fail_get_user_name">Your server is not returning a correct user id, please contact an administrator
        </string>
        <string name="auth_can_not_auth_against_server">Cannot authenticate against this server</string>
+     <string name="auth_account_does_not_exist">Account does not exist in the device yet</string>
      
      <string name="fd_keep_in_sync">Keep file up to date</string>
      <string name="common_rename">Rename</string>
        <string name="prefs_category_security">Security</string>
  
        <string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
+     <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
+       <string name="subject_token">%1$s shared \"%2$s\" with you</string>
  
 +    <string name="auth_refresh_button">Refresh connection</string>
 +    <string name="auth_host_address">Server address</string>
 +
  </resources>
@@@ -1,6 -1,10 +1,10 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author David A. Velasco
   *   Copyright (C) 2011  Bartek Przybylski
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -25,6 -29,8 +29,8 @@@ import android.accounts.Account
  import android.accounts.AccountManager;
  import android.accounts.AuthenticatorException;
  import android.accounts.OperationCanceledException;
+ import android.annotation.SuppressLint;
+ import android.annotation.TargetApi;
  import android.app.AlertDialog;
  import android.app.Dialog;
  import android.app.ProgressDialog;
@@@ -90,11 -96,10 +96,10 @@@ import com.owncloud.android.operations.
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
- import com.owncloud.android.operations.SynchronizeFolderOperation;
+ import com.owncloud.android.operations.RefreshFolderOperation;
  import com.owncloud.android.operations.UnshareLinkOperation;
  import com.owncloud.android.services.observer.FileObserverService;
  import com.owncloud.android.syncadapter.FileSyncAdapter;
- import com.owncloud.android.ui.adapter.FileListListAdapter;
  import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
  import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
  import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener;
@@@ -107,14 -112,12 +112,12 @@@ import com.owncloud.android.ui.preview.
  import com.owncloud.android.ui.preview.PreviewVideoActivity;
  import com.owncloud.android.utils.DisplayUtils;
  import com.owncloud.android.utils.ErrorMessageAdapter;
+ import com.owncloud.android.utils.FileStorageUtils;
  import com.owncloud.android.utils.UriUtils;
  
  
  /**
   * Displays, what files the user has available in his ownCloud.
-  * 
-  * @author Bartek Przybylski
-  * @author David A. Velasco
   */
  
  public class FileDisplayActivity extends HookActivity implements
@@@ -253,7 -256,7 +256,7 @@@ OnSslUntrustedCertListener, OnEnforceab
              setNavigationListWithFolder(file);
              
              if (!stateWasRecovered) {
-                 Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
+                 Log_OC.d(TAG, "Initializing Fragments in onAccountChanged..");
                  initFragmentsWithFile();
                  if (file.isFolder()) {
                      startSyncFolderOperation(file, false);
              
              // Read sorting order, default to sort by name ascending
              Integer sortOrder = appPreferences
-                     .getInt("sortOrder", FileListListAdapter.SORT_NAME);
+                     .getInt("sortOrder", FileStorageUtils.SORT_NAME);
              
              AlertDialog.Builder builder = new AlertDialog.Builder(this);
              builder.setTitle(R.string.actionbar_sort_title)
      }
  
      private void startSynchronization() {
-         Log_OC.e(TAG, "Got to start sync");
+         Log_OC.d(TAG, "Got to start sync");
          if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
-             Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority());
+             Log_OC.d(TAG, "Canceling all syncs for " + MainApp.getAuthority());
              ContentResolver.cancelSync(null, MainApp.getAuthority());   // cancel the current synchronizations of any ownCloud account
              Bundle bundle = new Bundle();
              bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
              bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
+             Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
              ContentResolver.requestSync(
                      getAccount(),
                      MainApp.getAuthority(), bundle);
          } else {
-             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
+             Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
              SyncRequest.Builder builder = new SyncRequest.Builder();
              builder.setSyncAdapter(getAccount(), MainApp.getAuthority());
              builder.setExpedited(true);
  
      /**
       * Called, when the user selected something for uploading
+      *
       */
+     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
  
          if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
-             requestSimpleUpload(data, resultCode);
+             //getClipData is only supported on api level 16+, Jelly Bean
+             if (data.getData() == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
+                 for( int i = 0; i < data.getClipData().getItemCount(); i++){
+                     Intent intent = new Intent();
+                     intent.setData(data.getClipData().getItemAt(i).getUri());
+                     requestSimpleUpload(intent, resultCode);
+                 }
+             }else {
+                 requestSimpleUpload(data, resultCode);
+             }
          } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
              requestMultipleUpload(data, resultCode);
  
          if (filePaths != null) {
              String[] remotePaths = new String[filePaths.length];
              String remotePathBase = "";
              for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
                  remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
              }
  
          } finally {
              if (filepath == null) {
-                 Log_OC.e(TAG, "Couldnt resolve path to file");
+                 Log_OC.e(TAG, "Couldn't resolve path to file");
                  Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
                  t.show();
                  return;
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
-         Log_OC.e(TAG, "onSaveInstanceState() start");
+         Log_OC.d(TAG, "onSaveInstanceState() start");
          super.onSaveInstanceState(outState);
          outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
          outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
      @Override
      protected void onResume() {
          super.onResume();
-         Log_OC.e(TAG, "onResume() start");
+         Log_OC.d(TAG, "onResume() start");
          
          // refresh list of files
          refreshListOfFilesFragment();
          IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
          mSyncBroadcastReceiver = new SyncBroadcastReceiver();
          registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
          //LocalBroadcastManager.getInstance(this).registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
  
      @Override
      protected void onPause() {
-         Log_OC.e(TAG, "onPause() start");
+         Log_OC.d(TAG, "onPause() start");
          if (mSyncBroadcastReceiver != null) {
              unregisterReceiver(mSyncBroadcastReceiver);
              //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver);
                      } else if (item == 1) {
                          Intent action = new Intent(Intent.ACTION_GET_CONTENT);
                          action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
+                         //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean
+                         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                             action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+                         }
                          startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
                                  ACTION_SELECT_CONTENT_FROM_APPS);
                      }
                              setFile(currentFile);
                          }
                          
-                         mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
+                         mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
                                  
-                         if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
+                         if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
                                      equals(event) &&
                                  /// TODO refactor and make common
                                  synchResult != null && !synchResult.isSuccess() &&  
                                      (synchResult.isException() && synchResult.getException() 
                                              instanceof AuthenticatorException))) {
  
-                             OwnCloudClient client = null;
                              try {
-                                 OwnCloudAccount ocAccount = 
+                                 OwnCloudClient client;
+                                 OwnCloudAccount ocAccount =
                                          new OwnCloudAccount(getAccount(), context);
                                  client = (OwnCloudClientManagerFactory.getDefaultSingleton().
                                          removeClientFor(ocAccount));
-                                 // TODO get rid of these exceptions
-                             } catch (AccountNotFoundException e) {
-                                 e.printStackTrace();
-                             } catch (AuthenticatorException e) {
-                                 e.printStackTrace();
-                             } catch (OperationCanceledException e) {
-                                 e.printStackTrace();
-                             } catch (IOException e) {
-                                 e.printStackTrace();
-                             }
-                             
-                             if (client != null) {
-                                 OwnCloudCredentials cred = client.getCredentials();
-                                 if (cred != null) {
-                                     AccountManager am = AccountManager.get(context);
-                                     if (cred.authTokenExpires()) {
-                                         am.invalidateAuthToken(
-                                                 getAccount().type, 
-                                                 cred.getAuthToken()
-                                         );
-                                     } else {
-                                         am.clearPassword(getAccount());
+                                 if (client != null) {
+                                     OwnCloudCredentials cred = client.getCredentials();
+                                     if (cred != null) {
+                                         AccountManager am = AccountManager.get(context);
+                                         if (cred.authTokenExpires()) {
+                                             am.invalidateAuthToken(
+                                                     getAccount().type,
+                                                     cred.getAuthToken()
+                                             );
+                                         } else {
+                                             am.clearPassword(getAccount());
+                                         }
                                      }
                                  }
+                                 requestCredentialsUpdate();
+                             } catch (AccountNotFoundException e) {
+                                 Log_OC.e(TAG, "Account " + getAccount() + " was removed!", e);
                              }
-                             
-                             requestCredentialsUpdate();
-                             
                          }
                      }
                      removeStickyBroadcast(intent);
  
  
      /**
-      * Class waiting for broadcast events from the {@link FielDownloader} service.
+      * Class waiting for broadcast events from the {@link FileDownloader} service.
       * 
       * Updates the UI when a download is started or finished, provided that it is relevant for the
       * current folder.
       */
      private class DownloadFinishReceiver extends BroadcastReceiver {
+         //int refreshCounter = 0;
          @Override
          public void onReceive(Context context, Intent intent) {
              try {
                  boolean sameAccount = isSameAccount(context, intent);
                  String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
                  boolean isDescendant = isDescendant(downloadedRemotePath);
-     
                  if (sameAccount && isDescendant) {
-                     refreshListOfFilesFragment();
-                     refreshSecondFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
+                     String linkedToRemotePath = intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
+                         //Log_OC.v(TAG, "refresh #" + ++refreshCounter);
+                         refreshListOfFilesFragment();
+                     }
+                     refreshSecondFragment(
+                             intent.getAction(),
+                             downloadedRemotePath,
+                             intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)
+                     );
                  }
      
                  if (mWaitingToSend != null) {
-                     mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); // Update the file to send
+                     mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
                      if (mWaitingToSend.isDown()) { 
                          sendDownloadedFile();
                      }
  
          private boolean isDescendant(String downloadedRemotePath) {
              OCFile currentDir = getCurrentDir();
-             return (currentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(currentDir.getRemotePath()));
+             return (
+                 currentDir != null &&
+                 downloadedRemotePath != null &&
+                 downloadedRemotePath.startsWith(currentDir.getRemotePath())
+             );
+         }
+         private boolean isAscendant(String linkedToRemotePath) {
+             OCFile currentDir = getCurrentDir();
+             return (
+                 currentDir != null &&
+                 currentDir.getRemotePath().startsWith(linkedToRemotePath)
+             );
          }
  
          private boolean isSameAccount(Context context, Intent intent) {
       * TODO
       */
      private void updateNavigationElementsInActionBar(OCFile chosenFile) {
 -        ActionBar actionBar = getSupportActionBar(); 
 +        ActionBar actionBar = getSupportActionBar();
 +
 +        // For adding content description tag to a title field in the action bar
 +        int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
 +
          if (chosenFile == null || mDualPane) {
              // only list of files - set for browsing through folders
              OCFile currentDir = getCurrentDir();
              actionBar.setDisplayShowTitleEnabled(!noRoot); 
              if (!noRoot) {
                  actionBar.setTitle(getString(R.string.default_display_name_for_root_folder));
 +                getWindow().getDecorView().findViewById(actionBarTitleId).setContentDescription(getString(R.string.default_display_name_for_root_folder));
              }
              actionBar.setNavigationMode(!noRoot ? ActionBar.NAVIGATION_MODE_STANDARD : ActionBar.NAVIGATION_MODE_LIST);
              actionBar.setListNavigationCallbacks(mDirectories, this);   // assuming mDirectories is updated
              actionBar.setDisplayShowTitleEnabled(true);
              actionBar.setTitle(chosenFile.getFileName());
              actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
 +            getWindow().getDecorView().findViewById(actionBarTitleId).setContentDescription(chosenFile.getFileName());
          }
      }
  
  
      private void requestForDownload() {
          Account account = getAccount();
+         //if (!mWaitingToPreview.isDownloading()) {
          if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
              Intent i = new Intent(this, FileDownloader.class);
              i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
          mSyncInProgress = true;
                  
          // perform folder synchronization
-         RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
+         RemoteOperation synchFolderOp = new RefreshFolderOperation( folder,
                                                                          currentSyncTime, 
                                                                          false,
                                                                          getFileOperationsHelper().isSharedSupported(),
      
      private void requestForDownload(OCFile file) {
          Account account = getAccount();
-         if (!mDownloaderBinder.isDownloading(account, file)) {
+         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
              Intent i = new Intent(this, FileDownloader.class);
              i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
              i.putExtra(FileDownloader.EXTRA_FILE, file);
@@@ -1,6 -1,10 +1,10 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author David A. Velasco
   *   Copyright (C) 2011  Bartek Przybylski
-  *   Copyright (C) 2012-2013 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -21,13 -25,17 +25,17 @@@ import android.accounts.Account
  import android.accounts.AccountManager;
  import android.accounts.AccountManagerCallback;
  import android.accounts.AccountManagerFuture;
+ import android.content.ComponentName;
+ import android.content.Context;
  import android.content.Intent;
+ import android.content.ServiceConnection;
  import android.content.SharedPreferences;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager.NameNotFoundException;
  import android.net.Uri;
  import android.os.Bundle;
  import android.os.Handler;
+ import android.os.IBinder;
  import android.preference.CheckBoxPreference;
  import android.preference.Preference;
  import android.preference.Preference.OnPreferenceChangeListener;
@@@ -50,20 -58,25 +58,25 @@@ import com.owncloud.android.MainApp
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.authentication.AuthenticatorActivity;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.db.DbHandler;
+ import com.owncloud.android.files.FileOperationsHelper;
+ import com.owncloud.android.files.services.FileDownloader;
+ import com.owncloud.android.files.services.FileUploader;
  import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.services.OperationsService;
  import com.owncloud.android.ui.RadioButtonPreference;
  import com.owncloud.android.utils.DisplayUtils;
  
+ import java.io.File;
  
  /**
   * An Activity that allows the user to change the application's settings.
-  * 
-  * @author Bartek Przybylski
-  * @author David A. Velasco
   */
- public class Preferences extends SherlockPreferenceActivity implements AccountManagerCallback<Boolean> {
+ public class Preferences extends SherlockPreferenceActivity
+         implements AccountManagerCallback<Boolean>, ComponentsGetter {
      
      private static final String TAG = "OwnCloudPreferences";
  
      private String mAccountName;
      private boolean mShowContextMenu = false;
      private String mUploadPath;
+     private PreferenceCategory mPrefInstantUploadCategory;
+     private Preference mPrefInstantUpload;
      private Preference mPrefInstantUploadPath;
+     private Preference mPrefInstantUploadPathWiFi;
+     private Preference mPrefInstantVideoUpload;
      private Preference mPrefInstantVideoUploadPath;
+     private Preference mPrefInstantVideoUploadPathWiFi;
      private String mUploadVideoPath;
  
+     protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
+     protected FileUploader.FileUploaderBinder mUploaderBinder = null;
+     private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
  
      @SuppressWarnings("deprecation")
      @Override
          actionBar.setDisplayHomeAsUpEnabled(true);
          actionBar.setTitle(R.string.actionbar_settings);
  
 +        // For adding content description tag to a title field in the action bar
 +        int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
 +        getWindow().getDecorView().findViewById(actionBarTitleId).setContentDescription(getString(R.string.actionbar_settings));
 +
          // Load the accounts category for adding the list of accounts
          mAccountsPrefCategory = (PreferenceCategory) findPreference("accounts_category");
  
                          String username = currentAccount.name.substring(0, currentAccount.name.lastIndexOf('@'));
                          
                          String recommendSubject = String.format(getString(R.string.recommend_subject), appName);
-                         String recommendText = String.format(getString(R.string.recommend_text), appName, downloadUrl, username);
+                         String recommendText = String.format(getString(R.string.recommend_text),
+                                 appName, downloadUrl, username);
                          
                          intent.putExtra(Intent.EXTRA_SUBJECT, recommendSubject);
                          intent.putExtra(Intent.EXTRA_TEXT, recommendText);
                          startActivity(intent);
  
                          return(true);
  
                      }
                      }
                  });
          }
+         
+         mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
+         
+         mPrefInstantUploadPathWiFi =  findPreference("instant_upload_on_wifi");
+         mPrefInstantUpload = findPreference("instant_uploading");
+         
+         toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
+         
+         mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+             
+             @Override
+             public boolean onPreferenceChange(Preference preference, Object newValue) {
+                 toggleInstantPictureOptions((Boolean) newValue);
+                 return true;
+             }
+         });
+        
          mPrefInstantVideoUploadPath =  findPreference("instant_video_upload_path");
          if (mPrefInstantVideoUploadPath != null){
  
                      }
                  });
          }
+         
+         mPrefInstantVideoUploadPathWiFi =  findPreference("instant_video_upload_on_wifi");
+         mPrefInstantVideoUpload = findPreference("instant_video_uploading");
+         toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked());
+         
+         mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+             
+             @Override
+             public boolean onPreferenceChange(Preference preference, Object newValue) {
+                 toggleInstantVideoOptions((Boolean) newValue);
+                 return true;
+             }
+         });
              
          /* About App */
         pAboutApp = (Preference) findPreference("about_app");
         loadInstantUploadPath();
         loadInstantUploadVideoPath();
  
+         /* ComponentsGetter */
+         mDownloadServiceConnection = newTransferenceServiceConnection();
+         if (mDownloadServiceConnection != null) {
+             bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
+                     Context.BIND_AUTO_CREATE);
+         }
+         mUploadServiceConnection = newTransferenceServiceConnection();
+         if (mUploadServiceConnection != null) {
+             bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
+                     Context.BIND_AUTO_CREATE);
+         }
+     }
+     
+     private void toggleInstantPictureOptions(Boolean value){
+         if (value){
+             mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi);
+             mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath);
+         } else {
+             mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
+             mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
+         }
+     }
+     
+     private void toggleInstantVideoOptions(Boolean value){
+         if (value){
+             mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi);
+             mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath);
+         } else {
+             mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
+             mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
+         }
      }
  
      @Override
  
                      // Remove account
                      am.removeAccount(a, this, mHandler);
+                     Log_OC.d(TAG, "Remove an account " + a.name);
                  }
              }
          }
      @Override
      public void run(AccountManagerFuture<Boolean> future) {
          if (future.isDone()) {
+             // after remove account
+             Account account = new Account(mAccountName, MainApp.getAccountType());
+             if (!AccountUtils.exists(account, MainApp.getAppContext())) {
+                 // Cancel tranfers
+                 if (mUploaderBinder != null) {
+                     mUploaderBinder.cancel(account);
+                 }
+                 if (mDownloaderBinder != null) {
+                     mDownloaderBinder.cancel(account);
+                 }
+             }
              Account a = AccountUtils.getCurrentOwnCloudAccount(this);
              String accountName = "";
              if (a == null) {
      @Override
      protected void onDestroy() {
          mDbHandler.close();
+         if (mDownloadServiceConnection != null) {
+             unbindService(mDownloadServiceConnection);
+             mDownloadServiceConnection = null;
+         }
+         if (mUploadServiceConnection != null) {
+             unbindService(mUploadServiceConnection);
+             mUploadServiceConnection = null;
+         }
          super.onDestroy();
      }
  
          editor.putString("instant_video_upload_path", mUploadVideoPath);
          editor.commit();
      }
+     // Methods for ComponetsGetter
+     @Override
+     public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
+         return mDownloaderBinder;
+     }
+     @Override
+     public FileUploader.FileUploaderBinder getFileUploaderBinder() {
+         return mUploaderBinder;
+     }
+     @Override
+     public OperationsService.OperationsServiceBinder getOperationsServiceBinder() {
+         return null;
+     }
+     @Override
+     public FileDataStorageManager getStorageManager() {
+         return null;
+     }
+     @Override
+     public FileOperationsHelper getFileOperationsHelper() {
+         return null;
+     }
+     protected ServiceConnection newTransferenceServiceConnection() {
+         return new PreferencesServiceConnection();
+     }
+     /** Defines callbacks for service binding, passed to bindService() */
+     private class PreferencesServiceConnection implements ServiceConnection {
+         @Override
+         public void onServiceConnected(ComponentName component, IBinder service) {
+             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
+                 mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
+             } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
+                 Log_OC.d(TAG, "Upload service connected");
+                 mUploaderBinder = (FileUploader.FileUploaderBinder) service;
+             } else {
+                 return;
+             }
+         }
+         @Override
+         public void onServiceDisconnected(ComponentName component) {
+             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
+                 Log_OC.d(TAG, "Download service suddenly disconnected");
+                 mDownloaderBinder = null;
+             } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
+                 Log_OC.d(TAG, "Upload service suddenly disconnected");
+                 mUploaderBinder = null;
+             }
+         }
+     };
  }
@@@ -1,6 -1,11 +1,11 @@@
- /* ownCloud Android client application\r
+ /**\r
+  *   ownCloud Android client application\r
+  *\r
+  *   @author Bartek Przybylski\r
+  *   @author Tobias Kaminsky\r
+  *   @author David A. Velasco\r
   *   Copyright (C) 2011  Bartek Przybylski\r
-  *   Copyright (C) 2012-2014 ownCloud Inc.\r
+  *   Copyright (C) 2015 ownCloud Inc.\r
   *\r
   *   This program is free software: you can redistribute it and/or modify\r
   *   it under the terms of the GNU General Public License version 2,\r
@@@ -19,11 -24,8 +24,8 @@@ package com.owncloud.android.ui.adapter
  \r
  \r
  import java.io.File;\r
- import java.util.Collections;\r
- import java.util.Comparator;\r
  import java.util.Vector;\r
  \r
- import third_parties.daveKoeller.AlphanumComparator;\r
  import android.accounts.Account;\r
  import android.content.Context;\r
  import android.content.SharedPreferences;\r
@@@ -33,11 -35,11 +35,12 @@@ import android.text.format.DateUtils
  import android.view.LayoutInflater;\r
  import android.view.View;\r
  import android.view.ViewGroup;\r
+ import android.widget.AbsListView;\r
  import android.widget.BaseAdapter;\r
+ import android.widget.GridView;\r
  import android.widget.ImageView;\r
 +import android.widget.LinearLayout;\r
  import android.widget.ListAdapter;\r
- import android.widget.ListView;\r
  import android.widget.TextView;\r
  \r
  import com.owncloud.android.R;\r
@@@ -45,9 -47,9 +48,9 @@@ import com.owncloud.android.authenticat
  import com.owncloud.android.datamodel.FileDataStorageManager;\r
  import com.owncloud.android.datamodel.OCFile;\r
  import com.owncloud.android.datamodel.ThumbnailsCacheManager;\r
- import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;\r
  import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
  import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
+ import com.owncloud.android.services.OperationsService.OperationsServiceBinder;\r
  import com.owncloud.android.ui.activity.ComponentsGetter;\r
  import com.owncloud.android.utils.DisplayUtils;\r
  import com.owncloud.android.utils.FileStorageUtils;\r
  /**\r
   * This Adapter populates a ListView with all files and folders in an ownCloud\r
   * instance.\r
-  * \r
-  * @author Bartek Przybylski\r
-  * @author Tobias Kaminsky\r
-  * @author David A. Velasco\r
   */\r
  public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
      private final static String PERMISSION_SHARED_WITH_ME = "S";\r
-     \r
\r
      private Context mContext;\r
      private OCFile mFile = null;\r
      private Vector<OCFile> mFiles = null;\r
+     private Vector<OCFile> mFilesOrig = new Vector<OCFile>();\r
      private boolean mJustFolders;\r
  \r
      private FileDataStorageManager mStorageManager;\r
      private Account mAccount;\r
      private ComponentsGetter mTransferServiceGetter;\r
-     private Integer mSortOrder;\r
-     public static final Integer SORT_NAME = 0;\r
-     public static final Integer SORT_DATE = 1;\r
-     public static final Integer SORT_SIZE = 2;\r
-     private Boolean mSortAscending;\r
+     private boolean mGridMode;\r
\r
+     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };\r
\r
      private SharedPreferences mAppPreferences;\r
      \r
      public FileListListAdapter(\r
              boolean justFolders, \r
-             Context context, \r
+             Context context,\r
              ComponentsGetter transferServiceGetter\r
              ) {\r
\r
+         \r
          mJustFolders = justFolders;\r
          mContext = context;\r
          mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
\r
          mTransferServiceGetter = transferServiceGetter;\r
-         \r
\r
          mAppPreferences = PreferenceManager\r
                  .getDefaultSharedPreferences(mContext);\r
          \r
          // Read sorting order, default to sort by name ascending\r
-         mSortOrder = mAppPreferences\r
-                 .getInt("sortOrder", 0);\r
-         mSortAscending = mAppPreferences.getBoolean("sortAscending", true);\r
+         FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);\r
+         FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);\r
 -\r
          \r
          // initialise thumbnails cache on background thread\r
          new ThumbnailsCacheManager.InitDiskCacheTask().execute();\r
  \r
+         mGridMode = false;\r
      }\r
      \r
      @Override\r
  \r
      @Override\r
      public View getView(int position, View convertView, ViewGroup parent) {\r
\r
          View view = convertView;\r
-         if (view == null) {\r
-             LayoutInflater inflator = (LayoutInflater) mContext\r
-                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
-             view = inflator.inflate(R.layout.list_item, null);\r
-         }\r
-          \r
+         OCFile file = null;\r
+         LayoutInflater inflator = (LayoutInflater) mContext\r
+                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
\r
          if (mFiles != null && mFiles.size() > position) {\r
-             OCFile file = mFiles.get(position);\r
-             TextView fileName = (TextView) view.findViewById(R.id.Filename);           \r
+             file = mFiles.get(position);\r
+         }\r
\r
+         // Find out which layout should be displayed\r
+         ViewType viewType;\r
+         if (!mGridMode){\r
+             viewType = ViewType.LIST_ITEM;\r
+         } else if (file.isImage()){\r
+             viewType = ViewType.GRID_IMAGE;\r
+         } else {\r
+             viewType = ViewType.GRID_ITEM;\r
+         }\r
\r
+         // Create View\r
+         switch (viewType){\r
+             case GRID_IMAGE:\r
+                 view = inflator.inflate(R.layout.grid_image, null);\r
+                 break;\r
+             case GRID_ITEM:\r
+                 view = inflator.inflate(R.layout.grid_item, null);\r
+                 break;\r
+             case LIST_ITEM:\r
+                 view = inflator.inflate(R.layout.list_item, null);\r
+                 break;\r
+         }\r
\r
+         view.invalidate();\r
\r
+         if (file != null){\r
\r
+             ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);\r
++\r
+             fileIcon.setTag(file.getFileId());\r
+             TextView fileName;\r
 -            String name;\r
 +            String name = file.getFileName();\r
 +\r
 +            LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.ListItemLayout);\r
 +            linearLayout.setContentDescription("LinearLayout-" + name);\r
  \r
-             fileName.setText(name);\r
-             ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);\r
-             fileIcon.setTag(file.getFileId());\r
-             ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
-             ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
-             sharedWithMeIconV.setVisibility(View.GONE);\r
\r
-             ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
-             localStateView.bringToFront();\r
-             FileDownloaderBinder downloaderBinder = \r
-                     mTransferServiceGetter.getFileDownloaderBinder();\r
-             FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
-             if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {\r
-                 localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {\r
-                 localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else if (file.isDown()) {\r
-                 localStateView.setImageResource(R.drawable.local_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else {\r
-                 localStateView.setVisibility(View.INVISIBLE);\r
+             switch (viewType){\r
+                 case LIST_ITEM:\r
+                     TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
+                     TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
+                     ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
\r
+                     lastModV.setVisibility(View.VISIBLE);\r
+                     lastModV.setText(showRelativeTimestamp(file));\r
\r
+                     checkBoxV.setVisibility(View.GONE);\r
\r
+                     fileSizeV.setVisibility(View.VISIBLE);\r
+                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
\r
+                     if (!file.isFolder()) {\r
+                         AbsListView parentList = (AbsListView)parent;\r
+                         if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+                             checkBoxV.setVisibility(View.GONE);\r
+                         } else {\r
+                             if (parentList.isItemChecked(position)) {\r
+                                 checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);\r
+                             } else {\r
+                                 checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
+                             }\r
+                             checkBoxV.setVisibility(View.VISIBLE);\r
+                         }\r
\r
+                     } else { //Folder\r
+                         fileSizeV.setVisibility(View.INVISIBLE);\r
+                     }\r
\r
+                 case GRID_ITEM:\r
+                     // filename\r
+                     fileName = (TextView) view.findViewById(R.id.Filename);\r
+                     name = file.getFileName();\r
+                     fileName.setText(name);\r
\r
+                 case GRID_IMAGE:\r
+                     // sharedIcon\r
+                     ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
+                     if (file.isShareByLink()) {\r
+                         sharedIconV.setVisibility(View.VISIBLE);\r
+                         sharedIconV.bringToFront();\r
+                     } else {\r
+                         sharedIconV.setVisibility(View.GONE);\r
+                     }\r
\r
+                     // local state\r
+                     ImageView localStateView = (ImageView) view.findViewById(R.id.localFileIndicator);\r
+                     localStateView.bringToFront();\r
+                     FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();\r
+                     FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
+                     boolean downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file));\r
+                     OperationsServiceBinder opsBinder = mTransferServiceGetter.getOperationsServiceBinder();\r
+                     downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, file.getRemotePath()));\r
+                     if (downloading) {\r
+                         localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {\r
+                         localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else if (file.isDown()) {\r
+                         localStateView.setImageResource(R.drawable.local_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else {\r
+                         localStateView.setVisibility(View.INVISIBLE);\r
+                     }\r
\r
+                     // share with me icon\r
+                     if (!file.isFolder()) {\r
+                         ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
+                         sharedWithMeIconV.bringToFront();\r
+                         if (checkIfFileIsSharedWithMe(file)) {\r
+                             sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                         } else {\r
+                             sharedWithMeIconV.setVisibility(View.GONE);\r
+                         }\r
+                     }\r
\r
+                     break;\r
              }\r
              \r
-             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
-             TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
-             ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+             // For all Views\r
              \r
+             // this if-else is needed even though favorite icon is visible by default\r
+             // because android reuses views in listview\r
+             if (!file.keepInSync()) {\r
+                 view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);\r
+             } else {\r
+                 view.findViewById(R.id.favoriteIcon).setVisibility(View.VISIBLE);\r
+             }\r
+             \r
+             // No Folder\r
              if (!file.isFolder()) {\r
-                 fileSizeV.setVisibility(View.VISIBLE);\r
-                 fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
-                 lastModV.setVisibility(View.VISIBLE);\r
-                 lastModV.setText(showRelativeTimestamp(file));\r
-                 // this if-else is needed even thoe fav icon is visible by default\r
-                 // because android reuses views in listview\r
-                 if (!file.keepInSync()) {\r
-                     view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
-                 } else {\r
-                     view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);\r
-                 }\r
-                 \r
-                 ListView parentList = (ListView)parent;\r
-                 if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { \r
-                     checkBoxV.setVisibility(View.GONE);\r
-                 } else {\r
-                     if (parentList.isItemChecked(position)) {\r
-                         checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);\r
-                     } else {\r
-                         checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
-                     }\r
-                     checkBoxV.setVisibility(View.VISIBLE);\r
-                 }               \r
-                 \r
-                 // get Thumbnail if file is image\r
                  if (file.isImage() && file.getRemoteId() != null){\r
-                      // Thumbnail in Cache?\r
+                     // Thumbnail in Cache?\r
                      Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
                              String.valueOf(file.getRemoteId())\r
-                     );\r
+                             );\r
                      if (thumbnail != null && !file.needsUpdateThumbnail()){\r
                          fileIcon.setImageBitmap(thumbnail);\r
                      } else {\r
                          // generate new Thumbnail\r
                          if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
-                             final ThumbnailsCacheManager.ThumbnailGenerationTask task = \r
+                             final ThumbnailsCacheManager.ThumbnailGenerationTask task =\r
                                      new ThumbnailsCacheManager.ThumbnailGenerationTask(\r
                                              fileIcon, mStorageManager, mAccount\r
-                                     );\r
+                                             );\r
                              if (thumbnail == null) {\r
                                  thumbnail = ThumbnailsCacheManager.mDefaultImg;\r
                              }\r
-                             final AsyncDrawable asyncDrawable = new AsyncDrawable(\r
+                             final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =\r
+                                     new ThumbnailsCacheManager.AsyncDrawable(\r
                                      mContext.getResources(), \r
                                      thumbnail, \r
                                      task\r
-                             );\r
+                                     );\r
                              fileIcon.setImageDrawable(asyncDrawable);\r
                              task.execute(file);\r
                          }\r
                      }\r
                  } else {\r
-                     fileIcon.setImageResource(\r
-                             DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
-                     );\r
-                 }\r
\r
-                 if (checkIfFileIsSharedWithMe(file)) {\r
-                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                     fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()));\r
                  }\r
-             } \r
-             else {\r
-                   // TODO Re-enable when server supports folder-size calculation\r
- //                if (FileStorageUtils.getDefaultSavePathFor(mAccount.name, file) != null){\r
- //                    fileSizeV.setVisibility(View.VISIBLE);\r
- //                    fileSizeV.setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)));\r
- //                } else {\r
-                     fileSizeV.setVisibility(View.INVISIBLE);\r
- //                }\r
\r
-                 lastModV.setVisibility(View.VISIBLE);\r
-                 lastModV.setText(showRelativeTimestamp(file));\r
-                 checkBoxV.setVisibility(View.GONE);\r
-                 view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
 +\r
+             } else {\r
+                 // Folder\r
                  if (checkIfFileIsSharedWithMe(file)) {\r
                      fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
-                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                 } else if (file.isShareByLink()) {\r
+                     // If folder is sharedByLink, icon folder must be changed to\r
+                     // folder-public one\r
+                     fileIcon.setImageResource(R.drawable.folder_public);\r
                  } else {\r
                      fileIcon.setImageResource(\r
-                             DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
+                             DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())\r
                      );\r
                  }\r
\r
-                 // If folder is sharedByLink, icon folder must be changed to\r
-                 // folder-public one\r
-                 if (file.isShareByLink()) {\r
-                     fileIcon.setImageResource(R.drawable.folder_public);\r
-                 }\r
-             }\r
\r
-             if (file.isShareByLink()) {\r
-                 sharedIconV.setVisibility(View.VISIBLE);\r
-             } else {\r
-                 sharedIconV.setVisibility(View.GONE);\r
              }\r
          }\r
  \r
          File dir = new File(path);\r
  \r
          if (dir.exists()) {\r
-             long bytes = getFolderSize(dir);\r
+             long bytes = FileStorageUtils.getFolderSize(dir);\r
              return DisplayUtils.bytesToHumanReadable(bytes);\r
          }\r
  \r
          }\r
          if (mStorageManager != null) {\r
              mFiles = mStorageManager.getFolderContent(mFile);\r
+             mFilesOrig.clear();\r
+             mFilesOrig.addAll(mFiles);\r
+             \r
              if (mJustFolders) {\r
                  mFiles = getFolders(mFiles);\r
              }\r
              mFiles = null;\r
          }\r
  \r
-         sortDirectory();\r
-     }\r
-     \r
-     /**\r
-      * Sorts all filenames, regarding last user decision \r
-      */\r
-     private void sortDirectory(){\r
-         switch (mSortOrder){\r
-         case 0:\r
-             sortByName(mSortAscending);\r
-             break;\r
-         case 1:\r
-             sortByDate(mSortAscending);\r
-             break;\r
-         case 2: \r
-             sortBySize(mSortAscending);\r
-             break;\r
-         }\r
-         \r
+         mFiles = FileStorageUtils.sortFolder(mFiles);\r
          notifyDataSetChanged();\r
      }\r
      \r
-     \r
\r
      /**\r
       * Filter for getting only the folders\r
       * @param files\r
                  && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
      }\r
  \r
-     /**\r
-      * Sorts list by Date\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortByDate(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
-         \r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     Long obj1 = o1.getModificationTimestamp();\r
-                     return val * obj1.compareTo(o2.getModificationTimestamp());\r
-                 }\r
-                 else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){\r
-                     return 0;\r
-                 } else {\r
-                     Long obj1 = o1.getModificationTimestamp();\r
-                     return val * obj1.compareTo(o2.getModificationTimestamp());\r
-                 }\r
-             }\r
-         });\r
-     }\r
\r
-     /**\r
-      * Sorts list by Size\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortBySize(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
-         \r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));\r
-                     return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));\r
-                 }\r
-                 else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){\r
-                     return 0;\r
-                 } else {\r
-                     Long obj1 = o1.getFileLength();\r
-                     return val * obj1.compareTo(o2.getFileLength());\r
-                 }\r
-             }\r
-         });\r
-     }\r
\r
-     /**\r
-      * Sorts list by Name\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortByName(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
\r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());\r
-                 } else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 }\r
-                 return val * new AlphanumComparator().compare(o1, o2);\r
-             }\r
-         });\r
-     }\r
\r
      public void setSortOrder(Integer order, boolean ascending) {\r
          SharedPreferences.Editor editor = mAppPreferences.edit();\r
          editor.putInt("sortOrder", order);\r
          editor.putBoolean("sortAscending", ascending);\r
          editor.commit();\r
          \r
-         mSortOrder = order;\r
-         mSortAscending = ascending;\r
+         FileStorageUtils.mSortOrder = order;\r
+         FileStorageUtils.mSortAscending = ascending;\r
          \r
-         sortDirectory();\r
-     }    \r
\r
+         mFiles = FileStorageUtils.sortFolder(mFiles);\r
+         notifyDataSetChanged();\r
\r
+     }\r
      \r
      private CharSequence showRelativeTimestamp(OCFile file){\r
          return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),\r
                  DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);\r
      }\r
\r
+     public void setGridMode(boolean gridMode) {\r
+         mGridMode = gridMode;\r
+     }\r
  }\r