Merge remote-tracking branch 'remotes/upstream/switchOfflineFiles' into beta
authortobiasKaminsky <tobias@kaminsky.me>
Thu, 29 Oct 2015 17:29:35 +0000 (18:29 +0100)
committertobiasKaminsky <tobias@kaminsky.me>
Thu, 29 Oct 2015 17:29:35 +0000 (18:29 +0100)
1  2 
res/values/strings.xml
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/FolderPickerActivity.java
src/com/owncloud/android/ui/activity/Uploader.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java

diff --combined res/values/strings.xml
@@@ -23,8 -23,7 +23,7 @@@
      <!-- TODO re-enable when "Accounts" is available in Navigation Drawer -->
      <!--<string name="drawer_item_accounts">Accounts</string>-->
      <string name="drawer_item_all_files">All files</string>
-     <!-- TODO re-enable when "On Device" is available
-     <string name="drawer_item_on_device">On device</string>-->
+     <string name="drawer_item_on_device">On device</string>
      <string name="drawer_item_settings">Settings</string>
      <string name="drawer_item_logs">Logs</string>
        <string name="drawer_close">Close</string>
      <string name="placeholder_filesize">389 KB</string>
      <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
      <string name="placeholder_media_time">12:23:45</string>
 -
 -    <string name="instant_upload_on_wifi">Upload pictures via WiFi only</string>
 -    <string name="instant_video_upload_on_wifi">Upload videos via WiFi only</string>
 +    
 +    <string name="instant_upload_on_wifi">Upload pictures via wifi only</string>
 +    <string name="instant_upload_on_charging">Upload when charging only</string>
 +    <string name="instant_video_upload_on_wifi">Upload videos via wifi only</string>
 +    <string name="instant_video_upload_on_charging">Upload when charging only</string>
      <string name="instant_upload_path">/InstantUpload</string>
      <string name="conflict_title">File conflict</string>
      <string name="conflict_message">Which files do you want to keep? If you select both versions, the local file will have a number added to its name.</string>
      <string name="preview_image_error_unknown_format">This image cannot be shown</string>
  
      <string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local folder</string>
 -    <string name="prefs_instant_upload_path_title">Upload Path</string>
 +    <string name="prefs_instant_upload_path_title">Upload path</string>
  
        <string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your
                administrator.</string>
      <string name="prefs_category_instant_uploading">Instant Uploads</string>
        <string name="prefs_category_security">Security</string>
  
 -      <string name="prefs_instant_video_upload_path_title">Upload Video Path</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="shared_subject_header">shared</string>
      <string name="file_list__footer__files">%1$d files</string>
      <string name="file_list__footer__files_and_folder">%1$d files, 1 folder</string>
      <string name="file_list__footer__files_and_folders">%1$d files, %2$d folders</string>
 -
 +    <string name="action_switch_grid_view">Switch to grid view</string>
 +    <string name="action_switch_list_view">Switch to list view</string>
  </resources>
@@@ -363,7 -363,12 +363,7 @@@ public class FileActivity extends AppCo
  //        }
  
          // Display username in drawer
 -        Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
 -        if (account != null) {
 -            TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
 -            int lastAtPos = account.name.lastIndexOf("@");
 -            username.setText(account.name.substring(0, lastAtPos));
 -        }
 +        setUsernameInDrawer(navigationDrawerLayout, AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()));
  
          // load slide menu items
          mDrawerTitles = getResources().getStringArray(R.array.drawer_items);
          mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[0], mDrawerContentDescriptions[0],
                  R.drawable.ic_folder_open));
  
-         // TODO Enable when "On Device" is recovered
          // On Device
-         //mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[2],
-         //        mDrawerContentDescriptions[2]));
+         mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[1], mDrawerContentDescriptions[1],
+                 R.drawable.ic_action_download_grey));
  
          // Settings
