Merge branch 'gradleWithInternalDependency' into us4_view_text_files
authorJorge Antonio Diaz-Benito Soriano <jorge.diazbenitosoriano@gmail.com>
Mon, 24 Nov 2014 11:57:02 +0000 (12:57 +0100)
committerJorge Antonio Diaz-Benito Soriano <jorge.diazbenitosoriano@gmail.com>
Mon, 24 Nov 2014 11:57:02 +0000 (12:57 +0100)
Conflicts:
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

1  2 
.idea/misc.xml
.idea/modules.xml
android.iml
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

diff --combined .idea/misc.xml
index 0000000,b153e48..cded496
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,10 +1,10 @@@
 -  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
+ <?xml version="1.0" encoding="UTF-8"?>
+ <project version="4">
+   <component name="EntryPointsManager">
+     <entry_points version="2.0" />
+   </component>
++  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+     <output url="file://$PROJECT_DIR$/build/classes" />
+   </component>
+ </project>
diff --combined .idea/modules.xml
index 0000000,92fbe54..0ca17d1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,10 +1,11 @@@
+ <?xml version="1.0" encoding="UTF-8"?>
+ <project version="4">
+   <component name="ProjectModuleManager">
+     <modules>
+       <module fileurl="file://$PROJECT_DIR$/android.iml" filepath="$PROJECT_DIR$/android.iml" />
+       <module fileurl="file://$PROJECT_DIR$/owncloud-android-library/owncloud-android-library.iml" filepath="$PROJECT_DIR$/owncloud-android-library/owncloud-android-library.iml" />
++      <module fileurl="file://$PROJECT_DIR$/owncloud-android-library/owncloud-android-library.iml" filepath="$PROJECT_DIR$/owncloud-android-library/owncloud-android-library.iml" />
+     </modules>
+   </component>
+ </project>
diff --combined android.iml
index 0000000,4d0d9af..50ce0aa
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,92 +1,92 @@@
 -    <orderEntry type="library" exported="" name="library-4.1.0" level="project" />
+ <?xml version="1.0" encoding="UTF-8"?>
+ <module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+   <component name="FacetManager">
+     <facet type="android-gradle" name="Android-Gradle">
+       <configuration>
+         <option name="GRADLE_PROJECT_PATH" value=":" />
+       </configuration>
+     </facet>
+     <facet type="android" name="Android">
+       <configuration>
+         <option name="SELECTED_BUILD_VARIANT" value="debug" />
+         <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+         <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+         <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugTest" />
+         <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
+         <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugTestSources" />
+         <option name="ALLOW_USER_CONFIGURATION" value="false" />
+         <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/res" />
+         <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/res" />
+       </configuration>
+     </facet>
+   </component>
+   <component name="NewModuleRootManager" inherit-compiler-output="false">
+     <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+     <exclude-output />
+     <content url="file://$MODULE_DIR$">
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/debug" isTestSource="true" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/debug" isTestSource="true" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/debug" isTestSource="true" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/debug" isTestSource="true" generated="true" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/test/debug" type="java-test-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/aidl" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/java" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/jni" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/rs" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/src" type="java-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+       <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+     </content>
+     <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
+     <orderEntry type="sourceFolder" forTests="false" />
+     <orderEntry type="library" exported="" name="touch-image-view" level="project" />
+     <orderEntry type="library" exported="" name="disklrucache-2.0.2" level="project" />
+     <orderEntry type="library" exported="" name="support-v4-19.1.0" level="project" />
+     <orderEntry type="library" exported="" name="jcl-over-slf4j-1.7.4" level="project" />
++    <orderEntry type="library" exported="" name="libs/actionbarsherlock_lib-unspecified" level="project" />
+     <orderEntry type="library" exported="" name="commons-codec-1.2" level="project" />
+     <orderEntry type="library" exported="" name="jackrabbit-webdav-2.7.2" level="project" />
+     <orderEntry type="library" exported="" name="commons-httpclient-3.1" level="project" />
+     <orderEntry type="library" exported="" name="slf4j-api-1.7.5" level="project" />
+     <orderEntry type="module" module-name="owncloud-android-library" exported="" />
+   </component>
+ </module>
@@@ -18,6 -18,9 +18,6 @@@
  
  package com.owncloud.android.ui.activity;
  
 -import java.io.File;
 -import java.io.IOException;
 -
  import android.accounts.Account;
  import android.accounts.AccountManager;
  import android.accounts.AuthenticatorException;
@@@ -28,6 -31,7 +28,7 @@@ import android.app.ProgressDialog
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.ContentResolver;
+ import android.content.ContentUris;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
@@@ -38,13 -42,18 +39,18 @@@ import android.content.SyncRequest
  import android.content.res.Resources.NotFoundException;
  import android.database.Cursor;
  import android.net.Uri;
+ import android.os.Build;
  import android.os.Bundle;
+ import android.os.Environment;
  import android.os.IBinder;
  import android.preference.PreferenceManager;
+ import android.provider.DocumentsContract;
  import android.provider.MediaStore;
+ import android.provider.OpenableColumns;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.support.v4.app.FragmentTransaction;
+ import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
@@@ -95,26 -104,23 +101,27 @@@ import com.owncloud.android.ui.fragment
  import com.owncloud.android.ui.preview.PreviewImageActivity;
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
 +import com.owncloud.android.ui.preview.PreviewTextFragment;
  import com.owncloud.android.ui.preview.PreviewVideoActivity;
  import com.owncloud.android.utils.DisplayUtils;
  import com.owncloud.android.utils.ErrorMessageAdapter;
