Browse Source

Merge pull request #141 from nextcloud/filesDrop

Files drop
Andy Scherzinger 8 years ago
parent
commit
470d89fb20

+ 2 - 2
AndroidManifest.xml

@@ -20,8 +20,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.owncloud.android"
-    android:versionCode="10020099"
-    android:versionName="1.2.0">
+    android:versionCode="10030001"
+    android:versionName="1.3.0 RC1">
 
     <uses-sdk
         android:minSdkVersion="14"

+ 1 - 1
build.gradle

@@ -33,7 +33,7 @@ dependencies {
     /// dependencies for app building
     compile name: 'touch-image-view'
 
-    compile 'com.github.nextcloud:android-library:1.0.6'
+    compile 'com.github.nextcloud:android-library:1.0.7'
     compile "com.android.support:support-v4:${supportLibraryVersion}"
     compile "com.android.support:design:${supportLibraryVersion}"
     compile 'com.jakewharton:disklrucache:2.0.2'

+ 34 - 0
res/layout/share_file_layout.xml

@@ -190,6 +190,40 @@
 
                 </RelativeLayout>
 
+                <RelativeLayout
+                    android:id="@+id/shareViaLinkHideFileListingPermissionSection"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginBottom="@dimen/standard_half_margin"
+                    android:visibility="invisible"
+                    >
+
+                    <android.support.v7.widget.SwitchCompat
+                        android:id="@+id/shareViaLinkFileListingPermissionSwitch"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_alignParentEnd="true"
+                        android:layout_alignParentRight="true"
+                        android:layout_centerInParent="true"
+                        android:padding="@dimen/standard_half_padding"
+                        />
+
+                    <TextView
+                        android:id="@+id/shareViaLinkFileListingPermissionLabel"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_alignParentLeft="true"
+                        android:layout_alignParentStart="true"
+                        android:layout_toLeftOf="@id/shareViaLinkFileListingPermissionSwitch"
+                        android:layout_toStartOf="@id/shareViaLinkFileListingPermissionSwitch"
+                        android:padding="@dimen/standard_half_padding"
+                        android:text="@string/share_via_link_hide_file_listing_permission_label"
+                        android:textColor="@color/black"
+                        android:textSize="14sp"
+                        />
+
+                </RelativeLayout>
+
                 <RelativeLayout
                     android:id="@+id/shareViaLinkPasswordSection"
                     android:layout_width="match_parent"

+ 1 - 0
res/values/setup.xml

@@ -66,6 +66,7 @@
     <string name="mail_recommend">"mailto:"</string>
     <string name="mail_feedback">"mailto:android@nextcloud.com"</string>
     <string name="url_app_download">"https://play.google.com/store/apps/details?id=com.nextcloud.client"</string>
+    <string name="url_server_install">https://nextcloud.com/install</string>
 
     <!--Destination mail for sending log files -->
     <string name="mail_logger"></string>

+ 3 - 0
res/values/strings.xml

@@ -424,6 +424,7 @@
     <string name="share_via_link_password_label">Password protect</string>
     <string name="share_via_link_password_title">Secured</string>
     <string name="share_via_link_edit_permission_label">Allow editing</string>
+    <string name="share_via_link_hide_file_listing_permission_label">Hide file listing</string>
     <string name="share_get_public_link_button">Get link</string>
     <string name="share_with_title">Share with &#8230;</string>
     <string name="share_with_edit_title">Share with %1$s</string>
@@ -464,6 +465,8 @@
     <string name="confirmation_remove_folders_alert">Do you really want to remove the selected items and their contents?</string>
     <string name="uploads_view_upload_status_waiting_for_charging">Waiting for device charging</string>
     <string name="actionbar_search">Search</string>
+    <string name="files_drop_not_supported">This is a Nextcloud feature, please update.</string>
+    <string name="learn_more">Learn more</string>
     <plurals name="items_selected_count">
         <!--
              As a developer, you should always supply "one" and "other"

+ 3 - 0
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -1911,6 +1911,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING, capability.getFilesBigFileChuncking().getValue());
         cv.put(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE, capability.getFilesUndelete().getValue());
         cv.put(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING, capability.getFilesVersioning().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_FILES_DROP, capability.getFilesFileDrop().getValue());
 
         if (capabilityExists(mAccount.name)) {
             if (getContentResolver() != null) {
@@ -2051,6 +2052,8 @@ public class FileDataStorageManager {
                     .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE))));
             capability.setFilesVersioning(CapabilityBooleanType.fromValue(c.getInt(c
                     .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING))));
