Selaa lähdekoodia

Merge pull request #1510 from owncloud/edit_public_share_permission

Added option to "Allow editing" folders publicly shared
David A. Velasco 9 vuotta sitten
vanhempi
commit
15e2c24614

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit 996660b88c4e2b3cef08604963cf2c29491efa1b
+Subproject commit 573afa15382b67cc84f67fc9a7b2329a72ecb352

+ 34 - 0
res/layout/share_file_layout.xml

@@ -228,6 +228,40 @@
 
         </RelativeLayout>
 
+        <RelativeLayout
+            android:id="@+id/shareViaLinkEditPermissionSection"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="invisible"
+            >
+
+            <Switch
+                android:id="@+id/shareViaLinkEditPermissionSwitch"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
+                android:layout_centerInParent="true"
+                android:padding="8dp"
+                />
+
+            <TextView
+                android:id="@+id/shareViaLinkEditPermissionLabel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentStart="true"
+                android:layout_toLeftOf="@id/shareViaLinkEditPermissionSwitch"
+                android:layout_toStartOf="@id/shareViaLinkEditPermissionSwitch"
+                android:paddingTop="8dp"
+                android:paddingLeft="8dp"
+                android:paddingRight="8dp"
+                android:text="@string/share_via_link_edit_permission_label"
+                android:textSize="16sp"
+                />
+
+        </RelativeLayout>
+
         <android.support.v7.widget.AppCompatButton
             android:id="@+id/shareViaLinkGetLinkButton"
             style="@style/ownCloud.Button"

+ 1 - 0
res/values/strings.xml

@@ -382,6 +382,7 @@
     <string name="share_via_link_expiration_date_label">Set expiration date</string>
     <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_get_public_link_button">Get link</string>
 
     <string name="share_search">Search</string>

+ 20 - 0
src/com/owncloud/android/files/FileOperationsHelper.java

@@ -3,6 +3,7 @@
  *
  *   @author masensio
  *   @author David A. Velasco
+ *   @author Juan Carlos González Cabrero
  *   Copyright (C) 2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
@@ -409,6 +410,25 @@ public class FileOperationsHelper {
         queueShareIntent(updateShareIntent);
     }
 