-         mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[1], mDrawerContentDescriptions[1],
-                 R.drawable.ic_settings));
+         mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[2], mDrawerContentDescriptions[2],
+                 R.drawable.ic_action_settings));
          // Logs
          if (BuildConfig.DEBUG) {
-             mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[2],
-                     mDrawerContentDescriptions[2],R.drawable.ic_log));
+             mDrawerItems.add(new NavigationDrawerItem(mDrawerTitles[3],
+                     mDrawerContentDescriptions[3],R.drawable.ic_log));
          }
  
          // setting the nav drawer list adapter
      }
  
      /**
 +     * sets the given account name in the drawer in case the drawer is available. The account name
 +     * is shortened beginning from the @-sign in the username.
 +     *
 +     * @param navigationDrawerLayout the drawer layout to be used
 +     * @param account                the account to be set in the drawer
 +     */
 +    protected void setUsernameInDrawer(RelativeLayout navigationDrawerLayout, Account account) {
 +        if (navigationDrawerLayout != null && getAccount() != null) {
 +            TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
 +            int lastAtPos = account.name.lastIndexOf("@");
 +            username.setText(account.name.substring(0, lastAtPos));
 +        }
 +    }
 +
 +    /**
       * Updates title bar and home buttons (state and icon).
       *
       * Assumes that navigation drawer is NOT visible.
          startActivity(i);
      }
  
+     public void refresh(){
+         Intent i = new Intent(this, FileDisplayActivity.class);
+         i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+         startActivity(i);
+     }
  //    TODO re-enable when "Accounts" is available in Navigation Drawer
  //    public void closeDrawer() {
  //        mDrawerLayout.closeDrawers();
          restart();
      }
  
+     public void refreshDirectory(){
+         // overridden by FileDisplayActivity
+     }
      private class DrawerItemClickListener implements ListView.OnItemClickListener {
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  //                    break;
  
                  case 0: // All Files
-                     allFilesOption();
+                     MainApp.showOnlyFilesOnDevice(false);
+                     refreshDirectory();
                      mDrawerLayout.closeDrawers();
                      break;
  
-                 // TODO Enable when "On Device" is recovered ?
- //                case 2:
//                    MainApp.showOnlyFilesOnDevice(true);
//                    mDrawerLayout.closeDrawers();
//                    break;
+                 case 1: // On Device
+                     MainApp.showOnlyFilesOnDevice(true);
                    refreshDirectory();
+                     mDrawerLayout.closeDrawers();
+                     break;
  
-                 case 1: // Settings
+                 case 2: // Settings
                      Intent settingsIntent = new Intent(getApplicationContext(),
                              Preferences.class);
                      startActivity(settingsIntent);
                      mDrawerLayout.closeDrawers();
                      break;
  
-                 case 2: // Logs
+                 case 3: // Logs
                      Intent loggerIntent = new Intent(getApplicationContext(),
                              LogHistoryActivity.class);
                      startActivity(loggerIntent);
@@@ -149,14 -149,13 +149,14 @@@ public class FileDisplayActivity extend
      private boolean mSyncInProgress = false;
  
      private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT";
 -    private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
 +    public static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
      private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE";
      private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED";
  
      private OCFile mWaitingToSend;
 +    private Menu mOptionsMenu;
 +
  
 -    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          Log_OC.v(TAG, "onCreate() start");
              setFile(file);
  
              if (mAccountWasSet) {
 -                RelativeLayout navigationDrawerLayout = (RelativeLayout) findViewById(R.id.left_drawer);
 -                if (navigationDrawerLayout != null && getAccount() != null) {
 -                    TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
 -                    int lastAtPos = getAccount().name.lastIndexOf("@");
 -                    username.setText(getAccount().name.substring(0, lastAtPos));
 -                }
 +                setUsernameInDrawer((RelativeLayout) findViewById(R.id.left_drawer), getAccount());
              }
  
              if (!stateWasRecovered) {
              /// First fragment
              OCFileListFragment listOfFiles = getListOfFilesFragment();
              if (listOfFiles != null) {
-                 listOfFiles.listDirectory(getCurrentDir());
-                 // TODO Enable when "On Device" is recovered
-                 // listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice());
+                 listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice());
              } else {
                  Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >(");
              }
                      startTextPreview(file);
              }
  
 +            if (DisplayUtils.isGridView(getFile(), getStorageManager())){
 +                switchToGridView();
 +            } else {
 +                switchToListView();
 +            }
 +
          } else {
              Log_OC.wtf(TAG, "initFragments() called with invalid NULLs!");
              if (getAccount() == null) {
      protected void refreshListOfFilesFragment() {
          OCFileListFragment fileListFragment = getListOfFilesFragment();
          if (fileListFragment != null) {
-             fileListFragment.listDirectory();
-             // TODO Enable when "On Device" is recovered ?
-             // fileListFragment.listDirectory(MainApp.getOnlyOnDevice());
+             fileListFragment.listDirectory(MainApp.getOnlyOnDevice());
          }
      }
  
      @Override
      public boolean onPrepareOptionsMenu(Menu menu) {
          boolean drawerOpen = mDrawerLayout.isDrawerOpen(GravityCompat.START);
 -        menu.findItem(R.id.action_upload).setVisible(!drawerOpen);
 -        menu.findItem(R.id.action_create_dir).setVisible(!drawerOpen);
          menu.findItem(R.id.action_sort).setVisible(!drawerOpen);
          menu.findItem(R.id.action_sync_account).setVisible(!drawerOpen);
 +        menu.findItem(R.id.action_switch_view).setVisible(!drawerOpen);
          
          return super.onPrepareOptionsMenu(menu);
      }
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.main_menu, menu);
 +        menu.findItem(R.id.action_create_dir).setVisible(false);
 +        mOptionsMenu = menu;
 +
 +        MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view);
 +
 +        changeGridIcon();
 +
          return true;
      }
      
      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(), DIALOG_CREATE_FOLDER);
 -                break;
 -            }
 -
              case R.id.action_sync_account: {
                  startSynchronization();
                  break;
              }
 -            case R.id.action_upload: {
 -                UploadSourceDialogFragment dialog =
 -                        UploadSourceDialogFragment.newInstance(getAccount());
 -                dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE);
 -                break;
 -            }
              case android.R.id.home: {
                  FileFragment second = getSecondFragment();
                  OCFile currentDir = getCurrentDir();
                  builder.create().show();
                  break;
              }
 +            case R.id.action_switch_view:{
 +                if (isGridView()){
 +                    item.setTitle(getApplicationContext().getString(R.string.action_switch_grid_view));
 +                    item.setIcon(ContextCompat.getDrawable(getApplicationContext(),
 +                            R.drawable.ic_view_module));
 +                    DisplayUtils.setViewMode(getFile(), false);
 +                    switchToListView();
 +                } else {
 +                    item.setTitle(getApplicationContext().getString(R.string.action_switch_list_view));
 +                    item.setIcon(ContextCompat.getDrawable(getApplicationContext(),
 +                            R.drawable.ic_view_list));
 +                    DisplayUtils.setViewMode(getFile(), true);
 +                    switchToGridView();
 +                }
 +
 +                return true;
 +            }
          default:
              retval = super.onOptionsItemSelected(item);
          }
          return retval;
      }
  
 +    public void createFolder() {
 +        CreateFolderDialogFragment dialog =
 +                CreateFolderDialogFragment.newInstance(getCurrentDir());
 +        dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER);
 +    }
 +
 +    public void uploadLocalFilesSelected() {
 +        Intent action = new Intent(this, UploadFilesActivity.class);
 +        action.putExtra(
 +                UploadFilesActivity.EXTRA_ACCOUNT,
 +                getAccount()
 +        );
 +        startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES);
 +    }
 +
 +    public void uploadFromOtherAppsSelected() {
 +        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
 +        );
 +    }
 +
      private void startSynchronization() {
          Log_OC.d(TAG, "Got to start sync");
          if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
  
      @Override
      public void onBackPressed() {
 -        if (!isDrawerOpen()){
 +        boolean isFabOpen = isFabOpen();
 +        boolean isDrawerOpen = isDrawerOpen();
 +
 +        /*
 +         * BackPressed priority/hierarchy:
 +         *    1. close drawer if opened
 +         *    2. close FAB if open (only if drawer isn't open)
 +         *    3. navigate up (only if drawer and FAB aren't open)
 +         */
 +        if(isDrawerOpen && isFabOpen) {
 +            // close drawer first
 +            super.onBackPressed();
 +        } else if(isDrawerOpen && !isFabOpen) {
 +            // close drawer
 +            super.onBackPressed();
 +        } else if (!isDrawerOpen && isFabOpen) {
 +            // close fab
 +            getListOfFilesFragment().getFabMain().collapse();
 +        } else {
 +            // all closed
              OCFileListFragment listOfFiles = getListOfFilesFragment();
              if (mDualPane || getSecondFragment() == null) {
                  OCFile currentDir = getCurrentDir();
                  setFile(listOfFiles.getCurrentFile());
              }
              cleanSecondFragment();
 +            changeGridIcon();
 +        }
 +    }
 +
 +    private void changeGridIcon(){
 +        MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view);
 +        if (DisplayUtils.isGridView(getFile(), getStorageManager())){
 +            menuItem.setTitle(getApplicationContext().getString(R.string.action_switch_list_view));
 +            menuItem.setIcon(ContextCompat.getDrawable(getApplicationContext(),
 +                    R.drawable.ic_view_list));
          } else {
 -            super.onBackPressed();
 +            menuItem.setTitle(getApplicationContext().getString(R.string.action_switch_grid_view));
 +            menuItem.setIcon(ContextCompat.getDrawable(getApplicationContext(),
 +                    R.drawable.ic_view_module));
          }
      }
  
          Log_OC.v(TAG, "onPause() end");
      }
  
 +    public boolean isFabOpen() {
 +        if(getListOfFilesFragment() != null && getListOfFilesFragment().getFabMain() != null && getListOfFilesFragment().getFabMain().isExpanded()) {
 +            return true;
 +        } else {
 +            return false;
 +        }
 +    }
 +
  
      private class SyncBroadcastReceiver extends BroadcastReceiver {
  
                                      currentDir.getRemotePath().equals(synchFolderRemotePath)) {
                                  OCFileListFragment fileListFragment = getListOfFilesFragment();
                                  if (fileListFragment != null) {
-                                     fileListFragment.listDirectory();
-                                     // TODO Enable when "On Device" is recovered ?
-                                     // fileListFragment.listDirectory(currentDir,
-                                     // MainApp.getOnlyOnDevice());
+                                     fileListFragment.listDirectory(currentDir,
+                                     MainApp.getOnlyOnDevice());
                                  }
                              }
                              setFile(currentFile);
          OCFileListFragment listOfFiles = getListOfFilesFragment();
          if (listOfFiles != null) {  // should never be null, indeed
              OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
-             listOfFiles.listDirectory(root);
-             // TODO Enable when "On Device" is recovered ?
-             // listOfFiles.listDirectory(root, MainApp.getOnlyOnDevice());
+             listOfFiles.listDirectory(root, MainApp.getOnlyOnDevice());
              setFile(listOfFiles.getCurrentFile());
              startSyncFolderOperation(root, false);
          }
          cleanSecondFragment();
          // Sync Folder
          startSyncFolderOperation(directory, false);
 +
 +        MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view);
 +
 +        changeGridIcon();
 +        if (DisplayUtils.isGridView(directory, getStorageManager())){
 +            switchToGridView();
 +        } else {
 +            switchToListView();
 +        }
      }
  
      /**
              // getFileDownloadBinder() - THIS IS A MESS
              OCFileListFragment listOfFiles = getListOfFilesFragment();
              if (listOfFiles != null) {
-                 listOfFiles.listDirectory();
-                 // TODO Enable when "On Device" is recovered ?
-                 // listOfFiles.listDirectory(MainApp.getOnlyOnDevice());
+                 listOfFiles.listDirectory(MainApp.getOnlyOnDevice());
              }
              FileFragment secondFragment = getSecondFragment();
              if (secondFragment != null && secondFragment instanceof FileDetailFragment) {
      private void sortByName(boolean ascending) {
          getListOfFilesFragment().sortByName(ascending);
      }
 +    private boolean isGridView(){ return getListOfFilesFragment().isGridView(); }
 +    private void switchToGridView() {
 +        getListOfFilesFragment().switchToGridView();
 +    }
 +    private void switchToListView() {
 +        getListOfFilesFragment().switchToListView();
 +    }
  
     public void allFilesOption() {
         browseToRoot();
     }
+     public void refreshDirectory(){
+         getListOfFilesFragment().refreshDirectory();
+     }
  }
@@@ -141,7 -141,7 +141,7 @@@ public class FolderPickerActivity exten
              
              if (!stateWasRecovered) {
                  OCFileListFragment listOfFolders = getListOfFilesFragment(); 
-                 listOfFolders.listDirectory(folder/*, false*/);
+                 listOfFolders.listDirectory(folder, false);
                  
                  startSyncFolderOperation(folder, false);
              }
          Bundle args = new Bundle();
          args.putBoolean(OCFileListFragment.ARG_JUST_FOLDERS, true);
          args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, false);
 +        args.putBoolean(OCFileListFragment.ARG_HIDE_FAB, true);
          listOfFiles.setArguments(args);
          FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
          transaction.add(R.id.fragment_container, listOfFiles, TAG_LIST_OF_FOLDERS);
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.main_menu, menu);
 -        menu.findItem(R.id.action_upload).setVisible(false);
          menu.findItem(R.id.action_sort).setVisible(false);
          return true;
      }
      protected void refreshListOfFilesFragment() {
          OCFileListFragment fileListFragment = getListOfFilesFragment();
          if (fileListFragment != null) {
-             fileListFragment.listDirectory();
-             // TODO Enable when "On Device" is recovered ?
-             // fileListFragment.listDirectory(false);
+             fileListFragment.listDirectory(false);
          }
      }
  
          OCFileListFragment listOfFiles = getListOfFilesFragment(); 
          if (listOfFiles != null) {  // should never be null, indeed
              OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
-             listOfFiles.listDirectory(root);
-             // TODO Enable when "On Device" is recovered ?
-             // listOfFiles.listDirectory(root, false);
+             listOfFiles.listDirectory(root, false);
              setFile(listOfFiles.getCurrentFile());
              updateNavigationElementsInActionBar();
              startSyncFolderOperation(root, false);
                                      equals(synchFolderRemotePath)) {
                                  OCFileListFragment fileListFragment = getListOfFilesFragment();
                                  if (fileListFragment != null) {
-                                     fileListFragment.listDirectory(currentDir);
-                                     // TODO Enable when "On Device" is recovered ?
-                                     // fileListFragment.listDirectory(currentDir, false);
+                                     fileListFragment.listDirectory(currentDir, false);
                                  }
                              }
                              setFile(currentFile);
