Merge pull request #1510 from owncloud/edit_public_share_permission

Added option to "Allow editing" folders publicly shared
This commit is contained in:
David A. Velasco 2016-03-21 13:02:06 +01:00
commit 15e2c24614
7 changed files with 230 additions and 54 deletions

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

View file

@ -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"

View file

@ -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>

View file

@ -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

View file

@ -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()) {

View file

@ -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);

View file

@ -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);
}