Merge remote-tracking branch 'remotes/upstream/streaming' into beta
authortobiasKaminsky <tobias@kaminsky.me>
Sun, 1 Nov 2015 08:07:58 +0000 (09:07 +0100)
committertobiasKaminsky <tobias@kaminsky.me>
Sun, 1 Nov 2015 08:07:58 +0000 (09:07 +0100)
1  2 
res/menu/file_actions_menu.xml
res/values/strings.xml
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@@ -1,5 -1,4 +1,5 @@@
 -<?xml version="1.0" encoding="utf-8"?><!--
 +<?xml version="1.0" encoding="utf-8"?>
 +<!--
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
          android:icon="@android:drawable/ic_menu_share"
          android:orderInCategory="1" />
      <item
+         android:id="@+id/action_stream_file"
+         android:title="@string/action_stream_file"
+         android:icon="@android:drawable/ic_menu_view"
+         android:orderInCategory="1" />
+     <item
          android:id="@+id/action_unshare_file"
          android:title="@string/action_unshare_file"
          android:icon="@android:drawable/ic_menu_share"
diff --combined res/values/strings.xml
@@@ -23,7 -23,8 +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="unfavorite">Unfavorite</string>
      <string name="common_rename">Rename</string>
      <string name="common_remove">Remove</string>
 -    <string name="confirmation_remove_alert">"Do you really want to remove %1$s?"</string>
 +    <string name="confirmation_remove_file_alert">"Do you really want to remove %1$s?"</string>
      <string name="confirmation_remove_folder_alert">"Do you really want to remove %1$s and its contents?"</string>
      <string name="confirmation_remove_local">Local only</string>
      <string name="confirmation_remove_folder_local">Local only</string>
 -    <string name="confirmation_remove_remote">From server</string>
 +    <string name="confirmation_remove_file_remote">From server</string>
      <string name="confirmation_remove_remote_and_local">Remote &amp; local</string>
      <string name="remove_success_msg">"Removal succeeded"</string>
      <string name="remove_fail_msg">"Removal failed"</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="sync_folder_failed_content">Synchronization 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>
 +    <string name="common_category">Common</string>
 +    <string name="pref_cache_size">Cache size</string>
 +    <string name="prefs_instant_behaviour_dialogTitle">Upload file to server and ...</string>
 +    <string name="prefs_instant_behaviour_title">Behaviour</string>
 +    <string name="upload_copy_files">Copy file</string>
 +    <string name="upload_move_files">Move file</string>
 +
 +    <string name="pref_behaviour_entries_do_nothing">do nothing</string>
 +    <string name="pref_behaviour_entries_copy">copy file to OC folder</string>
 +    <string name="pref_behaviour_entries_move">move file to OC folder</string>
 +    <string name="pref_behaviour_entries_delete">delete origin file</string>
 +    <string name="confirmation_remove_files_alert">Do you really want to remove selected items?</string>
 +    <string name="confirmation_remove_folders_alert">Do you really want to remove a folder and its content?</string>
 +    <string name="confirmation_remove_files">selected items</string>
 +    <string name="error_log_exit">Exit</string>
 +    <string name="error_log_send">Send Log</string>
 +    <string name="error_log_title">Error Log</string>
+     <string name="action_stream_file">Stream file with external player</string>
+     <string name="stream_expose_password">Do you want to stream this file with an external app?\n\nCAUTION: This may expose your password!</string>
  
  </resources>
   */
  package com.owncloud.android.ui.fragment;
  
+ import android.accounts.Account;
  import android.app.Activity;
+ import android.content.Context;
+ import android.content.DialogInterface;
  import android.content.Intent;
 +import android.content.SharedPreferences;
 +import android.os.Build;
+ import android.net.Uri;
  import android.os.Bundle;
 +import android.preference.PreferenceManager;
  import android.support.v4.widget.SwipeRefreshLayout;
 +import android.view.ActionMode;
+ import android.support.v7.app.AlertDialog;
+ import android.view.ContextMenu;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
 +import android.widget.AbsListView;
  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;
@@@ -49,35 -48,29 +55,37 @@@ import com.owncloud.android.datamodel.O
  import com.owncloud.android.files.FileMenuFilter;
  import com.owncloud.android.lib.common.utils.Log_OC;
  import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+ import com.owncloud.android.media.MediaService;
  import com.owncloud.android.ui.activity.FileActivity;
  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.RemoveFilesDialogFragment;
  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.ExceptionHandler;
 +import com.owncloud.android.utils.FileStorageUtils;
  import com.owncloud.android.ui.preview.PreviewTextFragment;