+ import com.owncloud.android.utils.UriUtils;
  
 +import java.io.File;
 +import java.io.IOException;
 +
  
  /**
   * Displays, what files the user has available in his ownCloud.
 - * 
 + *
   * @author Bartek Przybylski
   * @author David A. Velasco
   */
  
  public class FileDisplayActivity extends HookActivity implements
 -FileFragment.ContainerActivity, OnNavigationListener, 
 -OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 -    
 +        FileFragment.ContainerActivity, OnNavigationListener,
 +        OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 +
      private ArrayAdapter<String> mDirectories;
  
      private SyncBroadcastReceiver mSyncBroadcastReceiver;
      public static final int DIALOG_SHORT_WAIT = 0;
      private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1;
      private static final int DIALOG_CERT_NOT_SAVED = 2;
 -    
 +
      public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS";
  
      private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
      private static final String TAG_SECOND_FRAGMENT = "SECOND_FRAGMENT";
  
      private OCFile mWaitingToPreview;
 -    
 +
      private boolean mSyncInProgress = false;
  
      private String DIALOG_UNTRUSTED_CERT;
 -    
 +
      private OCFile mWaitingToSend;
  
      @Override
              Intent initObserversIntent = FileObserverService.makeInitIntent(this);
              startService(initObserversIntent);
          }
 -        
 +
          /// Load of saved instance state
 -        if(savedInstanceState != null) {
 +        if (savedInstanceState != null) {
              mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW);
              mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
              mWaitingToSend = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND);
 -           
 +
          } else {
              mWaitingToPreview = null;
              mSyncInProgress = false;
              mWaitingToSend = null;
 -        }        
 +        }
  
          /// USER INTERFACE
  
          // Inflate and set the layout view
 -        setContentView(R.layout.files);    
 +        setContentView(R.layout.files);
          mDualPane = getResources().getBoolean(R.bool.large_land_layout);
          mLeftFragmentContainer = findViewById(R.id.left_fragment_container);
          mRightFragmentContainer = findViewById(R.id.right_fragment_container);
          mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
          getSupportActionBar().setHomeButtonEnabled(true);       // mandatory since Android ICS, according to the official documentation
          setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);    // always AFTER setContentView(...) ; to work around bug in its implementation
 -        
 +
          setBackgroundText();
  
          Log_OC.d(TAG, "onCreate() end");
      }
 -    
 +
      @Override
      protected void onStart() {
          super.onStart();
      }
  
      /**
 -     *  Called when the ownCloud {@link Account} associated to the Activity was just updated.
 -     */ 
 +     * Called when the ownCloud {@link Account} associated to the Activity was just updated.
 +     */
      @Override
      protected void onAccountSet(boolean stateWasRecovered) {
          super.onAccountSet(stateWasRecovered);
                      // upload in progress - right now, files are not inserted in the local cache until the upload is successful
                      // get parent from path
                      parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
 -                    if (getStorageManager().getFileByPath(parentPath) ==  null)
 +                    if (getStorageManager().getFileByPath(parentPath) == null)
                          file = null; // not able to know the directory where the file is uploading
                  } else {
                      file = getStorageManager().getFileByPath(file.getRemotePath());   // currentDir = null if not in the current Account
              }
              setFile(file);
              setNavigationListWithFolder(file);
 -            
 +
              if (!stateWasRecovered) {
                  Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
                  initFragmentsWithFile();
                  if (file.isFolder()) {
                      startSyncFolderOperation(file, false);
                  }
 -                
 +
              } else {
                  updateFragmentsVisibility(!file.isFolder());
                  updateNavigationElementsInActionBar(file.isFolder() ? null : file);
          mDirectories.clear();
          OCFile fileIt = file;
          String parentPath;
 -        while(fileIt != null && fileIt.getFileName() != OCFile.ROOT_PATH) {
 +        while (fileIt != null && fileIt.getFileName() != OCFile.ROOT_PATH) {
              if (fileIt.isFolder()) {
                  mDirectories.add(fileIt.getFileName());
              }
          transaction.add(R.id.left_fragment_container, listOfFiles, TAG_LIST_OF_FILES);
          transaction.commit();
      }
 -    
 +
      private void initFragmentsWithFile() {
          if (getAccount() != null && getFile() != null) {
              /// First fragment
 -            OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +            OCFileListFragment listOfFiles = getListOfFilesFragment();
              if (listOfFiles != null) {
 -                listOfFiles.listDirectory(getCurrentDir());   
 +                listOfFiles.listDirectory(getCurrentDir());
              } else {
                  Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >(");
              }
 -            
 +
              /// Second fragment
 -            OCFile file = getFile(); 
 +            OCFile file = getFile();
              Fragment secondFragment = chooseInitialSecondFragment(file);
              if (secondFragment != null) {
                  setSecondFragment(secondFragment);
                  updateFragmentsVisibility(true);
                  updateNavigationElementsInActionBar(file);
 -                
 +
              } else {
                  cleanSecondFragment();
 +                if (file.isDown() && PreviewTextFragment.canBePreviewed(file))
 +                    startTextPreview(file);
              }
  
          } else {
      private Fragment chooseInitialSecondFragment(OCFile file) {
          Fragment secondFragment = null;
          if (file != null && !file.isFolder()) {
 -            if (file.isDown() && PreviewMediaFragment.canBePreviewed(file) 
 +            if (file.isDown() && PreviewMediaFragment.canBePreviewed(file)
                      && file.getLastSyncDateForProperties() > 0  // temporal fix
                      ) {
                  int startPlaybackPosition = getIntent().getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
                  boolean autoplay = getIntent().getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true);
                  secondFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay);
  
 -            } else {
 -                secondFragment = new FileDetailFragment(file, getAccount());
 -            }
 +            } else if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) {
 +                secondFragment = null;
 +            } else secondFragment = new FileDetailFragment(file, getAccount());
          }
          return secondFragment;
      }
      /**
       * Replaces the second fragment managed by the activity with the received as
       * a parameter.
 -     * 
 -     * Assumes never will be more than two fragments managed at the same time. 
 -     * 
 -     * @param fragment      New second Fragment to set.
 +     * <p/>
 +     * Assumes never will be more than two fragments managed at the same time.
 +     *
 +     * @param fragment New second Fragment to set.
       */
      private void setSecondFragment(Fragment fragment) {
          FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
      private OCFileListFragment getListOfFilesFragment() {
          Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_LIST_OF_FILES);
          if (listOfFiles != null) {
 -            return (OCFileListFragment)listOfFiles;
 +            return (OCFileListFragment) listOfFiles;
          }
          Log_OC.wtf(TAG, "Access to unexisting list of files fragment!!");
          return null;
      public FileFragment getSecondFragment() {
          Fragment second = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_SECOND_FRAGMENT);
          if (second != null) {
 -            return (FileFragment)second;
 +            return (FileFragment) second;
          }
          return null;
      }
  
      protected void refreshListOfFilesFragment() {
          OCFileListFragment fileListFragment = getListOfFilesFragment();
 -        if (fileListFragment != null) { 
 +        if (fileListFragment != null) {
              fileListFragment.listDirectory();
          }
      }
                          if (PreviewMediaFragment.canBePreviewed(mWaitingToPreview)) {
                              startMediaPreview(mWaitingToPreview, 0, true);
                              detailsFragmentChanged = true;
 +                        } else if (PreviewTextFragment.canBePreviewed(mWaitingToPreview)) {
 +                            startTextPreview(mWaitingToPreview);
 +                            detailsFragmentChanged = true;
                          } else {
                              getFileOperationsHelper().openFile(mWaitingToPreview);
                          }
      public boolean onOptionsItemSelected(MenuItem item) {
          boolean retval = true;
          switch (item.getItemId()) {
 -        case R.id.action_create_dir: {
 -            CreateFolderDialogFragment dialog = 
 -                    CreateFolderDialogFragment.newInstance(getCurrentDir());
 -            dialog.show(getSupportFragmentManager(), "createdirdialog");
 -            break;
 -        }
 -        case R.id.action_sync_account: {
 -            startSynchronization();
 -            break;
 -        }
 -        case R.id.action_upload: {
 -            showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
 -            break;
 -        }
 -        case R.id.action_settings: {
 -            Intent settingsIntent = new Intent(this, Preferences.class);
 -            startActivity(settingsIntent);
 -            break;
 -        }
 -        case R.id.action_logger: {
 -            Intent loggerIntent = new Intent(getApplicationContext(),LogHistoryActivity.class);
 -            startActivity(loggerIntent);
 -            break;
 -        }
 -        case android.R.id.home: {
 -            FileFragment second = getSecondFragment();
 -            OCFile currentDir = getCurrentDir();
 -            if((currentDir != null && currentDir.getParentId() != 0) || 
 -                    (second != null && second.getFile() != null)) {                
 -                onBackPressed(); 
 -                
 +            case R.id.action_create_dir: {
 +                CreateFolderDialogFragment dialog =
 +                        CreateFolderDialogFragment.newInstance(getCurrentDir());
 +                dialog.show(getSupportFragmentManager(), "createdirdialog");
 +                break;
              }
 -            break;
 -        }
 -        case R.id.action_sort: {
 -            SharedPreferences appPreferences = PreferenceManager
 -                    .getDefaultSharedPreferences(this);
 -            
 -            // Read sorting order, default to sort by name ascending
 -            Integer sortOrder = appPreferences
 -                    .getInt("sortOrder", FileListListAdapter.SORT_NAME);
 -            
 -            AlertDialog.Builder builder = new AlertDialog.Builder(this);
 -            builder.setTitle(R.string.actionbar_sort_title)
 -            .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder , new DialogInterface.OnClickListener() {
 -                public void onClick(DialogInterface dialog, int which) {
 -                    
 -                    switch (which){
 -                    case 0:
 -                        sortByName(true);
 -                        break;
 -                    case 1:
 -                        sortByDate(false);
 -                        break;
 -                        
 +            case R.id.action_sort: {
 +                SharedPreferences appPreferences = PreferenceManager
 +                        .getDefaultSharedPreferences(this);
 +
 +                // Read sorting order, default to sort by name ascending
 +                Integer sortOrder = appPreferences
 +                        .getInt("sortOrder", FileListListAdapter.SORT_NAME);
 +
 +                AlertDialog.Builder builder = new AlertDialog.Builder(this);
 +                builder.setTitle(R.string.actionbar_sort_title)
 +                        .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder, new DialogInterface.OnClickListener() {
 +                            public void onClick(DialogInterface dialog, int which) {
 +
 +                                switch (which) {
 +                                    case 0:
 +                                        sortByName(true);
 +                                        break;
 +                                    case 1:
 +                                        sortByDate(false);
 +                                        break;
 +
  // TODO re-enable when server-side folder size calculation is available                       
  //                    case 2:
  //                        sortBySize(false);
  //                        break;
 -                    }
 -                    
 -                    dialog.dismiss();
 -                    
 +                                }
 +
 +                                dialog.dismiss();
 +
 +                            }
 +                        });
 +                builder.create().show();
 +                break;
 +            }
 +            case R.id.action_sync_account: {
 +                startSynchronization();
 +                break;
 +            }
 +            case R.id.action_upload: {
 +                showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
 +                break;
 +            }
 +            case R.id.action_settings: {
 +                Intent settingsIntent = new Intent(this, Preferences.class);
 +                startActivity(settingsIntent);
 +                break;
 +            }
 +            case R.id.action_logger: {
 +                Intent loggerIntent = new Intent(getApplicationContext(), LogHistoryActivity.class);
 +                startActivity(loggerIntent);
 +                break;
 +            }
 +            case android.R.id.home: {
 +                FileFragment second = getSecondFragment();
 +                OCFile currentDir = getCurrentDir();
 +                if ((currentDir != null && currentDir.getParentId() != 0) ||
 +                        (second != null && second.getFile() != null)) {
 +                    onBackPressed();
 +
                  }
 -            });
 -            builder.create().show();
 -            break;
 -        }
 -        default:
 -            retval = super.onOptionsItemSelected(item);
 +                break;
 +            }
 +            default:
 +                retval = super.onOptionsItemSelected(item);
          }
          return retval;
      }
              builder.setExpedited(true);
              builder.setManual(true);
              builder.syncOnce();
+             // Fix bug in Android Lollipop when you click on refresh the whole account
+             Bundle extras = new Bundle();
+             builder.setExtras(extras);
              SyncRequest request = builder.build();
              ContentResolver.requestSync(request);
          }
      public boolean onNavigationItemSelected(int itemPosition, long itemId) {
          if (itemPosition != 0) {
              String targetPath = "";
 -            for (int i=itemPosition; i < mDirectories.getCount() - 1; i++) {
 -                targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath; 
 +            for (int i = itemPosition; i < mDirectories.getCount() - 1; i++) {
 +                targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath;
              }
              targetPath = OCFile.PATH_SEPARATOR + targetPath;
              OCFile targetFolder = getStorageManager().getFileByPath(targetPath);
              if (targetFolder != null) {
                  browseTo(targetFolder);
              }
 -            
 +
              // the next operation triggers a new call to this method, but it's necessary to 
              // ensure that the name exposed in the action bar is the current directory when the 
              // user selected it in the navigation list
 -            if (getSupportActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST  && itemPosition != 0) 
 +            if (getSupportActionBar().getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST && itemPosition != 0)
                  getSupportActionBar().setSelectedNavigationItem(0);
          }
          return true;
          } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
              requestMultipleUpload(data, resultCode);
  
 -        } else if (requestCode == ACTION_MOVE_FILES && (resultCode == RESULT_OK || 
 -                resultCode == MoveActivity.RESULT_OK_AND_MOVE)){
 +        } else if (requestCode == ACTION_MOVE_FILES && (resultCode == RESULT_OK ||
 +                resultCode == MoveActivity.RESULT_OK_AND_MOVE)) {
  
              final Intent fData = data;
 -            final int fResultCode = resultCode; 
 +            final int fResultCode = resultCode;
              getHandler().postDelayed(
 -                new Runnable() {
 -                    @Override
 -                    public void run() {
 -                        requestMoveOperation(fData, fResultCode);
 -                    }
 -                }, 
 -                DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS
 +                    new Runnable() {
 +                        @Override
 +                        public void run() {
 +                            requestMoveOperation(fData, fResultCode);
 +                        }
 +                    },
 +                    DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS
              );
          }
      }
              }
              if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR))
                  remotePathBase += OCFile.PATH_SEPARATOR;
 -            for (int j = 0; j< remotePaths.length; j++) {
 +            for (int j = 0; j < remotePaths.length; j++) {
                  remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName();
              }
  
  
      private void requestSimpleUpload(Intent data, int resultCode) {
          String filepath = null;
+         String mimeType = null;
+         Uri selectedImageUri = data.getData();
          try {
-             Uri selectedImageUri = data.getData();
+             mimeType = getContentResolver().getType(selectedImageUri);
  
              String filemanagerstring = selectedImageUri.getPath();
              String selectedImagePath = getPath(selectedImageUri);
          }
          if (!remotepath.endsWith(OCFile.PATH_SEPARATOR))
              remotepath += OCFile.PATH_SEPARATOR;
-         remotepath += new File(filepath).getName();
+         if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) {
+             Cursor cursor = MainApp.getAppContext().getContentResolver()
+                     .query(Uri.parse(filepath), null, null, null, null, null);
+             try {
+                 if (cursor != null && cursor.moveToFirst()) {
+                     String displayName = cursor.getString(
+                             cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+                     Log.i(TAG, "Display Name: " + displayName + "; mimeType: " + mimeType);
+                     displayName.replace(File.separatorChar, '_');
+                     displayName.replace(File.pathSeparatorChar, '_');
+                     remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath);
+                 }
+             } finally {
+                 cursor.close();
+             }
+         } else {
+             remotepath += new File(filepath).getName();
+         }
  
          i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath);
          i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath);
