Merge branch 'master' of https://github.com/owncloud/android into target_marshmallow
authorAndy Scherzinger <info@andy-scherzinger.de>
Fri, 27 Nov 2015 20:40:01 +0000 (21:40 +0100)
committerAndy Scherzinger <info@andy-scherzinger.de>
Fri, 27 Nov 2015 20:40:01 +0000 (21:40 +0100)
1  2 
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@@ -176,6 -176,7 +176,6 @@@ public class AuthenticatorActivity exte
      private EditText mUsernameInput;\r
      private EditText mPasswordInput;\r
      private View mOkButton;\r
 -    private View mCenteredRefreshButton;\r
      private TextView mAuthStatusView;\r
  \r
      private int mAuthStatusText = 0, mAuthStatusIcon = 0;\r
              }\r
          });\r
  \r
 -        mCenteredRefreshButton = findViewById(R.id.centeredRefreshButton);\r
 -        mCenteredRefreshButton.setOnClickListener(new View.OnClickListener() {\r
 +        findViewById(R.id.centeredRefreshButton).setOnClickListener(new View.OnClickListener() {\r
  \r
              @Override\r
              public void onClick(View v) {\r
                  checkOcServer();\r
              }\r
          });\r
 -        \r
 -        mOkButton = findViewById(R.id.buttonOK);\r
 +\r
 +        findViewById(R.id.embeddedRefreshButton).setOnClickListener(new View.OnClickListener() {\r
 +\r
 +            @Override\r
 +            public void onClick(View v) {\r
 +                checkOcServer();\r
 +            }\r
 +        });\r
 +\r
  \r
          /// initialize block to be moved to single Fragment to check server and get info about it \r
          initServerPreFragment(savedInstanceState);\r
          \r
          mHostUrlInput.removeTextChangedListener(mHostUrlInputWatcher);\r
          mHostUrlInput.setOnFocusChangeListener(null);\r
 -        \r
 +\r
          super.onPause();\r
      }\r
      \r
                  mOAuthTokenEndpointText.getText().toString().trim());\r
          \r
          getServerInfoIntent.putExtra(\r
-                 OperationsService.EXTRA_OAUTH2_QUERY_PARAMETERS, \r
+                 OperationsService.EXTRA_OAUTH2_QUERY_PARAMETERS,\r
                  queryParameters);\r
          \r
          if (mOperationsServiceBinder != null) {\r
          showRefreshButton(false);\r
  \r
          if (uri.length() != 0) {\r
+             uri = stripIndexPhpOrAppsFiles(uri, mHostUrlInput);\r
\r
              // Handle internationalized domain names\r
              uri = DisplayUtils.convertIdn(uri, true);\r
  \r
              Intent getServerInfoIntent = new Intent();\r
              getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);\r
              getServerInfoIntent.putExtra(\r
 -                OperationsService.EXTRA_SERVER_URL,\r
 -                normalizeUrlSuffix(uri)\r
 +                    OperationsService.EXTRA_SERVER_URL,\r
 +                    normalizeUrlSuffix(uri)\r
              );\r
              if (mOperationsServiceBinder != null) {\r
                  mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent);\r
          return url;\r
      }\r
  \r
+     private String stripIndexPhpOrAppsFiles(String url, EditText mHostUrlInput) {\r
+         if (url.endsWith("/index.php")) {\r
+             url = url.substring(0, url.lastIndexOf("/index.php"));\r
+             mHostUrlInput.setText(url);\r
+         } else if (url.contains("/index.php/apps/")) {\r
+             url = url.substring(0, url.lastIndexOf("/index.php/apps/"));\r
+             mHostUrlInput.setText(url);\r
+         }\r
\r
+         return url;\r
+     }\r
  \r
      // TODO remove, if possible\r
      private String trimUrlWebdav(String url){       \r
      }\r
  \r
      /**\r
 -     * Called when the refresh button in the input field for ownCloud host is clicked.\r
 -     * \r
 -     * Performs a new check on the URL in the input field.\r
 -     * \r
 -     * @param view      Refresh 'button'\r
 -     */\r
 -    public void onRefreshClick(View view) {\r
 -        checkOcServer();\r
 -    }\r
 -\r
 -\r
 -    /**\r
       * Called when the eye icon in the password field is clicked.\r
       * \r
       * Toggles the visibility of the password in the field. \r
@@@ -67,12 -67,14 +67,14 @@@ import com.owncloud.android.lib.common.
  import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.lib.resources.status.OCCapability;
  import com.owncloud.android.operations.CreateShareViaLinkOperation;
  import com.owncloud.android.operations.CreateShareWithShareeOperation;
  import com.owncloud.android.operations.GetSharesForFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
  import com.owncloud.android.operations.SynchronizeFolderOperation;
  import com.owncloud.android.operations.UnshareOperation;
+ import com.owncloud.android.operations.UpdateShareViaLinkOperation;
  import com.owncloud.android.services.OperationsService;
  import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
  import com.owncloud.android.ui.NavigationDrawerItem;
@@@ -93,8 -95,6 +95,6 @@@ public class FileActivity extends AppCo
  
      public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE";
      public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT";
-     public static final String EXTRA_WAITING_TO_PREVIEW =
-             "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW";
      public static final String EXTRA_FROM_NOTIFICATION =
              "com.owncloud.android.ui.activity.FROM_NOTIFICATION";
  
      /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located.*/
      private Account mAccount;
  