+ import com.owncloud.android.utils.FileStorageUtils;
  
  import java.io.File;
 +import java.util.ArrayList;
  
  /**
   * A Fragment that lists all files and folders in a given path.
   *
   * TODO refactor to get rid of direct dependency on FileDisplayActivity
   */
 -public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener {
 +public class OCFileListFragment extends ExtendedListFragment {
      
      private static final String TAG = OCFileListFragment.class.getSimpleName();
  
  
      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;
  
      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,
 -                                           int index, long arg3) {
 -                showFileAction(index);
 +        getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
 +            private Menu menu;
 +
 +            @Override
 +            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
 +                final int checkedCount = getListView().getCheckedItemCount();
 +                // TODO Tobi extract to values
 +                mode.setTitle(checkedCount + " selected");
 +
 +                if (checked) {
 +                    mAdapter.setNewSelection(position, checked);
 +                } else {
 +                    mAdapter.removeSelection(position);
 +                }
 +
 +                // TODO maybe change: only recreate menu if count changes
 +                menu.clear();
 +                if (checkedCount == 1) {
 +                    createContextMenu(menu);
 +                } else {
 +                    // download, move, copy, delete
 +                    getActivity().getMenuInflater().inflate(R.menu.multiple_file_actions_menu, menu);
 +                }
 +
 +            }
 +
 +            @Override
 +            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
 +                this.menu = menu;
                  return true;
              }
 +
 +            @Override
 +            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
 +                return false;
 +            }
 +
 +            @Override
 +            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
 +                return onFileActionChosen(item.getItemId());
 +            }
 +
 +            @Override
 +            public void onDestroyActionMode(ActionMode mode) {
 +                mAdapter.removeSelection();
 +            }
          });
      }
  
  
      /**
       * 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
                      ((FileDisplayActivity)mContainerActivity).startImagePreview(file);
                  } else if (PreviewTextFragment.canBePreviewed(file)){
                      ((FileDisplayActivity)mContainerActivity).startTextPreview(file);
-                 } else if (file.isDown()) {
-                     if (PreviewMediaFragment.canBePreviewed(file)) {
+                 } else if (PreviewMediaFragment.canBePreviewed(file)) {
                          // media preview
                          ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true);
-                     } else {
+                     } else if (file.isDown()) {
                          mContainerActivity.getFileOperationsHelper().openFile(file);
--                    }
 -                else {
 +                } else {
                      // automatic download, preview on finish
                      ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file);
                  }
 -
              }
 -
          } else {
              Log_OC.d(TAG, "Null object in ListAdapter!!");
          }
--
      }
  
      /**
       * {@inheritDoc}
       */
 -    @Override
 -    public void onCreateContextMenu(
 -            ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
 +    // TODO Tobi needed?
 +    public void createContextMenu(Menu menu) {
          Bundle args = getArguments();
          boolean allowContextualActions =
                  (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
          if (allowContextualActions) {
              MenuInflater inflater = getActivity().getMenuInflater();
              inflater.inflate(R.menu.file_actions_menu, menu);
 -            AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
 -            OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
 +            OCFile targetFile = null;
 +            if (mAdapter.getCheckedItems().size() == 1){
 +                targetFile = mAdapter.getCheckedItems().get(0);
 +            }
  
              if (mContainerActivity.getStorageManager() != null) {
                  FileMenuFilter mf = new FileMenuFilter(
                      item.setEnabled(false);
                  }
              }
 +
 +//            String.format(mContext.getString(R.string.subject_token),
 +//                    getClient().getCredentials().getUsername(), file.getFileName()));
          }
      }
  
 -    /**
 -     * {@inheritDoc}
 -     */
 -    @Override
 -    public boolean onFileActionChosen(int menuId, int filePosition) {
 -        mTargetFile = (OCFile) mAdapter.getItem(filePosition);
 -        switch (menuId) {
 -            case R.id.action_share_file: {
 -                mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
 -                return true;
 -            }
 -            case R.id.action_open_file_with: {
 -                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);
 -                return true;
 -            }
 -            case R.id.action_remove_file: {
 -                RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
 -                dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
 -                return true;
 -            }
 -            case R.id.action_download_file:
 -            case R.id.action_sync_file: {
 -                mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
 -                return true;
 -            }
 -            case R.id.action_cancel_sync: {
 -                ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile);
 -                return true;
 -            }
 -            case R.id.action_see_details: {
 -                mContainerActivity.showDetails(mTargetFile);
 -                return true;
 -            }
 -            case R.id.action_send_file: {
 -                // Obtain the file
 -                if (!mTargetFile.isDown()) {  // Download the file
 -                    Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
 -                    ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
 +    public boolean onFileActionChosen(int menuId) {
 +        if (mAdapter.getCheckedItems().size() == 1){
 +            OCFile mTargetFile = mAdapter.getCheckedItems().get(0);
  
 -                } else {
 -                    mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
 +            switch (menuId) {
 +                case R.id.action_share_file: {
 +                    mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
 +                    return true;
                  }
 -                return true;
 -            }
 -            case R.id.action_stream_file: {
 -                Account account = ((FileActivity)mContainerActivity).getAccount();
 -                Context context = MainApp.getAppContext();
 -                String uri = PreviewMediaFragment.generateUrlWithCredentials(account, context, mTargetFile);
 -                MediaService.streamWithExternalApp(uri, getActivity()).show();
 -
 -                return true;
 +                case R.id.action_open_file_with: {
 +                    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);
 +                    return true;
 +                }
 +                case R.id.action_remove_file: {
 +                    RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
 +                    dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
 +                    return true;
 +                }
 +                case R.id.action_download_file:
 +                case R.id.action_sync_file: {
 +                    mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
 +                    return true;
 +                }
 +                case R.id.action_cancel_sync: {
 +                    ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
 +                    return true;
 +                }
 +                case R.id.action_see_details: {
 +                    mContainerActivity.showDetails(mTargetFile);
 +                    return true;
 +                }
 +                case R.id.action_send_file: {
 +                    // Obtain the file
 +                    if (!mTargetFile.isDown()) {  // Download the file
 +                        Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
 +                        ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
++                        return true;
 +                    } else {
 +                        mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
 +                    }
++                }
++                case R.id.action_stream_file: {
++                    Account account = ((FileActivity)mContainerActivity).getAccount();
++                    Context context = MainApp.getAppContext();
++                    String uri = PreviewMediaFragment.generateUrlWithCredentials(account, context, mTargetFile);
++                    MediaService.streamWithExternalApp(uri, getActivity()).show();
 +                    return true;
 +                }
 +                case R.id.action_move: {
 +                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 +                    ArrayList files = new ArrayList();
 +                    files.add(mTargetFile);
 +                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, files);
 +                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
 +                    return true;
 +                }
 +                case R.id.action_favorite_file: {
 +                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
 +                    return true;
 +                }
 +                case R.id.action_unfavorite_file: {
 +                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
 +                    return true;
 +                }
 +                case R.id.action_copy:
 +                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 +
 +                    // Pass mTargetFile that contains info of selected file/folder
 +                    action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
 +                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
 +                    return true;
 +                default:
 +                    return false;
              }
 -            case R.id.action_move: {
 -                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 +        } else {
 +            ArrayList<OCFile> mTargetFiles = mAdapter.getCheckedItems();
  
 -                // Pass mTargetFile that contains info of selected file/folder
 -                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
 -                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
 -                return true;
 -            }
 -            case R.id.action_favorite_file: {
 -                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
 -                return true;
 -            }
 -            case R.id.action_unfavorite_file: {
 -                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
 -                return true;
 +            switch (menuId) {
 +                case R.id.action_remove_file: {
 +                    RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(mTargetFiles);
 +                    dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
 +                    return true;
 +                }
 +                case R.id.action_download_file:
 +                case R.id.action_sync_file: {
 +                    mContainerActivity.getFileOperationsHelper().syncFiles(mTargetFiles);
 +                    return true;
 +                }
 +                case R.id.action_move: {
 +                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 +                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
 +                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
 +                    return true;
 +                }
 +                case R.id.action_favorite_file: {
 +                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, true);
 +                    return true;
 +                }
 +                case R.id.action_unfavorite_file: {
 +                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, false);
 +                    return true;
 +                }
 +                case R.id.action_copy:
 +                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 +                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
 +                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
 +                    return true;
 +                default:
 +                    return false;
              }
 -            case R.id.action_copy:
 -                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
 -
 -                // Pass mTargetFile that contains info of selected file/folder
 -                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
 -                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
 -                return true;
 -            default:
 -                return false;
          }
 +
      }
      
      /**
      @Override
      public boolean onContextItemSelected (MenuItem item) {
          AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
 -        boolean matched = onFileActionChosen(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).position);
 +        boolean matched = onFileActionChosen(item.getItemId());
          if(!matched) {
              return super.onContextItemSelected(item);
          } else {
      }
  
      /**
 -     * 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 {