+    /**
+     * Updates a public share on a folder to set its editing permission.
+     * Starts a request to do it in {@link OperationsService}
+     *
+     * @param folder                     Folder which editing permission of his public share will be modified.
+     * @param uploadPermission          New state of the permission for editing the folder shared via link.
+     */
+    public void setUploadPermissionsToShare(OCFile folder, boolean uploadPermission) {
+        Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
+        updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE);
+        updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        updateShareIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, folder.getRemotePath());
+        updateShareIntent.putExtra(
+                OperationsService.EXTRA_SHARE_PUBLIC_UPLOAD,
+                uploadPermission
+        );
+        queueShareIntent(updateShareIntent);
+    }
+
 
     /**
      * @return 'True' if the server supports the Search Users API

+ 12 - 2
src/com/owncloud/android/operations/UpdateShareViaLinkOperation.java

@@ -31,8 +31,6 @@ import com.owncloud.android.lib.resources.shares.ShareType;
 import com.owncloud.android.lib.resources.shares.UpdateRemoteShareOperation;
 import com.owncloud.android.operations.common.SyncOperation;
 
-import java.util.Calendar;
-
 
 /**
  * Updates an existing public share for a given file
@@ -42,6 +40,7 @@ public class UpdateShareViaLinkOperation extends SyncOperation {
 
     private String mPath;
     private String mPassword;
+    private boolean mPublicUpload;
     private long mExpirationDateInMillis;
 
     /**
@@ -54,6 +53,7 @@ public class UpdateShareViaLinkOperation extends SyncOperation {
         mPath = path;
         mPassword = null;
         mExpirationDateInMillis = 0;
+        mPublicUpload = false;
     }
 
 
@@ -81,6 +81,15 @@ public class UpdateShareViaLinkOperation extends SyncOperation {
         mExpirationDateInMillis = expirationDateInMillis;
     }
 
+    /**
+     * Enable upload permissions to update in Share resource.
+     *
+     * @param publicUpload    Upload Permission to set to the public link.
+     */
+    public void setPublicUpload(boolean publicUpload) {
+        mPublicUpload = publicUpload;
+    }
+
 
     @Override
     protected RemoteOperationResult run(OwnCloudClient client) {
@@ -104,6 +113,7 @@ public class UpdateShareViaLinkOperation extends SyncOperation {
         );
         updateOp.setPassword(mPassword);
         updateOp.setExpirationDate(mExpirationDateInMillis);
+        updateOp.setPublicUpload(mPublicUpload);
         RemoteOperationResult result = updateOp.execute(client);
 
         if (result.isSuccess()) {

+ 5 - 1
src/com/owncloud/android/services/OperationsService.java

@@ -95,6 +95,7 @@ public class OperationsService extends Service {
     public static final String EXTRA_SHARE_WITH = "SHARE_WITH";
     public static final String EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS = "SHARE_EXPIRATION_YEAR";
     public static final String EXTRA_SHARE_PERMISSIONS = "SHARE_PERMISSIONS";
+    public static final String EXTRA_SHARE_PUBLIC_UPLOAD = "SHARE_PUBLIC_UPLOAD";
     public static final String EXTRA_SHARE_ID = "SHARE_ID";
 
     public static final String EXTRA_COOKIE = "COOKIE";
@@ -576,7 +577,7 @@ public class OperationsService extends Service {
                         operation = new UpdateShareViaLinkOperation(remotePath);
 
                         String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
-                        ((UpdateShareViaLinkOperation)operation).setPassword(password);
+                        ((UpdateShareViaLinkOperation) operation).setPassword(password);
 
                         long expirationDate = operationIntent.getLongExtra(
                                 EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS,
@@ -586,6 +587,9 @@ public class OperationsService extends Service {
                                 expirationDate
                         );
 
+                        boolean publicUpload = operationIntent.getBooleanExtra(EXTRA_SHARE_PUBLIC_UPLOAD, false);
+                        ((UpdateShareViaLinkOperation) operation).setPublicUpload(publicUpload);
+
                     } else if (shareId > 0) {
                         operation = new UpdateSharePermissionsOperation(shareId);
                         int permissions = operationIntent.getIntExtra(EXTRA_SHARE_PERMISSIONS, 1);

+ 157 - 50
src/com/owncloud/android/ui/fragment/ShareFileFragment.java

@@ -1,22 +1,22 @@
 /**
- *   ownCloud Android client application
- *
- *   @author masensio
- *   @author David A. Velasco
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ownCloud Android client application
  *
+ * @author masensio
+ * @author David A. Velasco
+ * @author Juan Carlos González Cabrero
+ * Copyright (C) 2015 ownCloud Inc.
+ * <p/>
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ * <p/>
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * <p/>
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.ui.fragment;
@@ -55,57 +55,74 @@ import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.MimetypeIconUtil;
 
 import java.text.SimpleDateFormat;
-
 import java.util.ArrayList;
 import java.util.Date;
 
 /**
  * Fragment for Sharing a file with sharees (users or groups) or creating
  * a public link.
- *
+ * <p/>
  * A simple {@link Fragment} subclass.
- *
+ * <p/>
  * Activities that contain this fragment must implement the
  * {@link ShareFragmentListener} interface
  * to handle interaction events.
- *
+ * <p/>
  * Use the {@link ShareFileFragment#newInstance} factory method to
  * create an instance of this fragment.
  */
 public class ShareFileFragment extends Fragment
-        implements ShareUserListAdapter.ShareUserAdapterListener{
+        implements ShareUserListAdapter.ShareUserAdapterListener {
 
     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";
 
 //    /** Tag for dialog */
 //    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;
 
     /**
@@ -118,6 +135,11 @@ public class ShareFileFragment extends Fragment
      */
     private OnExpirationDateInteractionListener mOnExpirationDateInteractionListener = null;
 
+    /**
+     * Listener for user actions to set or unset edit permission on public link
+     */
+    private OnEditPermissionInteractionListener mOnEditPermissionInteractionListener = null;
+
 
     /**
      * Public factory method to create new ShareFileFragment instances.
@@ -215,6 +237,9 @@ public class ShareFileFragment extends Fragment
         // Set listener for user actions on password
         initPasswordListener(view);
 
+        // Set listener for user actions on edit permission
+        initEditPermissionListener(view);
+
         return view;
     }
 
@@ -223,7 +248,7 @@ public class ShareFileFragment extends Fragment
      * Binds listener for user actions to create or delete a public share
      * to the views receiving the user events.
      *
-     * @param shareView     Root view in the fragment.
+     * @param shareView Root view in the fragment.
      */
     private void initShareViaLinkListener(View shareView) {
         mOnShareViaLinkSwitchCheckedChangeListener = new OnShareViaLinkListener();
@@ -240,8 +265,8 @@ public class ShareFileFragment extends Fragment
         /**
          * Called by R.id.shareViaLinkSectionSwitch to create or delete a public link.
          *
-         * @param switchView    {@link Switch} toggled by the user, R.id.shareViaLinkSectionSwitch
-         * @param isChecked     New switch state.
+         * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkSectionSwitch
+         * @param isChecked  New switch state.
          */
         @Override
         public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
@@ -284,7 +309,7 @@ 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.
      *
-     * @param shareView     Root view in the fragment.
+     * @param shareView Root view in the fragment.
      */
     private void initExpirationListener(View shareView) {
         mOnExpirationDateInteractionListener = new OnExpirationDateInteractionListener();
@@ -308,8 +333,8 @@ public class ShareFileFragment extends Fragment
         /**
          * Called by R.id.shareViaLinkExpirationSwitch to set or clear the expiration date.
          *
-         * @param switchView    {@link Switch} toggled by the user, R.id.shareViaLinkExpirationSwitch
-         * @param isChecked     New switch state.
+         * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkExpirationSwitch
+         * @param isChecked  New switch state.
          */
         @Override
         public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
@@ -341,7 +366,7 @@ public class ShareFileFragment extends Fragment
          * 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.
+         * @param expirationView Label or value view touched by the user.
          */
         @Override
         public void onClick(View expirationView) {
@@ -368,7 +393,7 @@ 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.
      *
-     * @param shareView     Root view in the fragment.
+     * @param shareView Root view in the fragment.
      */
     private void initPasswordListener(View shareView) {
         mOnPasswordInteractionListener = new OnPasswordInteractionListener();
@@ -393,8 +418,8 @@ public class ShareFileFragment extends Fragment
         /**
          * Called by R.id.shareViaLinkPasswordSwitch to set or clear the password.
          *
-         * @param switchView    {@link Switch} toggled by the user, R.id.shareViaLinkPasswordSwitch
-         * @param isChecked     New switch state.
+         * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkPasswordSwitch
+         * @param isChecked  New switch state.
          */
         @Override
         public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
@@ -421,7 +446,7 @@ public class ShareFileFragment extends Fragment
          * Called by R.id.shareViaLinkPasswordLabel or R.id.shareViaLinkPasswordValue
          * to change the current password.
          *
-         * @param passwordView      Label or value view touched by the user.
+         * @param passwordView Label or value view touched by the user.
          */
         @Override
         public void onClick(View passwordView) {
@@ -432,6 +457,55 @@ public class ShareFileFragment extends Fragment
         }
     }
 
+    /**
+     * Binds listener for user actions that start any update the edit permissions
+     * for the public link to the views receiving the user events.
+     *
+     * @param shareView Root view in the fragment.
+     */
+    private void initEditPermissionListener(View shareView) {
+        mOnEditPermissionInteractionListener = new OnEditPermissionInteractionListener();
+
+        ((Switch) shareView.findViewById(R.id.shareViaLinkEditPermissionSwitch)).
+                setOnCheckedChangeListener(mOnEditPermissionInteractionListener);
+
+    }
+
+    /**
+     * Listener for user actions that start any update on the edit permissions for the public link.
+     */
+    private class OnEditPermissionInteractionListener
+            implements CompoundButton.OnCheckedChangeListener {
+
+        /**
+         * Called by R.id.shareViaLinkEditPermissionSwitch to set or clear the edit permission.
+         *
+         * @param switchView {@link Switch} toggled by the user, R.id.shareViaLinkEditPermissionSwitch
+         * @param isChecked  New switch state.
+         */
+        @Override
+        public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
+            if (!isResumed()) {
+                // very important, setCheched(...) is called automatically during
+                // Fragment recreation on device rotations
+                return;
+            }
+
+            ((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);
+        }
+
+    }
+
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
@@ -470,13 +544,13 @@ public class ShareFileFragment extends Fragment
 
     /**
      * Get known server capabilities from DB
-     *
+     * <p/>
      * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
      * instance ready to use. If not ready, does nothing.
      */
     public void refreshCapabilitiesFromDB() {
-        if (((FileActivity)mListener).getStorageManager() != null) {
-            mCapabilities = ((FileActivity)mListener).getStorageManager().
+        if (((FileActivity) mListener).getStorageManager() != null) {
+            mCapabilities = ((FileActivity) mListener).getStorageManager().
                     getCapability(mAccount.name);
         }
     }
@@ -484,11 +558,11 @@ public class ShareFileFragment extends Fragment
 
     /**
      * Get users and groups from the DB to fill in the "share with" list.
-     *
+     * <p/>
      * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
      * instance ready to use. If not ready, does nothing.
      */
-    public void refreshUsersOrGroupsListFromDB (){
+    public void refreshUsersOrGroupsListFromDB() {
         if (((FileActivity) mListener).getStorageManager() != null) {
             // Get Users and Groups
             mPrivateShares = ((FileActivity) mListener).getStorageManager().getSharesWithForAFile(
@@ -547,9 +621,9 @@ public class ShareFileFragment extends Fragment
 
     /**
      * Get public link from the DB to fill in the "Share link" section in the UI.
-     *
+     * <p/>
      * Takes into account server capabilities before reading database.
-     *
+     * <p/>
      * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
      * instance ready to use. If not ready, does nothing.
      */
@@ -571,7 +645,7 @@ public class ShareFileFragment extends Fragment
     }
 
     /**
-     * @return  'True' when public share is disabled in the server
+     * @return 'True' when public share is disabled in the server
      */
     private boolean isPublicShareDisabled() {
         return (mCapabilities != null &&
@@ -597,6 +671,11 @@ public class ShareFileFragment extends Fragment
             }
             getExpirationDateSection().setVisibility(View.VISIBLE);
             getPasswordSection().setVisibility(View.VISIBLE);
+            if (mFile.isFolder() && !mCapabilities.getFilesSharingPublicUpload().isFalse()) {
+                getEditPermissionSection().setVisibility(View.VISIBLE);
+            } else {
+                getEditPermissionSection().setVisibility(View.GONE);
+            }
             // GetLink button
             AppCompatButton getLinkButton = getGetLinkButton();
             getLinkButton.setVisibility(View.VISIBLE);
@@ -655,6 +734,24 @@ public class ShareFileFragment extends Fragment
                     mOnPasswordInteractionListener
             );
 
+            /// update state of the edit permission switch
+            Switch editPermissionSwitch = getEditPermissionSwitch();
+
+            // set null listener before setChecked() to prevent infinite loop of calls
+            editPermissionSwitch.setOnCheckedChangeListener(null);
+            if (mPublicShare.getPermissions() > OCShare.READ_PERMISSION_FLAG) {
+                if (!editPermissionSwitch.isChecked()) {
+                    editPermissionSwitch.toggle();
+                }
+            } else {
+                if (editPermissionSwitch.isChecked()) {
+                    editPermissionSwitch.toggle();
+                }
+            }
+            // recover listener
+            editPermissionSwitch.setOnCheckedChangeListener(
+                    mOnEditPermissionInteractionListener
+            );
 
         } else {
             /// no public share -> collapse section
@@ -668,6 +765,7 @@ public class ShareFileFragment extends Fragment
             }
             getExpirationDateSection().setVisibility(View.GONE);
             getPasswordSection().setVisibility(View.GONE);
+            getEditPermissionSection().setVisibility(View.GONE);
             getGetLinkButton().setVisibility(View.GONE);
         }
     }
@@ -703,6 +801,14 @@ public class ShareFileFragment extends Fragment
         return (TextView) getView().findViewById(R.id.shareViaLinkPasswordValue);
     }
 
+    private View getEditPermissionSection() {
+        return getView().findViewById(R.id.shareViaLinkEditPermissionSection);
+    }
+
+    private Switch getEditPermissionSwitch() {
+        return (Switch) getView().findViewById(R.id.shareViaLinkEditPermissionSwitch);
+    }
+
     private AppCompatButton getGetLinkButton() {
         return (AppCompatButton) getView().findViewById(R.id.shareViaLinkGetLinkButton);
     }
@@ -714,6 +820,7 @@ public class ShareFileFragment extends Fragment
         getShareViaLinkSwitch().setVisibility(View.GONE);
         getExpirationDateSection().setVisibility(View.GONE);
         getPasswordSection().setVisibility(View.GONE);
+        getEditPermissionSection().setVisibility(View.GONE);
         getGetLinkButton().setVisibility(View.GONE);
     }