@@@ -333,8 -333,7 +333,7 @@@ public class Uploader extends FileActiv
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          // click on folder in the list
          Log_OC.d(TAG, "on item click");
-         // TODO Enable when "On Device" is recovered ?
-         Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile /*, false*/);
+         Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile, false);
          if (tmpfiles.size() <= 0) return;
          // filter on dirtype
          Vector<OCFile> files = new Vector<OCFile>();
  
          mFile = getStorageManager().getFileByPath(full_path);
          if (mFile != null) {
-             // TODO Enable when "On Device" is recovered ?
-             Vector<OCFile> files = getStorageManager().getFolderContent(mFile/*, false*/);
+             Vector<OCFile> files = getStorageManager().getFolderContent(mFile, false);
              List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
              for (OCFile f : files) {
                  HashMap<String, Object> h = new HashMap<String, Object>();
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.main_menu, menu);
 -        menu.findItem(R.id.action_upload).setVisible(false);
          menu.findItem(R.id.action_sort).setVisible(false);
          menu.findItem(R.id.action_sync_account).setVisible(false);
          return true;
@@@ -194,7 -194,6 +194,7 @@@ public class FileListListAdapter extend
              switch (viewType){\r
                  case LIST_ITEM:\r
                      TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
 +                    TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator);\r
                      TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
                      ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
  \r
  \r
                      checkBoxV.setVisibility(View.GONE);\r
  \r
 +                    fileSizeSeparatorV.setVisibility(View.VISIBLE);\r
                      fileSizeV.setVisibility(View.VISIBLE);\r
                      fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
  \r
                              } else {\r
                                  if (parentList.isItemChecked(position)) {\r
                                      checkBoxV.setImageResource(\r
 -                                            android.R.drawable.checkbox_on_background);\r
 +                                            R.drawable.ic_checkbox_marked);\r
                                  } else {\r
                                      checkBoxV.setImageResource(\r
 -                                            android.R.drawable.checkbox_off_background);\r
 +                                            R.drawable.ic_checkbox_blank_outline);\r
                                  }\r
                                  checkBoxV.setVisibility(View.VISIBLE);\r
                              }\r
                          }\r
  \r
                      } else { //Folder\r
 +                        fileSizeSeparatorV.setVisibility(View.INVISIBLE);\r
                          fileSizeV.setVisibility(View.INVISIBLE);\r
                      }\r
  \r
                                      task\r
                                      );\r
                              fileIcon.setImageDrawable(asyncDrawable);\r
 -                            task.execute(file);\r
 +                            task.execute(file, true);\r
                          }\r
                      }\r
  \r
       *                                  mStorageManager if is different (and not NULL)\r
       */\r
      public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager\r