+            capability.setFilesFileDrop(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_DROP))));
 
         }
         return capability;

+ 2 - 1
src/com/owncloud/android/db/ProviderMeta.java

@@ -33,7 +33,7 @@ import com.owncloud.android.MainApp;
 public class ProviderMeta {
 
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 14;
+    public static final int DB_VERSION = 15;
 
     private ProviderMeta() {
     }
@@ -131,6 +131,7 @@ public class ProviderMeta {
         public static final String CAPABILITIES_FILES_BIGFILECHUNKING = "files_bigfilechunking";
         public static final String CAPABILITIES_FILES_UNDELETE = "files_undelete";
         public static final String CAPABILITIES_FILES_VERSIONING = "files_versioning";
+        public static final String CAPABILITIES_FILES_DROP = "files_drop";
 
         public static final String CAPABILITIES_DEFAULT_SORT_ORDER = CAPABILITIES_ACCOUNT_NAME
                 + " collate nocase asc";

+ 22 - 5
src/com/owncloud/android/files/FileOperationsHelper.java

@@ -37,9 +37,7 @@ import android.widget.Toast;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.db.OCUpload;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
-import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.common.network.WebdavUtils;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -51,13 +49,10 @@ import com.owncloud.android.services.observer.FileObserverService;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.ShareActivity;
 import com.owncloud.android.ui.dialog.ShareLinkToDialog;
-import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
 
 import java.util.Collection;
 import java.util.List;
 
-import java.util.ArrayList;
-
 /**
  *
  */
@@ -397,6 +392,28 @@ public class FileOperationsHelper {
         queueShareIntent(updateShareIntent);
     }
 
+    /**
+     * Updates a public share on a folder to set its hide file listing permission.
+     * Starts a request to do it in {@link OperationsService}
+     *
+     * @param share                    {@link OCShare} instance which permissions will be updated.
+     * @param hideFileListing          New state of the permission for editing the folder shared via link.
+     */
+    public void setHideFileListingPermissionsToShare(OCShare share, boolean hideFileListing) {
+        Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
+        updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
+        updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_ID, share.getId());
+
+        if (hideFileListing) {
+            updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS, OCShare.CREATE_PERMISSION_FLAG);
+        } else {
+            updateShareIntent.
+                    putExtra(OperationsService.EXTRA_SHARE_PERMISSIONS, OCShare.FEDERATED_PERMISSIONS_FOR_FOLDER);
+        }
+
+        queueShareIntent(updateShareIntent);
+    }
 
     /**
      * @return 'True' if the server supports the Search Users API

+ 17 - 1
src/com/owncloud/android/providers/FileContentProvider.java

@@ -764,6 +764,21 @@ public class FileContentProvider extends ContentProvider {
                 }
             }
 
+            if (oldVersion < 15 && newVersion >= 15) {
+                Log_OC.i("SQL", "Entering in the #15 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    // drop old capabilities table
+                    db.execSQL("DROP TABLE IF EXISTS " + "capabilities" + ";");
+                    // Create uploads table
+                    createCapabilitiesTable(db);
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
             if (!upgraded)
                 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
                         ", newVersion == " + newVersion);
@@ -844,7 +859,8 @@ public class FileContentProvider extends ContentProvider {
                 + ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING + " INTEGER, "     // boolean
                 + ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING + " INTEGER, "   // boolean
                 + ProviderTableMeta.CAPABILITIES_FILES_UNDELETE + " INTEGER, "  // boolean
-                + ProviderTableMeta.CAPABILITIES_FILES_VERSIONING + " INTEGER );" );   // boolean
+                + ProviderTableMeta.CAPABILITIES_FILES_VERSIONING + " INTEGER, "   // boolean
+                + ProviderTableMeta.CAPABILITIES_FILES_DROP + " INTEGER );" );   // boolean
     }
 
     private void createUploadsTable(SQLiteDatabase db){

+ 132 - 63
src/com/owncloud/android/ui/fragment/ShareFileFragment.java

@@ -23,8 +23,11 @@ package com.owncloud.android.ui.fragment;
 
 import android.accounts.Account;
 import android.app.Activity;
+import android.content.Intent;
 import android.graphics.Bitmap;
+import android.net.Uri;
 import android.os.Bundle;
+import android.support.design.widget.Snackbar;
 import android.support.v4.app.Fragment;
 import android.support.v7.widget.AppCompatButton;
 import android.support.v7.widget.SwitchCompat;
@@ -79,7 +82,7 @@ public class ShareFileFragment extends Fragment
     private static final String TAG = ShareFileFragment.class.getSimpleName();
 
     /**
-     * The fragment initialization parameters
+     * The fragment initialization parameters.
      */
     private static final String ARG_FILE = "FILE";
     private static final String ARG_ACCOUNT = "ACCOUNT";