-     /** Main {@link OCFile} handled by the activity.*/
+     /** Capabilites of the server where {@link #mAccount} lives */
+      private OCCapability mCapabilities;
+      /** Main {@link OCFile} handled by the activity.*/
      private OCFile mFile;
  
      /** Flag to signal that the activity will is finishing to enforce the creation of an ownCloud
       * {@link Account} */
      private boolean mRedirectingToSetupAccount = false;
  
      private OperationsServiceBinder mOperationsServiceBinder = null;
  
+     private boolean mResumed = false;
      protected FileDownloaderBinder mDownloaderBinder = null;
      protected FileUploaderBinder mUploaderBinder = null;
      private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
  
-     private boolean mTryShareAgain = false;
      // Navigation Drawer
      protected DrawerLayout mDrawerLayout;
      protected ActionBarDrawerToggle mDrawerToggle;
      protected NavigationDrawerListAdapter mNavigationDrawerAdapter = null;
  
  
      // TODO re-enable when "Accounts" is available in Navigation Drawer
  //    protected boolean mShowAccounts = false;
  
              mFileOperationsHelper.setOpIdWaitingFor(
                      savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID, Long.MAX_VALUE)
                      );
-             mTryShareAgain = savedInstanceState.getBoolean(KEY_TRY_SHARE_AGAIN);
              if (getSupportActionBar() != null) {
                  getSupportActionBar().setTitle(savedInstanceState.getString(KEY_ACTION_BAR_TITLE));
              }
      @Override
      protected void onResume() {
          super.onResume();
+         mResumed = true;
          if (mOperationsServiceBinder != null) {
              doOnResumeAndBound();
          }
          if (mOperationsServiceBinder != null) {
              mOperationsServiceBinder.removeOperationListener(this);
          }
+         mResumed = false;
          super.onPause();
      }
  
  //        }
  
          // 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);
      }
  
      /**
 +     * 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.
          outState.putParcelable(FileActivity.EXTRA_FILE, mFile);
          outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification);
          outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor());
-         outState.putBoolean(KEY_TRY_SHARE_AGAIN, mTryShareAgain);
          if(getSupportActionBar() != null && getSupportActionBar().getTitle() != null) {
              // Null check in case the actionbar is used in ActionBar.NAVIGATION_MODE_LIST
              // since it doesn't have a title then
          mAccount = account;
      }
  
+     /**
+      * Getter for the capabilities of the server where the current OC account lives.
+      *
+      * @return  Capabilities of the server where the current OC account lives. Null if the account is not
+      *          set yet.
+      */
+     public OCCapability getCapabilities() {
+         return mCapabilities;
+     }
      /**
       * @return Value of mFromNotification: True if the Activity is launched by a notification
       */
          return mRedirectingToSetupAccount;
      }
  
-     public boolean isTryShareAgain(){
-         return mTryShareAgain;
-     }
-     public void setTryShareAgain(boolean tryShareAgain) {
-        mTryShareAgain = tryShareAgain;
-     }
      public OperationsServiceBinder getOperationsServiceBinder() {
          return mOperationsServiceBinder;
      }
      protected void onAccountSet(boolean stateWasRecovered) {
          if (getAccount() != null) {
              mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
+             mCapabilities = mStorageManager.getCapability(mAccount.name);
  
          } else {
              Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
                          Toast.LENGTH_LONG);
                  t.show();
              }