-             /*, boolean onlyOnDevice*/) {\r
+             , boolean onlyOnDevice) {\r
          mFile = directory;\r
          if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
              mStorageManager = updatedStorageManager;\r
              mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
          }\r
          if (mStorageManager != null) {\r
-             // TODO Enable when "On Device" is recovered ?\r
-             mFiles = mStorageManager.getFolderContent(mFile/*, onlyOnDevice*/);\r
+             mFiles = mStorageManager.getFolderContent(mFile, onlyOnDevice);\r
              mFilesOrig.clear();\r
              mFilesOrig.addAll(mFiles);\r
              \r
      public void setGridMode(boolean gridMode) {\r
          mGridMode = gridMode;\r
      }\r
 +\r
 +    public boolean isGridMode() {\r
 +        return mGridMode;\r
 +    }\r
  }\r
@@@ -24,10 -24,7 +24,10 @@@ package com.owncloud.android.ui.fragmen
  
  import android.app.Activity;
  import android.content.Intent;
 +import android.content.SharedPreferences;
 +import android.os.Build;
  import android.os.Bundle;
 +import android.preference.PreferenceManager;
  import android.support.v4.widget.SwipeRefreshLayout;
  import android.view.ContextMenu;
  import android.view.Menu;
@@@ -37,9 -34,8 +37,10 @@@ import android.view.View
  import android.widget.AdapterView;
  import android.widget.AdapterView.AdapterContextMenuInfo;
  import android.widget.PopupMenu;
 +import android.widget.TextView;
 +import android.widget.Toast;
  
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.datamodel.FileDataStorageManager;
@@@ -51,17 -47,13 +52,17 @@@ import com.owncloud.android.ui.activity
  import com.owncloud.android.ui.activity.FileDisplayActivity;
  import com.owncloud.android.ui.activity.FolderPickerActivity;
  import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
 +import com.owncloud.android.ui.activity.UploadFilesActivity;
  import com.owncloud.android.ui.adapter.FileListListAdapter;
  import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 +import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
  import com.owncloud.android.ui.dialog.FileActionsDialogFragment;
  import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
  import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 +import com.owncloud.android.ui.dialog.UploadSourceDialogFragment;
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
 +import com.owncloud.android.utils.DisplayUtils;
  import com.owncloud.android.utils.FileStorageUtils;
  import com.owncloud.android.ui.preview.PreviewTextFragment;
  