@@ -88,60 +91,64 @@ public class ShareFileFragment extends Fragment
 //    private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
 
     /**
-     * File to share, received as a parameter in construction time
+     * File to share, received as a parameter in construction time.
      */
     private OCFile mFile;
 
     /**
-     * OC account holding the file to share, received as a parameter in construction time
+     * OC account holding the file to share, received as a parameter in construction time.
      */
     private Account mAccount;
 
     /**
-     * Reference to parent listener
+     * Reference to parent listener.
      */
     private ShareFragmentListener mListener;
 
     /**
-     * List of private shares bound to the file
+     * List of private shares bound to the file.
      */
     private ArrayList<OCShare> mPrivateShares;
 
     /**
-     * Capabilities of the server
+     * Capabilities of the server.
      */
     private OCCapability mCapabilities;
 
     /**
-     * Adapter to show private shares
+     * Adapter to show private shares.
      */
     private ShareUserListAdapter mUserGroupsAdapter = null;
 
     /**
-     * Public share bound to the file
+     * Public share bound to the file.
      */
     private OCShare mPublicShare;
 
     /**
-     * Listener for changes on switch to share / unshare publicly
+     * Listener for changes on switch to share / unshare publicly.
      */
     private CompoundButton.OnCheckedChangeListener mOnShareViaLinkSwitchCheckedChangeListener;
 
     /**
-     * Listener for user actions to set, update or clear password on public link
+     * Listener for user actions to set, update or clear password on public link.
      */
     private OnPasswordInteractionListener mOnPasswordInteractionListener = null;
 
     /**
-     * Listener for user actions to set, update or clear expiration date on public link
+     * Listener for user actions to set, update or clear expiration date on public link.
      */
     private OnExpirationDateInteractionListener mOnExpirationDateInteractionListener = null;
 
     /**
-     * Listener for user actions to set or unset edit permission on public link
+     * Listener for user actions to set or unset edit permission on public link.
      */
     private OnEditPermissionInteractionListener mOnEditPermissionInteractionListener = null;
 
+    /**
+     * Listener for user actions to set or unset hide file listing permission on public link.
+     */
+    private OnHideFileListingPermissionInteractionListener mOnHideFileListingPermissionInteractionListener = null;
 
     /**
      * Public factory method to create new ShareFileFragment instances.
@@ -160,14 +167,11 @@ public class ShareFileFragment extends Fragment
     }
 
     /**
-     * Required empty public constructor
+     * Required empty public constructor.
      */
     public ShareFileFragment() {
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -178,10 +182,6 @@ public class ShareFileFragment extends Fragment
         }
     }
 
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
@@ -202,9 +202,11 @@ public class ShareFileFragment extends Fragment
                 icon.setImageBitmap(thumbnail);
             }
         }
+
         // Name
         TextView fileNameHeader = (TextView) view.findViewById(R.id.shareFileName);
         fileNameHeader.setText(getResources().getString(R.string.share_file, mFile.getFileName()));
+
         // Size
         TextView size = (TextView) view.findViewById(R.id.shareFileSize);
         if (mFile.isFolder()) {
@@ -242,6 +244,9 @@ public class ShareFileFragment extends Fragment
         // Set listener for user actions on edit permission
         initEditPermissionListener(view);
 
+        // Set listener for hide file listing
+        initHideFileListingListener(view);
+
         // Hide share features sections that are not enabled
         hideNotEnabledShareSections(view);
 
@@ -309,7 +314,6 @@ public class ShareFileFragment extends Fragment
         }
     }
 