+         i.putExtra(FileUploader.KEY_MIME_TYPE, mimeType);
          i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
          if (resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)
              i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
  
      /**
       * Request the operation for moving the file/folder from one path to another
 -     * 
 -     * @param data              Intent received
 -     * @param resultCode        Result code received
 +     *
 +     * @param data       Intent received
 +     * @param resultCode Result code received
       */
      private void requestMoveOperation(Intent data, int resultCode) {
          OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(MoveActivity.EXTRA_CURRENT_FOLDER);
  
      @Override
      public void onBackPressed() {
 -        OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +        OCFileListFragment listOfFiles = getListOfFilesFragment();
          if (mDualPane || getSecondFragment() == null) {
              if (listOfFiles != null) {  // should never be null, indeed
                  if (mDirectories.getCount() <= 1) {
                      return;
                  }
                  int levelsUp = listOfFiles.onBrowseUp();
 -                for (int i=0; i < levelsUp && mDirectories.getCount() > 1 ; i++) {
 +                for (int i = 0; i < levelsUp && mDirectories.getCount() > 1; i++) {
                      popDirname();
                  }
              }
  
          Log_OC.d(TAG, "onSaveInstanceState() end");
      }
 -    
  
  
      @Override
      protected void onResume() {
          super.onResume();
          Log_OC.e(TAG, "onResume() start");
 -        
 +
          // refresh list of files
          refreshListOfFilesFragment();
  
          downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage());
          mDownloadFinishReceiver = new DownloadFinishReceiver();
          registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
 -        
 +
          Log_OC.d(TAG, "onResume() end");
      }
  
              unregisterReceiver(mDownloadFinishReceiver);
              mDownloadFinishReceiver = null;
          }
 -        
 -        
 +
 +
          Log_OC.d(TAG, "onPause() end");
          super.onPause();
      }
          Dialog dialog = null;
          AlertDialog.Builder builder;
          switch (id) {
 -        case DIALOG_SHORT_WAIT: {
 -            ProgressDialog working_dialog = new ProgressDialog(this);
 -            working_dialog.setMessage(getResources().getString(
 -                    R.string.wait_a_moment));
 -            working_dialog.setIndeterminate(true);
 -            working_dialog.setCancelable(false);
 -            dialog = working_dialog;
 -            break;
 -        }
 -        case DIALOG_CHOOSE_UPLOAD_SOURCE: {
 -
 -
 -            String[] allTheItems = { getString(R.string.actionbar_upload_files),
 -                    getString(R.string.actionbar_upload_from_apps) };
 -
 -            builder = new AlertDialog.Builder(this);
 -            builder.setTitle(R.string.actionbar_upload);
 -            builder.setItems(allTheItems, new DialogInterface.OnClickListener() {
 -                public void onClick(DialogInterface dialog, int item) {
 -                    if (item == 0) {
 -                        // if (!mDualPane) {
 +            case DIALOG_SHORT_WAIT: {
 +                ProgressDialog working_dialog = new ProgressDialog(this);
 +                working_dialog.setMessage(getResources().getString(
 +                        R.string.wait_a_moment));
 +                working_dialog.setIndeterminate(true);
 +                working_dialog.setCancelable(false);
 +                dialog = working_dialog;
 +                break;
 +            }
 +            case DIALOG_CHOOSE_UPLOAD_SOURCE: {
 +
 +
 +                String[] allTheItems = {getString(R.string.actionbar_upload_files),
 +                        getString(R.string.actionbar_upload_from_apps)};
 +
 +                builder = new AlertDialog.Builder(this);
 +                builder.setTitle(R.string.actionbar_upload);
 +                builder.setItems(allTheItems, new DialogInterface.OnClickListener() {
 +                    public void onClick(DialogInterface dialog, int item) {
 +                        if (item == 0) {
 +                            // if (!mDualPane) {
                              Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class);
                              action.putExtra(UploadFilesActivity.EXTRA_ACCOUNT, FileDisplayActivity.this.getAccount());
                              startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES);
                              // TODO create and handle new fragment
                              // LocalFileListFragment
                              // }
 -                    } else if (item == 1) {
 -                        Intent action = new Intent(Intent.ACTION_GET_CONTENT);
 -                        action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
 -                        startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
 -                                ACTION_SELECT_CONTENT_FROM_APPS);
 +                        } else if (item == 1) {
 +                            Intent action = new Intent(Intent.ACTION_GET_CONTENT);
 +                            action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
 +                            startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
 +                                    ACTION_SELECT_CONTENT_FROM_APPS);
 +                        }
                      }
 -                }
 -            });
 -            dialog = builder.create();
 -            break;
 -        }
 -        case DIALOG_CERT_NOT_SAVED: {
 -            builder = new AlertDialog.Builder(this);
 -            builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
 -            builder.setCancelable(false);
 -            builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
 -                @Override
 -                public void onClick(DialogInterface dialog, int which) {
 -                    dialog.dismiss();
 -                };
 -            });
 -            dialog = builder.create();
 -            break;
 -        }
 -        default:
 -            dialog = null;
 +                });
 +                dialog = builder.create();
 +                break;
 +            }
 +            case DIALOG_CERT_NOT_SAVED: {
 +                builder = new AlertDialog.Builder(this);
 +                builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
 +                builder.setCancelable(false);
 +                builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
 +                    @Override
 +                    public void onClick(DialogInterface dialog, int which) {
 +                        dialog.dismiss();
 +                    }
 +
 +                    ;
 +                });
 +                dialog = builder.create();
 +                break;
 +            }
 +            default:
 +                dialog = null;
          }
  
          return dialog;
      }
  
      /**
 -     * Translates a content URI of an content to a physical path on the disk
 -     * 
 +     * Translates a content URI of an image to a physical path
 +     * on the disk
 +     *
       * @param uri The URI to resolve
-      * @return The path to the image or null if it could not be found
+      * @return The path to the content or null if it could not be found
       */
      public String getPath(Uri uri) {
-         String[] projection = {MediaStore.Images.Media.DATA};
-         Cursor cursor = managedQuery(uri, projection, null, null, null);
-         if (cursor != null) {
-             int column_index = cursor
-                     .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
-             cursor.moveToFirst();
-             return cursor.getString(column_index);
+         final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+         // DocumentProvider
+         if (isKitKatOrLater && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) {
+             // ExternalStorageProvider
+             if (UriUtils.isExternalStorageDocument(uri)) {
+                 final String docId = DocumentsContract.getDocumentId(uri);
+                 final String[] split = docId.split(":");
+                 final String type = split[0];
+                 if ("primary".equalsIgnoreCase(type)) {
+                     return Environment.getExternalStorageDirectory() + "/" + split[1];
+                 }
+             }
+             // DownloadsProvider
+             else if (UriUtils.isDownloadsDocument(uri)) {
+                 final String id = DocumentsContract.getDocumentId(uri);
+                 final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
+                         Long.valueOf(id));
+                 return UriUtils.getDataColumn(getApplicationContext(), contentUri, null, null);
+             }
+             // MediaProvider
+             else if (UriUtils.isMediaDocument(uri)) {
+                 final String docId = DocumentsContract.getDocumentId(uri);
+                 final String[] split = docId.split(":");
+                 final String type = split[0];
+                 Uri contentUri = null;
+                 if ("image".equals(type)) {
+                     contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                 } else if ("video".equals(type)) {
+                     contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                 } else if ("audio".equals(type)) {
+                     contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                 }
+                 final String selection = "_id=?";
 -                final String[] selectionArgs = new String[] { split[1] };
++                final String[] selectionArgs = new String[]{split[1]};
+                 return UriUtils.getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs);
+             }
+             // Documents providers returned as content://...
+             else if (UriUtils.isContentDocument(uri)) {
+                 return uri.toString();
+             }
+         }
+         // MediaStore (and general)
+         else if ("content".equalsIgnoreCase(uri.getScheme())) {
+             // Return the remote address
+             if (UriUtils.isGooglePhotosUri(uri))
+                 return uri.getLastPathSegment();
+             return UriUtils.getDataColumn(getApplicationContext(), uri, null, null);
+         }
+         // File
+         else if ("file".equalsIgnoreCase(uri.getScheme())) {
+             return uri.getPath();
          }
          return null;
      }
  
      /**
       * Pushes a directory to the drop down list
 +     *
       * @param directory to push
       * @throws IllegalArgumentException If the {@link OCFile#isFolder()} returns false.
       */
      public void pushDirname(OCFile directory) {
 -        if(!directory.isFolder()){
 +        if (!directory.isFolder()) {
              throw new IllegalArgumentException("Only directories may be pushed!");
          }
          mDirectories.insert(directory.getFileName(), 0);
  
      /**
       * Pops a directory name from the drop down list
 +     *
       * @return True, unless the stack is empty
       */
      public boolean popDirname() {
  
              ((TextView) v).setTextColor(getResources().getColorStateList(
                      android.R.color.white));
 -            
 -            fixRoot((TextView) v );
 +
 +            fixRoot((TextView) v);
              return v;
          }
  
          public View getDropDownView(int position, View convertView,
 -                ViewGroup parent) {
 +                                    ViewGroup parent) {
              View v = super.getDropDownView(position, convertView, parent);
  
              ((TextView) v).setTextColor(getResources().getColorStateList(
                      android.R.color.white));
  
 -            fixRoot((TextView) v );
 +            fixRoot((TextView) v);
              return v;
          }
  
                  String event = intent.getAction();
                  Log_OC.d(TAG, "Received broadcast " + event);
                  String accountName = intent.getStringExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME);
 -                String synchFolderRemotePath = intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH); 
 -                RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncAdapter.EXTRA_RESULT);
 -                boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null); 
 -    
 +                String synchFolderRemotePath = intent.getStringExtra(FileSyncAdapter.EXTRA_FOLDER_PATH);
 +                RemoteOperationResult synchResult = (RemoteOperationResult) intent.getSerializableExtra(FileSyncAdapter.EXTRA_RESULT);
 +                boolean sameAccount = (getAccount() != null && accountName.equals(getAccount().name) && getStorageManager() != null);
 +
                  if (sameAccount) {
 -                    
 +
                      if (FileSyncAdapter.EVENT_FULL_SYNC_START.equals(event)) {
                          mSyncInProgress = true;
 -                        
 +
                      } else {
                          OCFile currentFile = (getFile() == null) ? null : getStorageManager().getFileByPath(getFile().getRemotePath());
                          OCFile currentDir = (getCurrentDir() == null) ? null : getStorageManager().getFileByPath(getCurrentDir().getRemotePath());
 -    
 +
                          if (currentDir == null) {
                              // current folder was removed from the server 
 -                            Toast.makeText( FileDisplayActivity.this, 
 -                                            String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)), 
 -                                            Toast.LENGTH_LONG)
 -                                .show();
 +                            Toast.makeText(FileDisplayActivity.this,
 +                                    String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)),
 +                                    Toast.LENGTH_LONG)
 +                                    .show();
                              browseToRoot();
 -                            
 +
                          } else {
                              if (currentFile == null && !getFile().isFolder()) {
                                  // currently selected file was removed in the server, and now we know it
                              }
                              setFile(currentFile);
                          }
 -                        
 +
                          mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
 -                                
 +
                          if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
 -                                    equals(event) &&
 +                                equals(event) &&
                                  /// TODO refactor and make common
 -                                synchResult != null && !synchResult.isSuccess() &&  
 -                                (synchResult.getCode() == ResultCode.UNAUTHORIZED   || 
 -                                    synchResult.isIdPRedirection()                  ||
 -                                    (synchResult.isException() && synchResult.getException() 
 -                                            instanceof AuthenticatorException))) {
 +                                synchResult != null && !synchResult.isSuccess() &&
 +                                (synchResult.getCode() == ResultCode.UNAUTHORIZED ||
 +                                        synchResult.isIdPRedirection() ||
 +                                        (synchResult.isException() && synchResult.getException()
 +                                                instanceof AuthenticatorException))) {
  
                              OwnCloudClient client = null;
                              try {
 -                                OwnCloudAccount ocAccount = 
 +                                OwnCloudAccount ocAccount =
                                          new OwnCloudAccount(getAccount(), context);
                                  client = (OwnCloudClientManagerFactory.getDefaultSingleton().
                                          removeClientFor(ocAccount));
                              } 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, 
 +                                                getAccount().type,
                                                  cred.getAuthToken()
                                          );
                                      } else {
                                      }
                                  }
                              }
 -                            
 +
                              requestCredentialsUpdate();
 -                            
 +
                          }
                      }
                      removeStickyBroadcast(intent);
                      setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);
  
                      setBackgroundText();
 -                        
 +
                  }
 -                
 +
                  if (synchResult != null) {
                      if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
                          mLastSslUntrustedServerResult = synchResult;
              }
          }
      }
 -    
 +
      /**
       * Show a text message on screen view for notifying user if content is
       * loading or folder is empty
      private class UploadFinishReceiver extends BroadcastReceiver {
          /**
           * Once the file upload has finished -> update view
 -         *  @author David A. Velasco
 +         *
 +         * @author David A. Velasco
           * {@link BroadcastReceiver} to enable upload feedback in UI
           */
          @Override
                  String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
                  boolean sameAccount = getAccount() != null && accountName.equals(getAccount().name);
                  OCFile currentDir = getCurrentDir();
 -                boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) && 
 +                boolean isDescendant = (currentDir != null) && (uploadedRemotePath != null) &&
                          (uploadedRemotePath.startsWith(currentDir.getRemotePath()));
 -                
 +
                  if (sameAccount && isDescendant) {
                      refreshListOfFilesFragment();
                  }
 -                
 +
                  boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);
                  boolean renamedInUpload = getFile().getRemotePath().
                          equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));
 -                boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) || 
 +                boolean sameFile = getFile().getRemotePath().equals(uploadedRemotePath) ||
                          renamedInUpload;
                  FileFragment details = getSecondFragment();
 -                boolean detailFragmentIsShown = (details != null && 
 +                boolean detailFragmentIsShown = (details != null &&
                          details instanceof FileDetailFragment);
 -                
 +
                  if (sameAccount && sameFile && detailFragmentIsShown) {
                      if (uploadWasFine) {
                          setFile(getStorageManager().getFileByPath(uploadedRemotePath));
                      if (renamedInUpload) {
                          String newName = (new File(uploadedRemotePath)).getName();
                          Toast msg = Toast.makeText(
 -                                context, 
 +                                context,
                                  String.format(
 -                                        getString(R.string.filedetails_renamed_in_upload_msg), 
 -                                        newName), 
 +                                        getString(R.string.filedetails_renamed_in_upload_msg),
 +                                        newName),
                                  Toast.LENGTH_LONG);
                          msg.show();
                      }
                      if (uploadWasFine || getFile().fileExists()) {
 -                        ((FileDetailFragment)details).updateFileDetails(false, true);
 +                        ((FileDetailFragment) details).updateFileDetails(false, true);
                      } else {
                          cleanSecondFragment();
                      }
 -                    
 -                    // Force the preview if the file is an image
 -                    if (uploadWasFine && PreviewImageFragment.canBePreviewed(getFile())) {
 -                        startImagePreview(getFile());
 -                    } // TODO what about other kind of previews?
 +
 +                    // Force the preview if the file is an image or text file
 +                    if (uploadWasFine) {
 +                        OCFile ocFile = getFile();
 +                        if (PreviewImageFragment.canBePreviewed(ocFile))
 +                            startImagePreview(getFile());
 +                        else if (PreviewTextFragment.canBePreviewed(ocFile))
 +                            startTextPreview(ocFile);
 +                        // TODO what about other kind of previews?
 +                    }
                  }
 -                
 +
              } finally {
                  if (intent != null) {
                      removeStickyBroadcast(intent);
                  }
              }
 -            
 +
          }
 -        
 +
      }
  
  
      /**
 -     * Class waiting for broadcast events from the {@link FielDownloader} service.
 -     * 
 +     * Class waiting for broadcast events from the {@link FileDownloader} service.
 +     * <p/>
       * Updates the UI when a download is started or finished, provided that it is relevant for the
       * current folder.
       */
                  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));
                  }
 -    
 +
                  if (mWaitingToSend != null) {
                      mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); // Update the file to send
 -                    if (mWaitingToSend.isDown()) { 
 +                    if (mWaitingToSend.isDown()) {
                          sendDownloadedFile();
                      }
                  }
 -            
 +
              } finally {
                  if (intent != null) {
                      removeStickyBroadcast(intent);
              return (accountName != null && getAccount() != null && accountName.equals(getAccount().name));
          }
      }
 -    
 -    
 +
 +
      public void browseToRoot() {
 -        OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +        OCFileListFragment listOfFiles = getListOfFilesFragment();
          if (listOfFiles != null) {  // should never be null, indeed
              while (mDirectories.getCount() > 1) {
                  popDirname();
          }
          cleanSecondFragment();
      }
 -    
 -    
 +
 +
      public void browseTo(OCFile folder) {
          if (folder == null || !folder.isFolder()) {
              throw new IllegalArgumentException("Trying to browse to invalid folder " + folder);
          }
 -        OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +        OCFileListFragment listOfFiles = getListOfFilesFragment();
          if (listOfFiles != null) {
              setNavigationListWithFolder(folder);
              listOfFiles.listDirectory(folder);
  
      /**
       * {@inheritDoc}
 -     * 
 +     * <p/>
       * Updates action bar and second fragment, if in dual pane mode.
       */
      @Override
      public void onBrowsedDownTo(OCFile directory) {
          pushDirname(directory);
          cleanSecondFragment();
 -        
 +
          // Sync Folder
          startSyncFolderOperation(directory, false);
 -        
 +
      }
  
      /**
 -     * Shows the information of the {@link OCFile} received as a 
 +     * Shows the information of the {@link OCFile} received as a
       * parameter in the second fragment.
 -     * 
 -     * @param file          {@link OCFile} whose details will be shown
 +     *
 +     * @param file {@link OCFile} whose details will be shown
       */
      @Override
      public void showDetails(OCFile file) {
       * TODO
       */
      private void updateNavigationElementsInActionBar(OCFile chosenFile) {
 -        ActionBar actionBar = getSupportActionBar(); 
 +        ActionBar actionBar = getSupportActionBar();
          if (chosenFile == null || mDualPane) {
              // only list of files - set for browsing through folders
              OCFile currentDir = getCurrentDir();
              boolean noRoot = (currentDir != null && currentDir.getParentId() != 0);
              actionBar.setDisplayHomeAsUpEnabled(noRoot);
 -            actionBar.setDisplayShowTitleEnabled(!noRoot); 
 +            actionBar.setDisplayShowTitleEnabled(!noRoot);
              if (!noRoot) {
                  actionBar.setTitle(getString(R.string.default_display_name_for_root_folder));
              }
          return new ListServiceConnection();
      }
  
 -    /** Defines callbacks for service binding, passed to bindService() */
 +    /**
 +     * Defines callbacks for service binding, passed to bindService()
 +     */
      private class ListServiceConnection implements ServiceConnection {
  
          @Override
                          if (!mWaitingToPreview.isDown()) {
                              requestForDownload();
                          }
 -                }
 +                    }
  
              } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
                  Log_OC.d(TAG, "Upload service connected");
                  return;
              }
              // a new chance to get the mDownloadBinder through getFileDownloadBinder() - THIS IS A MESS
 -            OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +            OCFileListFragment listOfFiles = getListOfFilesFragment();
              if (listOfFiles != null) {
                  listOfFiles.listDirectory();
              }
              FileFragment secondFragment = getSecondFragment();
              if (secondFragment != null && secondFragment instanceof FileDetailFragment) {
 -                FileDetailFragment detailFragment = (FileDetailFragment)secondFragment;
 +                FileDetailFragment detailFragment = (FileDetailFragment) secondFragment;
                  detailFragment.listenForTransferProgress();
                  detailFragment.updateFileDetails(false, false);
              }
                  mUploaderBinder = null;
              }
          }
 -    };    
 +    }
  
 +    ;
  
  
      /**
      /**
       * Updates the view associated to the activity after the finish of some operation over files
       * in the current account.
 -     * 
 -     * @param operation     Removal operation performed.
 -     * @param result        Result of the removal.
 +     *
 +     * @param operation Removal operation performed.
 +     * @param result    Result of the removal.
       */
      @Override
      public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
          super.onRemoteOperationFinish(operation, result);
 -        
 +
          if (operation instanceof RemoveFileOperation) {
 -            onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
 +            onRemoveFileOperationFinish((RemoveFileOperation) operation, result);
  
          } else if (operation instanceof RenameFileOperation) {
 -            onRenameFileOperationFinish((RenameFileOperation)operation, result);
 +            onRenameFileOperationFinish((RenameFileOperation) operation, result);
  
          } else if (operation instanceof SynchronizeFileOperation) {
 -            onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
 +            onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
  
          } else if (operation instanceof CreateFolderOperation) {
 -            onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
 -            
 +            onCreateFolderOperationFinish((CreateFolderOperation) operation, result);
 +
          } else if (operation instanceof CreateShareOperation) {
              onCreateShareOperationFinish((CreateShareOperation) operation, result);
 -            
 +
          } else if (operation instanceof UnshareLinkOperation) {
 -            onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result);
 -        
 +            onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result);
 +
          } else if (operation instanceof MoveFileOperation) {
 -            onMoveFileOperationFinish((MoveFileOperation)operation, result);
 +            onMoveFileOperationFinish((MoveFileOperation) operation, result);
          }
 -        
 +
      }
  
 -    
 +
      private void onCreateShareOperationFinish(CreateShareOperation operation, RemoteOperationResult result) {
          if (result.isSuccess()) {
              refreshShowDetails();
          }
      }
  
 -    
 +
      private void onUnshareLinkOperationFinish(UnshareLinkOperation operation, RemoteOperationResult result) {
          if (result.isSuccess()) {
              refreshShowDetails();
              refreshListOfFilesFragment();
 -            
 +
          } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND) {
              cleanSecondFragment();
              refreshListOfFilesFragment();
          }
      }
 -    
 +
      private void refreshShowDetails() {
          FileFragment details = getSecondFragment();
          if (details != null) {
              OCFile file = details.getFile();
              if (file != null) {
 -                file = getStorageManager().getFileByPath(file.getRemotePath()); 
 +                file = getStorageManager().getFileByPath(file.getRemotePath());
                  if (details instanceof PreviewMediaFragment) {
                      // Refresh  OCFile of the fragment
                      ((PreviewMediaFragment) details).updateFile(file);
 -                } else {
 +                } else if (details instanceof PreviewTextFragment) {
 +                    // Refresh  OCFile of the fragment
 +                    ((PreviewTextFragment) details).updateFile(file);
 +                } else
                      showDetails(file);
 -                } 
              }
              invalidateOptionsMenu();
 -        } 
 +        }
      }
 -    
 +
      /**
 -     * Updates the view associated to the activity after the finish of an operation trying to remove a 
 -     * file. 
 -     * 
 -     * @param operation     Removal operation performed.
 -     * @param result        Result of the removal.
 +     * Updates the view associated to the activity after the finish of an operation trying to remove a
 +     * file.
 +     *
 +     * @param operation Removal operation performed.
 +     * @param result    Result of the removal.
       */
      private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
          dismissLoadingDialog();
 -        
 -        Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
 -                Toast.LENGTH_LONG); 
 +
 +        Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
 +                Toast.LENGTH_LONG);
          msg.show();
 -        
 +
          if (result.isSuccess()) {
              OCFile removedFile = operation.getFile();
              FileFragment second = getSecondFragment();
              if (second != null && removedFile.equals(second.getFile())) {
                  if (second instanceof PreviewMediaFragment) {
 -                    ((PreviewMediaFragment)second).stopPreview(true);
 +                    ((PreviewMediaFragment) second).stopPreview(true);
                  }
                  setFile(getStorageManager().getFileById(removedFile.getParentId()));
                  cleanSecondFragment();
              }
          }
      }
 -    
 -    
 +
 +
      /**
 -     * Updates the view associated to the activity after the finish of an operation trying to move a 
 +     * Updates the view associated to the activity after the finish of an operation trying to move a
       * file.
 -     * 
 -     * @param operation     Move operation performed.
 -     * @param result        Result of the move operation.
 +     *
 +     * @param operation Move operation performed.
 +     * @param result    Result of the move operation.
       */
      private void onMoveFileOperationFinish(MoveFileOperation operation, RemoteOperationResult result) {
          if (result.isSuccess()) {
          } else {
              dismissLoadingDialog();
              try {
 -                Toast msg = Toast.makeText(FileDisplayActivity.this, 
 -                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
 -                        Toast.LENGTH_LONG); 
 +                Toast msg = Toast.makeText(FileDisplayActivity.this,
 +                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
 +                        Toast.LENGTH_LONG);
                  msg.show();
  
              } catch (NotFoundException e) {
 -                Log_OC.e(TAG, "Error while trying to show fail message " , e);
 +                Log_OC.e(TAG, "Error while trying to show fail message ", e);
              }
          }
      }
  
  
      /**
 -     * Updates the view associated to the activity after the finish of an operation trying to rename a 
 -     * file. 
 -     * 
 -     * @param operation     Renaming operation performed.
 -     * @param result        Result of the renaming.
 +     * Updates the view associated to the activity after the finish of an operation trying to rename a
 +     * file.
 +     *
 +     * @param operation Renaming operation performed.
 +     * @param result    Result of the renaming.
       */
      private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) {
          dismissLoadingDialog();
          if (result.isSuccess()) {
              FileFragment details = getSecondFragment();
              if (details != null) {
 -                if (details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) {
 +                if (details instanceof FileDetailFragment && renamedFile.equals(details.getFile())) {
                      ((FileDetailFragment) details).updateFileDetails(renamedFile, getAccount());
                      showDetails(renamedFile);
  
                  } else if (details instanceof PreviewMediaFragment && renamedFile.equals(details.getFile())) {
                      ((PreviewMediaFragment) details).updateFile(renamedFile);
                      if (PreviewMediaFragment.canBePreviewed(renamedFile)) {
 -                        int position = ((PreviewMediaFragment)details).getPosition();
 +                        int position = ((PreviewMediaFragment) details).getPosition();
                          startMediaPreview(renamedFile, position, true);
                      } else {
                          getFileOperationsHelper().openFile(renamedFile);
                      }
 +                } else if (details instanceof PreviewTextFragment && renamedFile.equals(details.getFile())) {
 +                    ((PreviewTextFragment) details).updateFile(renamedFile);
 +                    if (PreviewTextFragment.canBePreviewed(renamedFile)) {
 +                        startTextPreview(renamedFile);
 +                    } else {
 +                        getFileOperationsHelper().openFile(renamedFile);
 +                    }
                  }
              }
 -            
 +
              if (getStorageManager().getFileById(renamedFile.getParentId()).equals(getCurrentDir())) {
                  refreshListOfFilesFragment();
              }
  
          } else {
 -            Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
 -                    Toast.LENGTH_LONG); 
 +            Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
 +                    Toast.LENGTH_LONG);
              msg.show();
 -            
 +
              if (result.isSslRecoverableException()) {
                  mLastSslUntrustedServerResult = result;
                  showUntrustedCertDialog(mLastSslUntrustedServerResult);
                  i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, getAccount());
                  startActivity(i);
  
 -            } 
 -            
 +            }
 +
          } else {
              if (operation.transferWasRequested()) {
                  onTransferStateChanged(syncedFile, true, true);
 -                
 +
              } else {
 -                Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
 -                        Toast.LENGTH_LONG); 
 +                Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
 +                        Toast.LENGTH_LONG);
                  msg.show();
              }
          }
  
      /**
       * Updates the view associated to the activity after the finish of an operation trying create a new folder
 -     * 
 -     * @param operation     Creation operation performed.
 -     * @param result        Result of the creation.
 +     *
 +     * @param operation Creation operation performed.
 +     * @param result    Result of the creation.
       */
      private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) {
          if (result.isSuccess()) {
          } else {
              dismissLoadingDialog();
              try {
 -                Toast msg = Toast.makeText(FileDisplayActivity.this, 
 -                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
 -                        Toast.LENGTH_LONG); 
 +                Toast msg = Toast.makeText(FileDisplayActivity.this,
 +                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
 +                        Toast.LENGTH_LONG);
                  msg.show();
  
              } catch (NotFoundException e) {
 -                Log_OC.e(TAG, "Error while trying to show fail message " , e);
 +                Log_OC.e(TAG, "Error while trying to show fail message ", e);
              }
          }
      }
  
 -    
 +
      /**
       * {@inheritDoc}
       */
      public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) {
          refreshListOfFilesFragment();
          FileFragment details = getSecondFragment();
 -        if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) {
 +        if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile())) {
              if (downloading || uploading) {
 -                ((FileDetailFragment)details).updateFileDetails(file, getAccount());
 +                ((FileDetailFragment) details).updateFileDetails(file, getAccount());
              } else {
                  if (!file.fileExists()) {
                      cleanSecondFragment();
                  } else {
 -                    ((FileDetailFragment)details).updateFileDetails(false, true);
 +                    ((FileDetailFragment) details).updateFileDetails(false, true);
                  }
              }
          }
 -            
 +
      }
  
  
          }
          return null;
      }
 -    
 +
      public void startSyncFolderOperation(OCFile folder, boolean ignoreETag) {
 -        long currentSyncTime = System.currentTimeMillis(); 
 -        
 +        long currentSyncTime = System.currentTimeMillis();
 +
          mSyncInProgress = true;
 -                
 +
          // perform folder synchronization
 -        RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
 -                                                                        currentSyncTime, 
 -                                                                        false,
 -                                                                        getFileOperationsHelper().isSharedSupported(),
 -                                                                        ignoreETag,
 -                                                                        getStorageManager(), 
 -                                                                        getAccount(), 
 -                                                                        getApplicationContext()
 -                                                                      );
 +        RemoteOperation synchFolderOp = new SynchronizeFolderOperation(folder,
 +                currentSyncTime,
 +                false,
 +                getFileOperationsHelper().isSharedSupported(),
 +                ignoreETag,
 +                getStorageManager(),
 +                getAccount(),
 +                getApplicationContext()
 +        );
          synchFolderOp.execute(getAccount(), this, null, null);
 -        
 +
          setSupportProgressBarIndeterminateVisibility(true);
  
          setBackgroundText();
      }
  
      /**
 -     * Show untrusted cert dialog 
 +     * Show untrusted cert dialog
       */
      public void showUntrustedCertDialog(RemoteOperationResult result) {
          // Show a dialog with the certificate info
 -        SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException)result.getException());
 +        SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException) result.getException());
          FragmentManager fm = getSupportFragmentManager();
          FragmentTransaction ft = fm.beginTransaction();
          dialog.show(ft, DIALOG_UNTRUSTED_CERT);
      }
 -    
 +
      private void requestForDownload(OCFile file) {
          Account account = getAccount();
          if (!mDownloaderBinder.isDownloading(account, file)) {
              startService(i);
          }
      }
 -    
 -    private void sendDownloadedFile(){
 +
 +    private void sendDownloadedFile() {
          getFileOperationsHelper().sendDownloadedFile(mWaitingToSend);
          mWaitingToSend = null;
      }
  
 -    
 +
      /**
       * Requests the download of the received {@link OCFile} , updates the UI
       * to monitor the download progress and prepares the activity to send the file
       * when the download finishes.
 -     * 
 -     * @param file          {@link OCFile} to download and preview.
 +     *
 +     * @param file {@link OCFile} to download and preview.
       */
      public void startDownloadForSending(OCFile file) {
          mWaitingToSend = file;
          requestForDownload(mWaitingToSend);
 -        boolean hasSecondFragment = (getSecondFragment()!= null);
 +        boolean hasSecondFragment = (getSecondFragment() != null);
          updateFragmentsVisibility(hasSecondFragment);
      }
 -    
 +
      /**
       * Opens the image gallery showing the image {@link OCFile} received as parameter.
 -     * 
 -     * @param file                      Image {@link OCFile} to show.
 +     *
 +     * @param file Image {@link OCFile} to show.
       */
      public void startImagePreview(OCFile file) {
          Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class);
          showDetailsIntent.putExtra(EXTRA_FILE, file);
          showDetailsIntent.putExtra(EXTRA_ACCOUNT, getAccount());
          startActivity(showDetailsIntent);
 -        
      }
  
      /**
       * Stars the preview of an already down media {@link OCFile}.
 -     * 
 -     * @param file                      Media {@link OCFile} to preview.
 -     * @param startPlaybackPosition     Media position where the playback will be started, in milliseconds.
 -     * @param autoplay                  When 'true', the playback will start without user interactions.
 +     *
 +     * @param file                  Media {@link OCFile} to preview.
 +     * @param startPlaybackPosition Media position where the playback will be started, in milliseconds.
 +     * @param autoplay              When 'true', the playback will start without user interactions.
       */
      public void startMediaPreview(OCFile file, int startPlaybackPosition, boolean autoplay) {
          Fragment mediaFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay);
      }
  
      /**
 +     * Stars the preview of a text file {@link OCFile}.
 +     *
 +     * @param file Text {@link OCFile} to preview.
 +     */
 +    public void startTextPreview(OCFile file) {
 +        Bundle args = new Bundle();
 +        args.putParcelable(EXTRA_FILE, file);
 +        args.putParcelable(EXTRA_ACCOUNT, getAccount());
 +        Fragment textPreviewFragment = Fragment.instantiate(getApplicationContext(), PreviewTextFragment.class.getName(), args);
 +        setSecondFragment(textPreviewFragment);
 +        updateFragmentsVisibility(true);
 +        updateNavigationElementsInActionBar(file);
 +        setFile(file);
 +    }
 +
 +    /**
       * Requests the download of the received {@link OCFile} , updates the UI
       * to monitor the download progress and prepares the activity to preview
       * or open the file when the download finishes.
 -     * 
 -     * @param file          {@link OCFile} to download and preview.
 +     *
 +     * @param file {@link OCFile} to download and preview.
       */
      public void startDownloadForPreview(OCFile file) {
          Fragment detailFragment = new FileDetailFragment(file, getAccount());
  
      public void cancelTransference(OCFile file) {
          getFileOperationsHelper().cancelTransference(file);
 -        if (mWaitingToPreview != null && 
 +        if (mWaitingToPreview != null &&
                  mWaitingToPreview.getRemotePath().equals(file.getRemotePath())) {
              mWaitingToPreview = null;
          }
          }
      }
  
 -    private void sortByDate(boolean ascending){
 +    private void sortByDate(boolean ascending) {
          getListOfFilesFragment().sortByDate(ascending);
      }
  
 -    private void sortBySize(boolean ascending){
 +    private void sortBySize(boolean ascending) {
          getListOfFilesFragment().sortBySize(ascending);
      }
  
 -    private void sortByName(boolean ascending){
 +    private void sortByName(boolean ascending) {
          getListOfFilesFragment().sortByName(ascending);
      }
  }