@@@ -81,12 -73,8 +82,12 @@@ public class OCFileListFragment extend
  
      public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS";
      public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL";
 +    public final static String ARG_HIDE_FAB = MY_PACKAGE + ".HIDE_FAB";
  
      private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
 +    private static final String KEY_FAB_EVER_CLICKED = "FAB_EVER_CLICKED";
 +
 +    private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
  
      private FileFragment.ContainerActivity mContainerActivity;
  
@@@ -95,8 -83,8 +96,8 @@@
      private boolean mJustFolders;
      
      private OCFile mTargetFile;
 -    
 -   
 +
 +    private boolean miniFabClicked = false;
      
      /**
       * {@inheritDoc}
          setListAdapter(mAdapter);
  
          registerLongClickListener();
 +
 +        boolean hideFab = (args != null) && args.getBoolean(ARG_HIDE_FAB, false);
 +        if (hideFab) {
 +            setFabEnabled(false);
 +        } else {
 +            setFabEnabled(true);
 +            registerFabListeners();
 +
 +            // detect if a mini FAB has ever been clicked
 +            final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
 +            if(prefs.getLong(KEY_FAB_EVER_CLICKED, 0) > 0) {
 +                miniFabClicked = true;
 +            }
 +
 +            // add labels to the min FABs when none of them has ever been clicked on
 +            if(!miniFabClicked) {
 +                setFabLabels();
 +            } else {
 +                removeFabLabels();
 +            }
 +        }
    }
  
 +    /**
 +     * adds labels to all mini FABs.
 +     */
 +    private void setFabLabels() {
 +        getFabUpload().setTitle(getResources().getString(R.string.actionbar_upload));
 +        getFabMkdir().setTitle(getResources().getString(R.string.actionbar_mkdir));
 +        getFabUploadFromApp().setTitle(getResources().getString(R.string.actionbar_upload_from_apps));
 +    }
 +
 +    /**
 +     * registers all listeners on all mini FABs.
 +     */
 +    private void registerFabListeners() {
 +        registerFabUploadListeners();
 +        registerFabMkDirListeners();
 +        registerFabUploadFromAppListeners();
 +    }
 +
 +    /**
 +     * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
 +     * on the Upload mini FAB for the linked action and {@link Toast} showing the underlying action.
 +     */
 +    private void registerFabUploadListeners() {
 +        getFabUpload().setOnClickListener(new View.OnClickListener() {
 +            @Override
 +            public void onClick(View v) {
 +                Intent action = new Intent(getActivity(), UploadFilesActivity.class);
 +                action.putExtra(
 +                        UploadFilesActivity.EXTRA_ACCOUNT,
 +                        ((FileActivity) getActivity()).getAccount()
 +                );
 +                getActivity().startActivityForResult(action, UploadSourceDialogFragment.ACTION_SELECT_MULTIPLE_FILES);
 +                getFabMain().collapse();
 +                recordMiniFabClick();
 +            }
 +        });
 +
 +        getFabUpload().setOnLongClickListener(new View.OnLongClickListener() {
 +            @Override
 +            public boolean onLongClick(View v) {
 +                Toast.makeText(getActivity(), R.string.actionbar_upload, Toast.LENGTH_SHORT).show();
 +                return true;
 +            }
 +        });
 +    }
 +
 +    /**
 +     * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
 +     * on the 'Create Dir' mini FAB for the linked action and {@link Toast} showing the underlying action.
 +     */
 +    private void registerFabMkDirListeners() {
 +        getFabMkdir().setOnClickListener(new View.OnClickListener() {
 +            @Override
 +            public void onClick(View v) {
 +                CreateFolderDialogFragment dialog =
 +                        CreateFolderDialogFragment.newInstance(mFile);
 +                dialog.show(getActivity().getSupportFragmentManager(), FileDisplayActivity.DIALOG_CREATE_FOLDER);
 +                getFabMain().collapse();
 +                recordMiniFabClick();
 +            }
 +        });
 +
 +        getFabMkdir().setOnLongClickListener(new View.OnLongClickListener() {
 +            @Override
 +            public boolean onLongClick(View v) {
 +                Toast.makeText(getActivity(), R.string.actionbar_mkdir, Toast.LENGTH_SHORT).show();
 +                return true;
 +            }
 +        });
 +    }
 +
 +    /**
 +     * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener}
 +     * on the Upload from App mini FAB for the linked action and {@link Toast} showing the underlying action.
 +     */
 +    private void registerFabUploadFromAppListeners() {
 +        getFabUploadFromApp().setOnClickListener(new View.OnClickListener() {
 +            @Override
 +            public void onClick(View v) {
 +                Intent action = new Intent(Intent.ACTION_GET_CONTENT);
 +                action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
 +
 +                //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean
 +                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
 +                    action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
 +                }
 +
 +                getActivity().startActivityForResult(
 +                        Intent.createChooser(action, getString(R.string.upload_chooser_title)),
 +                        UploadSourceDialogFragment.ACTION_SELECT_CONTENT_FROM_APPS
 +                );
 +                getFabMain().collapse();
 +                recordMiniFabClick();
 +            }
 +        });
 +
 +        getFabUploadFromApp().setOnLongClickListener(new View.OnLongClickListener() {
 +            @Override
 +            public boolean onLongClick(View v) {
 +                Toast.makeText(getActivity(),
 +                        R.string.actionbar_upload_from_apps,
 +                        Toast.LENGTH_SHORT).show();
 +                return true;
 +            }
 +        });
 +    }
 +
 +    /**
 +     * records a click on a mini FAB and thus:
 +     * <ol>
 +     *     <li>persists the click fact</li>
 +     *     <li>removes the mini FAB labels</li>
 +     * </ol>
 +     */
 +    private void recordMiniFabClick() {
 +        // only record if it hasn't been done already at some other time
 +        if(!miniFabClicked) {
 +            final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
 +            sp.edit().putLong(KEY_FAB_EVER_CLICKED, 1).commit();
 +            miniFabClicked = true;
 +        }
 +    }
 +
 +    /**
 +     * removes the labels on all known min FABs.
 +     */
 +    private void removeFabLabels() {
 +        getFabUpload().setTitle(null);
 +        getFabMkdir().setTitle(null);
 +        getFabUploadFromApp().setTitle(null);
 +        ((TextView) getFabUpload().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
 +        ((TextView) getFabMkdir().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
 +        ((TextView) getFabUploadFromApp().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
 +    }
 +
      private void registerLongClickListener() {
          getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
              public boolean onItemLongClick(AdapterView<?> arg0, View v,
          });
      }
  
 -
      private void showFileAction(int fileIndex) {
          Bundle args = getArguments();
          PopupMenu pm = new PopupMenu(getActivity(),null);
  
      /**
       * Call this, when the user presses the up button.
 -     *
 -     * Tries to move up the current folder one level. If the parent folder was removed from the
 -     * database, it continues browsing up until finding an existing folders.
 -     * <p/>
 -     * return       Count of folder levels browsed up.
 +     * <p>
 +     *     Tries to move up the current folder one level. If the parent folder was removed from the
 +     *     database, it continues browsing up until finding an existing folders.
 +     * </p>
 +     * @return Count of folder levels browsed up.
       */
      public int onBrowseUp() {
          OCFile parentDir = null;
              }   // exit is granted because storageManager.getFileByPath("/") never returns null
              mFile = parentDir;
  
-             // TODO Enable when "On Device" is recovered ?
-             listDirectory(mFile /*, MainApp.getOnlyOnDevice()*/);
+             listDirectory(mFile, MainApp.getOnlyOnDevice());
  
              onRefresh(false);
  
          if (file != null) {
              if (file.isFolder()) {
                  // update state and view of this fragment
-                 // TODO Enable when "On Device" is recovered ?
-                 listDirectory(file/*, MainApp.getOnlyOnDevice()*/);
+                 listDirectory(file, MainApp.getOnlyOnDevice());
                  // then, notify parent activity to let it update its state and view
                  mContainerActivity.onBrowsedDownTo(file);
                  // save index and top position
                      } else {
                          mContainerActivity.getFileOperationsHelper().openFile(file);
                      }
 -
 -                } else {
 -                    // automatic download, preview on finish
 -                    ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file);
 +                    
                  }
 -
              }
  
          } else {
                      item.setEnabled(false);
                  }
              }
 +
 +//            String.format(mContext.getString(R.string.subject_token),
 +//                    getClient().getCredentials().getUsername(), file.getFileName()));
          }
      }
  
      }
  
      /**
-      * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter
+      * Calls {@link OCFileListFragment#listDirectory(OCFile, boolean)} with a null parameter
       */