-
     /**
      * Binds listener for user actions that start any update on a expiration date
      * for the public link to the views receiving the user events.
@@ -357,8 +361,7 @@ public class ShareFileFragment extends Fragment
                 );
 
             } else {
-                ((FileActivity) getActivity()).getFileOperationsHelper().
-                        setExpirationDateToShareViaLink(mFile, -1);
+                ((FileActivity) getActivity()).getFileOperationsHelper().setExpirationDateToShareViaLink(mFile, -1);
             }
 
             // undo the toggle to grant the view will be correct if the dialog is cancelled
@@ -368,8 +371,8 @@ public class ShareFileFragment extends Fragment
         }
 
         /**
-         * Called by R.id.shareViaLinkExpirationLabel or R.id.shareViaLinkExpirationValue
-         * to change the current expiration date.
+         * Called by R.id.shareViaLinkExpirationLabel or R.id.shareViaLinkExpirationValue to change the current
+         * expiration date.
          *
          * @param expirationView Label or value view touched by the user.
          */
@@ -381,10 +384,7 @@ public class ShareFileFragment extends Fragment
                     chosenDateInMillis = mPublicShare.getExpirationDate();
                 }
                 ExpirationDatePickerDialogFragment dialog =
-                        ExpirationDatePickerDialogFragment.newInstance(
-                                mFile,
-                                chosenDateInMillis
-                        );
+                        ExpirationDatePickerDialogFragment.newInstance(mFile, chosenDateInMillis);
                 dialog.show(
                         getActivity().getSupportFragmentManager(),
                         ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG
@@ -393,10 +393,9 @@ public class ShareFileFragment extends Fragment
         }
     }
 
-
     /**
-     * Binds listener for user actions that start any update on a password for the public link
-     * to the views receiving the user events.
+     * Binds listener for user actions that start any update on a password for the public link to the views receiving
+     * the user events.
      *
      * @param shareView Root view in the fragment.
      */
@@ -406,11 +405,9 @@ public class ShareFileFragment extends Fragment
         ((SwitchCompat) shareView.findViewById(R.id.shareViaLinkPasswordSwitch)).
                 setOnCheckedChangeListener(mOnPasswordInteractionListener);
 
-        shareView.findViewById(R.id.shareViaLinkPasswordLabel).
-                setOnClickListener(mOnPasswordInteractionListener);
+        shareView.findViewById(R.id.shareViaLinkPasswordLabel).setOnClickListener(mOnPasswordInteractionListener);
 
-        shareView.findViewById(R.id.shareViaLinkPasswordValue).
-                setOnClickListener(mOnPasswordInteractionListener);
+        shareView.findViewById(R.id.shareViaLinkPasswordValue).setOnClickListener(mOnPasswordInteractionListener);
     }
 
 
@@ -474,11 +471,23 @@ public class ShareFileFragment extends Fragment
 
     }
 
+    /**
+     * Binds listener for user actions that start any update the hide file listing permissions
+     * for the public link to the views receiving the user events.
+     *
+     * @param shareView Root view in the fragment.
+     */
+    private void initHideFileListingListener(View shareView) {
+        mOnHideFileListingPermissionInteractionListener = new OnHideFileListingPermissionInteractionListener();
+
+        ((SwitchCompat) shareView.findViewById(R.id.shareViaLinkFileListingPermissionSwitch)).
+                setOnCheckedChangeListener(mOnHideFileListingPermissionInteractionListener);
+    }
+
     /**
      * Listener for user actions that start any update on the edit permissions for the public link.
      */