-             mTryShareAgain = false;
  
          } else if (operation == null ||
                  operation instanceof CreateShareWithShareeOperation ||
                  operation instanceof UnshareOperation ||
-                 operation instanceof SynchronizeFolderOperation
+                 operation instanceof SynchronizeFolderOperation ||
+                 operation instanceof UpdateShareViaLinkOperation
                  ) {
              if (result.isSuccess()) {
                  updateFileFromDB();
              onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
  
          } else if (operation instanceof GetSharesForFileOperation) {
-             if (result.isSuccess()) {
+             if (result.isSuccess() || result.getCode() == ResultCode.SHARE_NOT_FOUND) {
                  updateFileFromDB();
  
-             } else if (result.getCode() != ResultCode.SHARE_NOT_FOUND) {
+             } else {
                  Toast t = Toast.makeText(this,
                          ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
                          Toast.LENGTH_LONG);
      private void onCreateShareViaLinkOperationFinish(CreateShareViaLinkOperation operation,
                                                       RemoteOperationResult result) {
          if (result.isSuccess()) {
-             mTryShareAgain = false;
              updateFileFromDB();
  
              Intent sendIntent = operation.getSendIntentWithSubject(this);
-             startActivity(sendIntent);
+             if (sendIntent != null) {
+                 startActivity(sendIntent);
+             }
          } else {
              // Detect Failure (403) --> needs Password
              if (result.getCode() == ResultCode.SHARE_FORBIDDEN) {
-                 if (!isTryShareAgain()) {
+                 String password = operation.getPassword();
+                 if ((password == null || password.length() == 0) &&
+                     getCapabilities().getFilesSharingPublicEnabled().isUnknown())
+                     {
+                     // Was tried without password, but not sure that it's optional. Try with password.
+                     // Try with password before giving up.
+                     // See also ShareFileFragment#OnShareViaLinkListener
                      SharePasswordDialogFragment dialog =
-                             SharePasswordDialogFragment.newInstance(new OCFile(operation.getPath()),
-                                     operation.getSendIntent());
+                             SharePasswordDialogFragment.newInstance(new OCFile(operation.getPath()), true);
                      dialog.show(getSupportFragmentManager(), DIALOG_SHARE_PASSWORD);
                  } else {
                      Toast t = Toast.makeText(this,
                          ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
                          Toast.LENGTH_LONG);
                      t.show();
-                     mTryShareAgain = false;
                  }
              } else {
                  Toast t = Toast.makeText(this,
                  /*if (!mOperationsServiceBinder.isPerformingBlockingOperation()) {
                      dismissLoadingDialog();
                  }*/
-                 doOnResumeAndBound();
+                 if (mResumed) {
+                     doOnResumeAndBound();
+                 }
  
              } else {
                  return;
@@@ -26,7 -26,6 +26,6 @@@ import android.accounts.Account
  import android.accounts.AccountManager;
  import android.accounts.AuthenticatorException;
  import android.annotation.TargetApi;
- import android.support.v7.app.AlertDialog;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.ContentResolver;
@@@ -50,6 -49,7 +49,7 @@@ import android.support.v4.app.FragmentM
  import android.support.v4.app.FragmentTransaction;
  import android.support.v4.content.ContextCompat;
  import android.support.v4.view.GravityCompat;
+ import android.support.v7.app.AlertDialog;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
@@@ -79,14 -79,11 +79,11 @@@ import com.owncloud.android.lib.common.
  import com.owncloud.android.lib.common.utils.Log_OC;
  import com.owncloud.android.operations.CopyFileOperation;
  import com.owncloud.android.operations.CreateFolderOperation;
- import com.owncloud.android.operations.CreateShareViaLinkOperation;
- import com.owncloud.android.operations.CreateShareWithShareeOperation;
  import com.owncloud.android.operations.MoveFileOperation;
  import com.owncloud.android.operations.RefreshFolderOperation;
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
- import com.owncloud.android.operations.UnshareOperation;
  import com.owncloud.android.services.observer.FileObserverService;
  import com.owncloud.android.syncadapter.FileSyncAdapter;
  import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
@@@ -148,7 -145,7 +145,7 @@@ 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";
  
              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) {
      @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);
          
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.main_menu, menu);
 +        menu.findItem(R.id.action_create_dir).setVisible(false);
          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();
          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();
 -        } else {
 -            super.onBackPressed();
          }
      }
  
          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 {
  
          } else if (operation instanceof CreateFolderOperation) {
              onCreateFolderOperationFinish((CreateFolderOperation) operation, result);
  
-         } else if (operation instanceof CreateShareViaLinkOperation ||
-                     operation instanceof CreateShareWithShareeOperation ) {
-             refreshShowDetails();
-             refreshListOfFilesFragment();
-         } else if (operation instanceof UnshareOperation) {
-             onUnshareLinkOperationFinish((UnshareOperation) operation, result);
          } else if (operation instanceof MoveFileOperation) {
              onMoveFileOperationFinish((MoveFileOperation) operation, result);
  
  
      }
  
-     private void onUnshareLinkOperationFinish(UnshareOperation 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) {
@@@ -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,8 -34,6 +37,8 @@@ 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.R;
  import com.owncloud.android.authentication.AccountUtils;
@@@ -51,14 -46,11 +51,14 @@@ 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.ui.preview.PreviewTextFragment;
@@@ -81,12 -73,8 +81,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 +95,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;
          mTargetFile = (OCFile) mAdapter.getItem(filePosition);
          switch (menuId) {
              case R.id.action_share_file: {
-                 mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
-                 return true;
-             }
-             case R.id.action_share_with_users: {
                  mContainerActivity.getFileOperationsHelper().showShareFile(mTargetFile);
                  return true;
              }
                  mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
                  return true;
              }
-             case R.id.action_unshare_file: {
-                 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
-                 return true;
-             }
              case R.id.action_rename_file: {
                  RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
                  dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);