-     public void listDirectory(/*boolean onlyOnDevice*/){
-         listDirectory(null);
-         // TODO Enable when "On Device" is recovered ?
-         // listDirectory(null, onlyOnDevice);
+     public void listDirectory(boolean onlyOnDevice){
+         listDirectory(null, onlyOnDevice);
      }
      
      public void refreshDirectory(){
-         // TODO Enable when "On Device" is recovered ?
-         listDirectory(getCurrentFile()/*, MainApp.getOnlyOnDevice()*/);
+         listDirectory(getCurrentFile(), MainApp.getOnlyOnDevice());
      }
  
      /**
       *
       * @param directory File to be listed
       */
-     public void listDirectory(OCFile directory/*, boolean onlyOnDevice*/) {
+     public void listDirectory(OCFile directory, boolean onlyOnDevice) {
          FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
          if (storageManager != null) {
  
                  directory = storageManager.getFileById(directory.getParentId());
              }
  
-             // TODO Enable when "On Device" is recovered ?
-             mAdapter.swapDirectory(directory, storageManager/*, onlyOnDevice*/);
+             mAdapter.swapDirectory(directory, storageManager, onlyOnDevice);
              if (mFile == null || !mFile.equals(directory)) {
                  mCurrentListView.setSelection(0);
              }
              OwnCloudVersion version = AccountUtils.getServerVersion(
                      ((FileActivity)mContainerActivity).getAccount());
              if (version != null && version.supportsRemoteThumbnails() &&
 -                imagesCount > 0 && imagesCount == filesCount) {
 +                    DisplayUtils.isGridView(mFile, mContainerActivity.getStorageManager())) {
                  switchToGridView();
                  registerLongClickListener();
              } else {
@@@ -41,6 -41,7 +41,7 @@@ import android.view.View
  import android.view.Window;
  
  import com.ortiz.touch.ExtendedViewPager;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.datamodel.FileDataStorageManager;
@@@ -156,9 -157,8 +157,8 @@@ public class PreviewImageActivity exten
              parentFolder = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
          }
  
-         // TODO Enable when "On Device" is recovered ?
          mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(),
-                 parentFolder, getAccount(), getStorageManager()/*, MainApp.getOnlyOnDevice()*/);
+                 parentFolder, getAccount(), getStorageManager(), MainApp.getOnlyOnDevice());
  
          mViewPager = (ExtendedViewPager) findViewById(R.id.fragmentPager);
          int position = mHasSavedPosition ? mSavedPosition :
              OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position); 
              getSupportActionBar().setTitle(currentFile.getFileName());
              mDrawerToggle.setDrawerIndicatorEnabled(false);
 -            if (!currentFile.isDown()) {
 -                if (!mPreviewImagePagerAdapter.pendingErrorAt(position)) {
 -                    requestForDownload(currentFile);
 -                }
 -            }
 -
 +            
              // Call to reset image zoom to initial state
              ((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom();
          }
@@@ -27,7 -27,6 +27,7 @@@ import java.util.Set
  import java.util.Vector;
  
  import android.accounts.Account;
 +import android.graphics.Bitmap;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.support.v4.app.FragmentStatePagerAdapter;
@@@ -35,8 -34,6 +35,8 @@@ import android.view.ViewGroup
  
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
 +import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 +import com.owncloud.android.ui.adapter.FileListListAdapter;
  import com.owncloud.android.ui.fragment.FileFragment;
  import com.owncloud.android.utils.FileStorageUtils;
  
@@@ -64,8 -61,8 +64,8 @@@ public class PreviewImagePagerAdapter e
       * @param storageManager    Bridge to database.
       */
      public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder,
-                                     Account account, FileDataStorageManager storageManager /*,
-                                     boolean onlyOnDevice*/) {
+                                     Account account, FileDataStorageManager storageManager,
+                                     boolean onlyOnDevice) {
          super(fragmentManager);
          
          if (fragmentManager == null) {
@@@ -80,8 -77,7 +80,7 @@@
  
          mAccount = account;
          mStorageManager = storageManager;
-         // TODO Enable when "On Device" is recovered ?
-         mImageFiles = mStorageManager.getFolderImages(parentFolder/*, false*/);
+         mImageFiles = mStorageManager.getFolderImages(parentFolder, false);
          
          mImageFiles = FileStorageUtils.sortFolder(mImageFiles);
          
          Fragment fragment = null;
          if (file.isDown()) {
              fragment = PreviewImageFragment.newInstance(file,
 -                    mObsoletePositions.contains(Integer.valueOf(i)));
 +                    mObsoletePositions.contains(Integer.valueOf(i)), false);
              
          } else if (mDownloadErrors.contains(Integer.valueOf(i))) {
              fragment = FileDownloadFragment.newInstance(file, mAccount, true);
              ((FileDownloadFragment)fragment).setError(true);
              mDownloadErrors.remove(Integer.valueOf(i));
 -            
          } else {
 -            fragment = FileDownloadFragment.newInstance(
 -                    file, mAccount, mObsoletePositions.contains(Integer.valueOf(i))
 -            );
 +            fragment = PreviewImageFragment.newInstance(file,
 +                    mObsoletePositions.contains(Integer.valueOf(i)), true);
          }
          mObsoletePositions.remove(Integer.valueOf(i));
          return fragment;