-    private class OnEditPermissionInteractionListener
-            implements CompoundButton.OnCheckedChangeListener {
+    private class OnEditPermissionInteractionListener implements CompoundButton.OnCheckedChangeListener {
 
         /**
          * Called by R.id.shareViaLinkEditPermissionSwitch to set or clear the edit permission.
@@ -494,19 +503,59 @@ public class ShareFileFragment extends Fragment
                 return;
             }
 
-            ((FileActivity) getActivity()).getFileOperationsHelper().
-                    setUploadPermissionsToShare(
-                            mFile,
-                            isChecked
-                    );
-            ;
+            ((FileActivity) getActivity()).getFileOperationsHelper().setUploadPermissionsToShare(mFile, isChecked);
 
             // undo the toggle to grant the view will be correct if the dialog is cancelled
             switchView.setOnCheckedChangeListener(null);
             switchView.toggle();
             switchView.setOnCheckedChangeListener(mOnEditPermissionInteractionListener);
         }
+    }
 
+    /**
+     * Listener for user actions that start any update on the hide file listing permissions for the public link.
+     */
+    private class OnHideFileListingPermissionInteractionListener implements CompoundButton.OnCheckedChangeListener {
+
+        /**
+         * Called by R.id.shareViaLinkHideListPermissionSwitch to set or clear the edit permission.
+         *
+         * @param switchView {@link SwitchCompat} toggled by the user, R.id.shareViaLinkHideListPermissionSwitch
+         * @param isChecked  New switch state.
+         */
+        @Override
+        public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
+            if (!isResumed()) {
+                // very important, setChecked(...) is called automatically during
+                // Fragment recreation on device rotations
+                return;
+            }
+
+            if (mCapabilities.getFilesFileDrop().isTrue()) {
+                ((FileActivity) getActivity()).getFileOperationsHelper().
+                        setHideFileListingPermissionsToShare(
+                                mPublicShare,
+                                isChecked
+                        );
+            } else {
+                // not supported in ownCloud
+                Snackbar.make(getView(), R.string.files_drop_not_supported, Snackbar.LENGTH_LONG)
+                        .setAction(R.string.learn_more, new View.OnClickListener(){
+                            @Override
+                            public void onClick(View v) {
+                                Intent i = new Intent(Intent.ACTION_VIEW);
+                                i.setData(Uri.parse(getString(R.string.url_server_install)));
+                                startActivity(i);
+                            }
+                        })
+                        .show();
+            }
+
+            // undo the toggle to grant the view will be correct if the dialog is cancelled
+            switchView.setOnCheckedChangeListener(null);
+            switchView.toggle();
+            switchView.setOnCheckedChangeListener(mOnHideFileListingPermissionInteractionListener);
+        }
     }
 
 
@@ -531,8 +580,7 @@ public class ShareFileFragment extends Fragment
         try {
             mListener = (ShareFragmentListener) activity;
         } catch (ClassCastException e) {
-            throw new ClassCastException(activity.toString()
-                    + " must implement OnShareFragmentInteractionListener");
+            throw new ClassCastException(activity.toString() + " must implement OnShareFragmentInteractionListener");
         }
     }
 
@@ -542,7 +590,6 @@ public class ShareFileFragment extends Fragment
         mListener = null;
     }
 
-
     /**
      * Get known server capabilities from DB
      * <p/>
@@ -551,12 +598,10 @@ public class ShareFileFragment extends Fragment
      */
     public void refreshCapabilitiesFromDB() {
         if (((FileActivity) mListener).getStorageManager() != null) {
-            mCapabilities = ((FileActivity) mListener).getStorageManager().
-                    getCapability(mAccount.name);
+            mCapabilities = ((FileActivity) mListener).getStorageManager().getCapability(mAccount.name);
         }
     }
 
-
     /**
      * Get users and groups from the DB to fill in the "share with" list.
      * <p/>
@@ -619,7 +664,6 @@ public class ShareFileFragment extends Fragment
         mListener.showEditShare(share);
     }
 
-
     /**
      * Get public link from the DB to fill in the "Share link" section in the UI.
      * <p/>
@@ -655,8 +699,8 @@ public class ShareFileFragment extends Fragment
     }
 
     /**
-     * Updates in the UI the section about public share with the information in the current
-     * public share bound to mFile, if any
+     * Updates in the UI the section about public share with the information in the current public share bound to
+     * mFile, if any.
      */
     private void updatePublicShareSection() {
         if (mPublicShare != null && ShareType.PUBLIC_LINK.equals(mPublicShare.getShareType())) {
@@ -674,9 +718,11 @@ public class ShareFileFragment extends Fragment
             getPasswordSection().setVisibility(View.VISIBLE);
             if (mFile.isFolder() && !mCapabilities.getFilesSharingPublicUpload().isFalse()) {
                 getEditPermissionSection().setVisibility(View.VISIBLE);
+                getHideFileListingPermissionSection().setVisibility(View.VISIBLE);
             } else {
                 getEditPermissionSection().setVisibility(View.GONE);
             }
+
             // GetLink button
             AppCompatButton getLinkButton = getGetLinkButton();
             getLinkButton.setVisibility(View.VISIBLE);
@@ -710,10 +756,9 @@ public class ShareFileFragment extends Fragment
                 }
                 getExpirationDateValue().setText(R.string.empty);
             }
+
             // recover listener
-            expirationDateSwitch.setOnCheckedChangeListener(
-                    mOnExpirationDateInteractionListener
-            );
+            expirationDateSwitch.setOnCheckedChangeListener(mOnExpirationDateInteractionListener);
 
             /// update state of password switch and message depending on password protection
             SwitchCompat passwordSwitch = getPasswordSwitch();
@@ -730,10 +775,9 @@ public class ShareFileFragment extends Fragment
                 }
                 getPasswordValue().setVisibility(View.INVISIBLE);
             }
+
             // recover listener
-            passwordSwitch.setOnCheckedChangeListener(
-                    mOnPasswordInteractionListener
-            );
+            passwordSwitch.setOnCheckedChangeListener(mOnPasswordInteractionListener);
 
             /// update state of the edit permission switch
             SwitchCompat editPermissionSwitch = getEditPermissionSwitch();
@@ -744,14 +788,29 @@ public class ShareFileFragment extends Fragment
                 if (!editPermissionSwitch.isChecked()) {
                     editPermissionSwitch.toggle();
                 }
+                getHideFileListingPermissionSection().setVisibility(View.VISIBLE);
             } else {
                 if (editPermissionSwitch.isChecked()) {
                     editPermissionSwitch.toggle();
                 }
+                getHideFileListingPermissionSection().setVisibility(View.GONE);
             }
+
             // recover listener
-            editPermissionSwitch.setOnCheckedChangeListener(
-                    mOnEditPermissionInteractionListener
+            editPermissionSwitch.setOnCheckedChangeListener(mOnEditPermissionInteractionListener);
+
+            /// update state of the hide file listing permission switch
+            SwitchCompat hideFileListingPermissionSwitch = getHideFileListingPermissionSwitch();
+
+            // set null listener before setChecked() to prevent infinite loop of calls
+            hideFileListingPermissionSwitch.setOnCheckedChangeListener(null);
+
+            boolean readOnly = (mPublicShare.getPermissions() & OCShare.READ_PERMISSION_FLAG) != 0;
+            hideFileListingPermissionSwitch.setChecked(!readOnly);
+
+            // recover listener
+            hideFileListingPermissionSwitch.setOnCheckedChangeListener(
+                    mOnHideFileListingPermissionInteractionListener
             );
 
         } else {
@@ -767,6 +826,7 @@ public class ShareFileFragment extends Fragment
             getExpirationDateSection().setVisibility(View.GONE);
             getPasswordSection().setVisibility(View.GONE);
             getEditPermissionSection().setVisibility(View.GONE);
+            getHideFileListingPermissionSection().setVisibility(View.GONE);
             getGetLinkButton().setVisibility(View.GONE);
         }
     }
@@ -810,6 +870,14 @@ public class ShareFileFragment extends Fragment
         return (SwitchCompat) getView().findViewById(R.id.shareViaLinkEditPermissionSwitch);
     }
 
+    private SwitchCompat getHideFileListingPermissionSwitch() {
+        return (SwitchCompat) getView().findViewById(R.id.shareViaLinkFileListingPermissionSwitch);
+    }
+
+    private View getHideFileListingPermissionSection() {
+        return getView().findViewById(R.id.shareViaLinkHideFileListingPermissionSection);
+    }
+
     private AppCompatButton getGetLinkButton() {
         return (AppCompatButton) getView().findViewById(R.id.shareViaLinkGetLinkButton);
     }
@@ -823,6 +891,7 @@ public class ShareFileFragment extends Fragment
         getPasswordSection().setVisibility(View.GONE);
         getEditPermissionSection().setVisibility(View.GONE);
         getGetLinkButton().setVisibility(View.GONE);
+        getHideFileListingPermissionSection().setVisibility(View.GONE);
     }
 
     public static void setListViewHeightBasedOnChildren(ListView listView) {
@@ -862,7 +931,8 @@ public class ShareFileFragment extends Fragment
 
     /**
      * Hide share features sections that are not enabled
-     * @param view
+     *
+     * @param view share file view
      */
     private void hideNotEnabledShareSections(View view) {
         LinearLayout shareWithUsersSection = (LinearLayout) view.findViewById(R.id.shareWithUsersSection);
@@ -881,5 +951,4 @@ public class ShareFileFragment extends Fragment
             shareWithUsersSection.setVisibility(View.GONE);
         }
     }
-
 }