浏览代码

allow to set/edit note on shares

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 6 年之前
父节点
当前提交
d0a3302212

+ 1 - 1
build.gradle

@@ -214,7 +214,7 @@ dependencies {
 //    implementation project('nextcloud-android-library')
     genericImplementation "com.github.nextcloud:android-library:master-SNAPSHOT"
     gplayImplementation "com.github.nextcloud:android-library:master-SNAPSHOT"
-    versionDevImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT' // use always latest master
+    versionDevImplementation "com.github.nextcloud:android-library:master-SNAPSHOT" // use always latest master
     implementation 'com.android.support.constraint:constraint-layout:1.1.3'
     implementation "com.android.support:support-v4:${supportLibraryVersion}"
     implementation "com.android.support:design:${supportLibraryVersion}"

+ 9 - 20
src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -1000,16 +1000,13 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
         cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
         cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-        cv.put(
-                ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
-                share.getSharedWithDisplayName()
-        );
+        cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
         cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
         cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
         cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId());
         cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
-
         cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0);
+        cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote());
 
         if (shareExistsForRemoteId(share.getRemoteId())) {// for renamed files; no more delete and create
             overriden = true;
@@ -1215,6 +1212,7 @@ public class FileDataStorageManager {
             share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
             share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
             share.setIsPasswordProtected(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED)) == 1);
+            share.setNote(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_NOTE)));
         }
         return share;
     }
@@ -1313,16 +1311,13 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-                cv.put(
-                        ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
-                        share.getSharedWithDisplayName()
-                );
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId());
                 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
-
                 cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0);
+                cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote());
 
                 if (shareExistsForRemoteId(share.getRemoteId())) {
                     // updating an existing file
@@ -1596,23 +1591,17 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-                cv.put(
-                        ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
-                        share.getSharedWithDisplayName()
-                );
+                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId());
                 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
-
                 cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0);
+                cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote());
 
                 // adding a new share resource
-                operations.add(
-                        ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
-                                withValues(cv).
-                                build()
-                );
+                operations.add(ContentProviderOperation.newInsert(
+                        ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
             }
         }
         return operations;

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

@@ -32,7 +32,7 @@ import com.owncloud.android.MainApp;
 public class ProviderMeta {
 
     public static final String DB_NAME = "filelist";
-    public static final int DB_VERSION = 34;
+    public static final int DB_VERSION = 35;
 
     private ProviderMeta() {
     }
@@ -129,6 +129,7 @@ public class ProviderMeta {
         public static final String OCSHARES_ID_REMOTE_SHARED = "id_remote_shared";
         public static final String OCSHARES_ACCOUNT_OWNER = "owner_share";
         public static final String OCSHARES_IS_PASSWORD_PROTECTED = "is_password_protected";
+        public static final String OCSHARES_NOTE = "note";
 
         public static final String OCSHARES_DEFAULT_SORT_ORDER = OCSHARES_FILE_SOURCE
                 + " collate nocase asc";

+ 70 - 0
src/main/java/com/owncloud/android/operations/UpdateNoteForShareOperation.java

@@ -0,0 +1,70 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.operations;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.shares.GetRemoteShareOperation;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.UpdateRemoteShareOperation;
+import com.owncloud.android.operations.common.SyncOperation;
+
+
+/**
+ * Updates a note of a private share.
+ */
+public class UpdateNoteForShareOperation extends SyncOperation {
+
+    private long shareId;
+    private String note;
+
+    public UpdateNoteForShareOperation(long shareId, String note) {
+        this.shareId = shareId;
+        this.note = note;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+
+        OCShare share = getStorageManager().getShareById(shareId);
+
+        if (share == null) {
+            return new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND);
+        }
+
+        UpdateRemoteShareOperation updateOperation = new UpdateRemoteShareOperation(share.getRemoteId());
+        updateOperation.setNote(note);
+        RemoteOperationResult result = updateOperation.execute(client);
+
+        if (result.isSuccess()) {
+            RemoteOperation getShareOp = new GetRemoteShareOperation(share.getRemoteId());
+            result = getShareOp.execute(client);
+            if (result.isSuccess()) {
+                getStorageManager().saveShare((OCShare) result.getData().get(0));
+            }
+        }
+
+        return result;
+    }
+}
+

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

@@ -770,7 +770,8 @@ public class FileContentProvider extends ContentProvider {
                 + ProviderTableMeta.OCSHARES_USER_ID + INTEGER
                 + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + INTEGER
                 + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + TEXT
-                + ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED + " INTEGER );");
+                + ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED + INTEGER
+                + ProviderTableMeta.OCSHARES_NOTE + " TEXT );");
     }
 
     private void createCapabilitiesTable(SQLiteDatabase db) {
@@ -1745,6 +1746,24 @@ public class FileContentProvider extends ContentProvider {
             if (!upgraded) {
                 Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
             }
+
+            if (oldVersion < 35 && newVersion >= 35) {
+                Log_OC.i(SQL, "Entering in the #35 add note to share table");
+                db.beginTransaction();
+                try {
+                    db.execSQL(ALTER_TABLE + ProviderTableMeta.OCSHARES_TABLE_NAME +
+                            ADD_COLUMN + ProviderTableMeta.OCSHARES_NOTE + " TEXT ");
+
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
+            if (!upgraded) {
+                Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
+            }
         }
 
         @Override

+ 150 - 136
src/main/java/com/owncloud/android/services/OperationsService.java

@@ -70,6 +70,7 @@ import com.owncloud.android.operations.RestoreFileVersionOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
 import com.owncloud.android.operations.UnshareOperation;
+import com.owncloud.android.operations.UpdateNoteForShareOperation;
 import com.owncloud.android.operations.UpdateSharePermissionsOperation;
 import com.owncloud.android.operations.UpdateShareViaLinkOperation;
 import com.owncloud.android.operations.common.SyncOperation;
@@ -103,6 +104,7 @@ public class OperationsService extends Service {
     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_SHARE_NOTE = "SHARE_NOTE";
     public static final String EXTRA_USER_ID = "USER_ID";
     public static final String EXTRA_IN_BACKGROUND = "IN_BACKGROUND";
 
@@ -112,6 +114,7 @@ public class OperationsService extends Service {
     public static final String ACTION_CREATE_SHARE_WITH_SHAREE = "CREATE_SHARE_WITH_SHAREE";
     public static final String ACTION_UNSHARE = "UNSHARE";
     public static final String ACTION_UPDATE_SHARE = "UPDATE_SHARE";
+    public static final String ACTION_UPDATE_SHARE_NOTE = "UPDATE_SHARE_NOTE";
     public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO";
     public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN";
     public static final String ACTION_GET_USER_NAME = "GET_USER_NAME";
@@ -529,7 +532,7 @@ public class OperationsService extends Service {
      * @return                      Pair with the new operation object and the information about its
      *                              target server.
      */
-    private Pair<Target , RemoteOperation> newOperation(Intent operationIntent) {
+    private Pair<Target, RemoteOperation> newOperation(Intent operationIntent) {
         RemoteOperation operation = null;
         Target target = null;
         try {
@@ -548,154 +551,165 @@ public class OperationsService extends Service {
                 );
                 
                 String action = operationIntent.getAction();
+                String remotePath;
+                String password;
+                ShareType shareType;
+                String newParentPath;
+                long shareId;
+
+                switch (action) {
+                    case ACTION_CREATE_SHARE_VIA_LINK:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
+                        if (remotePath.length() > 0) {
+                            operation = new CreateShareViaLinkOperation(remotePath, password);
+                        }
+                        break;
 
-                if (ACTION_CREATE_SHARE_VIA_LINK.equals(action)) {  // Create public share via link
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
-                    if (remotePath.length() > 0) {
-                        operation = new CreateShareViaLinkOperation(
-                                remotePath,
-                                password
-                        );
-                    }
+                    case ACTION_UPDATE_SHARE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        shareId = operationIntent.getLongExtra(EXTRA_SHARE_ID, -1);
 
-                } else if (ACTION_UPDATE_SHARE.equals(action)) {
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    long shareId = operationIntent.getLongExtra(EXTRA_SHARE_ID, -1);
-                    if (remotePath != null && remotePath.length() > 0) {
-                        operation = new UpdateShareViaLinkOperation(remotePath);
+                        if (remotePath != null && remotePath.length() > 0) {
+                            UpdateShareViaLinkOperation updateLinkOperation = new UpdateShareViaLinkOperation(remotePath);
 
-                        String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
-                        ((UpdateShareViaLinkOperation) operation).setPassword(password);
+                            password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
+                            updateLinkOperation.setPassword(password);
 
-                        long expirationDate = operationIntent.getLongExtra(
-                                EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS,
-                                0
-                        );
-                        ((UpdateShareViaLinkOperation)operation).setExpirationDate(
-                                expirationDate
-                        );
+                            long expirationDate = operationIntent.getLongExtra(EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS, 0);
+                            updateLinkOperation.setExpirationDate(expirationDate);
 
-                        if (operationIntent.hasExtra(EXTRA_SHARE_PUBLIC_UPLOAD)) {
-                            ((UpdateShareViaLinkOperation) operation).setPublicUpload(
-                                operationIntent.getBooleanExtra(EXTRA_SHARE_PUBLIC_UPLOAD, false)
-                            );
+                            if (operationIntent.hasExtra(EXTRA_SHARE_PUBLIC_UPLOAD)) {
+                                updateLinkOperation.setPublicUpload(
+                                        operationIntent.getBooleanExtra(EXTRA_SHARE_PUBLIC_UPLOAD, false));
+                            }
+                            operation = updateLinkOperation;
+                        } else if (shareId > 0) {
+                            UpdateSharePermissionsOperation updateShare = new UpdateSharePermissionsOperation(shareId);
+
+                            int permissions = operationIntent.getIntExtra(EXTRA_SHARE_PERMISSIONS, -1);
+                            updateShare.setPermissions(permissions);
+
+                            long expirationDateInMillis = operationIntent
+                                    .getLongExtra(EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS, 0L);
+                            updateShare.setExpirationDate(expirationDateInMillis);
+
+                            password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
+                            updateShare.setPassword(password);
+
+                            operation = updateShare;
+                        }
+                        break;
+
+                    case ACTION_UPDATE_SHARE_NOTE:
+                        shareId = operationIntent.getLongExtra(EXTRA_SHARE_ID, -1);
+                        String note = operationIntent.getStringExtra(EXTRA_SHARE_NOTE);
+
+                        if (shareId > 0) {
+                            operation = new UpdateNoteForShareOperation(shareId, note);
                         }
+                        break;
 
-                    } else if (shareId > 0) {
-                        operation = new UpdateSharePermissionsOperation(shareId);
+                    case ACTION_CREATE_SHARE_WITH_SHAREE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        String shareeName = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
+                        shareType = (ShareType) operationIntent.getSerializableExtra(EXTRA_SHARE_TYPE);
                         int permissions = operationIntent.getIntExtra(EXTRA_SHARE_PERMISSIONS, -1);
-                        ((UpdateSharePermissionsOperation)operation).setPermissions(permissions);
-                        long expirationDateInMillis = operationIntent.getLongExtra(EXTRA_SHARE_EXPIRATION_DATE_IN_MILLIS, 0L);
-                        ((UpdateSharePermissionsOperation)operation).setExpirationDate(expirationDateInMillis);
-                        String password = operationIntent.getStringExtra(EXTRA_SHARE_PASSWORD);
-                        ((UpdateSharePermissionsOperation)operation).setPassword(password);
-                    }
+                        if (remotePath.length() > 0) {
+                            operation = new CreateShareWithShareeOperation(remotePath, shareeName, shareType,
+                                    permissions);
+                        }
+                        break;
 
-                } else if (ACTION_CREATE_SHARE_WITH_SHAREE.equals(action)) {
-                    // Create private share with user or group
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    String shareeName = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
-                    ShareType shareType = (ShareType) operationIntent.getSerializableExtra(EXTRA_SHARE_TYPE);
-                    int permissions = operationIntent.getIntExtra(EXTRA_SHARE_PERMISSIONS, -1);
-                    if (remotePath.length() > 0) {
-                        operation = new CreateShareWithShareeOperation(
-                                remotePath,
-                                shareeName,
-                                shareType,
-                                permissions
-                        );
-                    }
+                    case ACTION_UNSHARE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        shareType = (ShareType) operationIntent.getSerializableExtra(EXTRA_SHARE_TYPE);
+                        String shareWith = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
 
-                } else if (ACTION_UNSHARE.equals(action)) {  // Unshare file
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    ShareType shareType = (ShareType) operationIntent.
-                            getSerializableExtra(EXTRA_SHARE_TYPE);
-                    String shareWith = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
-                    if (remotePath.length() > 0) {
-                        operation = new UnshareOperation(
+                        if (remotePath.length() > 0) {
+                            operation = new UnshareOperation(remotePath, shareType, shareWith, this);
+                        }
+                        break;
+
+                    case ACTION_GET_SERVER_INFO:
+                        operation = new GetServerInfoOperation(serverUrl, this);
+                        break;
+
+                    case ACTION_OAUTH2_GET_ACCESS_TOKEN:
+                        String oauth2QueryParameters = operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS);
+                        operation = new OAuth2GetAccessToken(getString(R.string.oauth2_client_id),
+                                getString(R.string.oauth2_redirect_uri), getString(R.string.oauth2_grant_type),
+                                oauth2QueryParameters);
+                        break;
+
+                    case ACTION_GET_USER_NAME:
+                        operation = new GetRemoteUserInfoOperation();
+                        break;
+
+                    case ACTION_RENAME:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        String newName = operationIntent.getStringExtra(EXTRA_NEWNAME);
+                        operation = new RenameFileOperation(remotePath, newName);
+                        break;
+
+                    case ACTION_REMOVE:
+                        // Remove file or folder
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false);
+                        boolean inBackground = operationIntent.getBooleanExtra(EXTRA_IN_BACKGROUND, false);
+                        operation = new RemoveFileOperation(remotePath, onlyLocalCopy, account, inBackground,
+                                getApplicationContext());
+                        break;
+
+                    case ACTION_CREATE_FOLDER:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true);
+                        operation = new CreateFolderOperation(remotePath, createFullPath);
+                        break;
+
+                    case ACTION_SYNC_FILE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
+                        operation = new SynchronizeFileOperation(remotePath, account, syncFileContents,
+                                getApplicationContext());
+                        break;
+
+                    case ACTION_SYNC_FOLDER:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        operation = new SynchronizeFolderOperation(
+                                this,                       // TODO remove this dependency from construction time
                                 remotePath,
-                                shareType,
-                                shareWith,
-                                this
+                                account,
+                                System.currentTimeMillis()  // TODO remove this dependency from construction time
                         );
-                    }
-                    
-                } else if (ACTION_GET_SERVER_INFO.equals(action)) {
-                    // check OC server and get basic information from it
-                    operation = new GetServerInfoOperation(serverUrl, this);
-
-                } else if (ACTION_OAUTH2_GET_ACCESS_TOKEN.equals(action)) {
-                    /// GET ACCESS TOKEN to the OAuth server
-                    String oauth2QueryParameters =
-                            operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS);
-                    operation = new OAuth2GetAccessToken(
-                            getString(R.string.oauth2_client_id), 
-                            getString(R.string.oauth2_redirect_uri),       
-                            getString(R.string.oauth2_grant_type),
-                            oauth2QueryParameters);
-
-                } else if (ACTION_GET_USER_NAME.equals(action)) {
-                    // Get User Name
-                    operation = new GetRemoteUserInfoOperation();
-                    
-                } else if (ACTION_RENAME.equals(action)) {
-                    // Rename file or folder
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    String newName = operationIntent.getStringExtra(EXTRA_NEWNAME);
-                    operation = new RenameFileOperation(remotePath, newName);
-                    
-                } else if (ACTION_REMOVE.equals(action)) {
-                    // Remove file or folder
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    boolean onlyLocalCopy = operationIntent.getBooleanExtra(EXTRA_REMOVE_ONLY_LOCAL, false);
-                    boolean inBackground = operationIntent.getBooleanExtra(EXTRA_IN_BACKGROUND, false);
-                    operation = new RemoveFileOperation(remotePath, onlyLocalCopy, account, inBackground,
-                            getApplicationContext());
-                    
-                } else if (ACTION_CREATE_FOLDER.equals(action)) {
-                    // Create Folder
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    boolean createFullPath = operationIntent.getBooleanExtra(EXTRA_CREATE_FULL_PATH, true);
-                    operation = new CreateFolderOperation(remotePath, createFullPath);
-
-                } else if (ACTION_SYNC_FILE.equals(action)) {
-                    // Sync file
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    boolean syncFileContents = operationIntent.getBooleanExtra(EXTRA_SYNC_FILE_CONTENTS, true);
-                    operation = new SynchronizeFileOperation(remotePath, account, syncFileContents,
-                            getApplicationContext());
-                    
-                } else if (ACTION_SYNC_FOLDER.equals(action)) {
-                    // Sync folder (all its descendant files are sync'ed)
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    operation = new SynchronizeFolderOperation(
-                            this,                       // TODO remove this dependency from construction time
-                            remotePath,
-                            account, 
-                            System.currentTimeMillis()  // TODO remove this dependency from construction time
-                    );
-
-                } else if (ACTION_MOVE_FILE.equals(action)) {
-                    // Move file/folder
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
-                    operation = new MoveFileOperation(remotePath, newParentPath);
-
-                } else if (ACTION_COPY_FILE.equals(action)) {
-                    // Copy file/folder
-                    String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                    String newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
-                    operation = new CopyFileOperation(remotePath, newParentPath);
-
-                } else if (ACTION_CHECK_CURRENT_CREDENTIALS.equals(action)) {
-                    // Check validity of currently stored credentials for a given account
+                        break;
+
+                    case ACTION_MOVE_FILE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
+                        operation = new MoveFileOperation(remotePath, newParentPath);
+                        break;
+
+                    case ACTION_COPY_FILE:
+                        remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        newParentPath = operationIntent.getStringExtra(EXTRA_NEW_PARENT_PATH);
+                        operation = new CopyFileOperation(remotePath, newParentPath);
+                        break;
+
+                    case ACTION_CHECK_CURRENT_CREDENTIALS:
                     operation = new CheckCurrentCredentialsOperation(account);
-                } else if (ACTION_RESTORE_VERSION.equals(action)) {
-                    FileVersion fileVersion = operationIntent.getParcelableExtra(EXTRA_FILE_VERSION);
-                    String userId = operationIntent.getStringExtra(EXTRA_USER_ID);
-                    operation = new RestoreFileVersionOperation(fileVersion.getRemoteId(), fileVersion.getFileName(),
-                            userId);
+                        break;
+
+                    case ACTION_RESTORE_VERSION:
+                        FileVersion fileVersion = operationIntent.getParcelableExtra(EXTRA_FILE_VERSION);
+                        String userId = operationIntent.getStringExtra(EXTRA_USER_ID);
+                        operation = new RestoreFileVersionOperation(fileVersion.getRemoteId(),
+                                fileVersion.getFileName(), userId);
+                        break;
+
+                    default:
+                        // do nothing
+                        break;
                 }
             }
                 

+ 17 - 6
src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -86,7 +86,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
-import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.media.MediaService;
 import com.owncloud.android.media.MediaServiceBinder;
@@ -101,6 +100,7 @@ import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.RestoreFileVersionOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.UnshareOperation;
+import com.owncloud.android.operations.UpdateNoteForShareOperation;
 import com.owncloud.android.operations.UpdateSharePermissionsOperation;
 import com.owncloud.android.operations.UpdateShareViaLinkOperation;
 import com.owncloud.android.operations.UploadFileOperation;
@@ -191,8 +191,6 @@ public class FileDisplayActivity extends HookActivity
 
     public static final String TEXT_PREVIEW = "TEXT_PREVIEW";
 
-    private static final String VERSION_DOT = ".";
-
     private OCFile mWaitingToPreview;
 
     private boolean mSyncInProgress;
@@ -374,9 +372,7 @@ public class FileDisplayActivity extends HookActivity
                 OwnCloudVersion serverVersion = AccountUtils.getServerVersionForAccount(account, this);
 
                 if (serverVersion == null) {
-                    OCCapability capability = getCapabilities();
-                    serverVersion = new OwnCloudVersion(capability.getVersionMayor() + VERSION_DOT +
-                            capability.getVersionMinor() + VERSION_DOT + capability.getVersionMicro());
+                    serverVersion = getCapabilities().getVersion();
                 }
 
                 if (MainApp.OUTDATED_SERVER_VERSION.compareTo(serverVersion) >= 0) {
@@ -1787,6 +1783,8 @@ public class FileDisplayActivity extends HookActivity
             onUpdateShareInformation(result, R.string.unsharing_failed);
         } else if (operation instanceof RestoreFileVersionOperation) {
             onRestoreFileVersionOperationFinish(result);
+        } else if (operation instanceof UpdateNoteForShareOperation) {
+            onUpdateNoteForShareOperationFinish(result);
         }
     }
 
@@ -1968,6 +1966,19 @@ public class FileDisplayActivity extends HookActivity
         }
     }
 
+    private void onUpdateNoteForShareOperationFinish(RemoteOperationResult result) {
+        FileDetailFragment fileDetailFragment = getShareFileFragment();
+
+        if (result.isSuccess()) {
+            if (fileDetailFragment != null && fileDetailFragment.getFileDetailSharingFragment() != null) {
+                fileDetailFragment.getFileDetailSharingFragment().refreshPublicShareFromDB();
+                fileDetailFragment.getFileDetailSharingFragment().onUpdateShareInformation(result, getFile());
+            }
+        } else {
+            DisplayUtils.showSnackMessage(this, R.string.note_could_not_sent);
+        }
+    }
+
     private void copyAndShareFileLink(String link) {
         ClipboardUtil.copyToClipboard(this, link, false);
         Snackbar snackbar = Snackbar.make(

+ 12 - 4
src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java

@@ -47,6 +47,7 @@ import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.services.OperationsService;
 import com.owncloud.android.ui.TextDrawable;
 import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
+import com.owncloud.android.ui.dialog.NoteDialogFragment;
 import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
@@ -200,6 +201,8 @@ public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.UserVi
 
         MenuItem reshareItem = menu.findItem(R.id.action_can_reshare);
 
+        MenuItem sendNoteItem = menu.findItem(R.id.action_share_send_note);
+
         if (isReshareForbidden(share)) {
             reshareItem.setVisible(false);
         }
@@ -237,6 +240,8 @@ public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.UserVi
 
         SharingMenuHelper.setupExpirationDateMenuItem(
                 menu.findItem(R.id.action_expiration_date), share.getExpirationDate(), context.getResources());
+
+        sendNoteItem.setVisible(capabilities.getVersion().isNoteOnShareSupported());
     }
 
     private boolean isEditOptionsAvailable(OCShare share) {
@@ -324,12 +329,13 @@ public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.UserVi
             }
             case R.id.action_expiration_date: {
                 ExpirationDatePickerDialogFragment dialog = ExpirationDatePickerDialogFragment.newInstance(share, -1);
-                dialog.show(
-                        fragmentManager,
-                        ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG
-                );
+                dialog.show(fragmentManager, ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG);
                 return true;
             }
+            case R.id.action_share_send_note:
+                NoteDialogFragment dialog = NoteDialogFragment.newInstance(share);
+                dialog.show(fragmentManager, NoteDialogFragment.NOTE_FRAGMENT);
+                return true;
             default:
                 return true;
         }
@@ -406,6 +412,8 @@ public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.UserVi
                                      boolean canEditChange,
                                      boolean canEditDelete);
 
+        void updateNoteToShare(OCShare share, String note);
+        
         /**
          * show a snackbar that this feature is not supported by ownCloud.
          */

+ 141 - 0
src/main/java/com/owncloud/android/ui/dialog/NoteDialogFragment.java

@@ -0,0 +1,141 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.dialog;
+
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.graphics.PorterDuff;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager.LayoutParams;
+import android.widget.EditText;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.ui.activity.ComponentsGetter;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.ThemeUtils;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+/**
+ * Dialog to input a multiline note for a share
+ */
+public class NoteDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
+
+    private static final String ARG_SHARE = "SHARE";
+
+    public static final String NOTE_FRAGMENT = "NOTE_FRAGMENT";
+
+    private OCShare share;
+    private Unbinder unbinder;
+
+    @BindView(R.id.user_input)
+    EditText noteEditText;
+
+    public static NoteDialogFragment newInstance(OCShare share) {
+        NoteDialogFragment frag = new NoteDialogFragment();
+
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_SHARE, share);
+        frag.setArguments(args);
+
+        return frag;
+
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        int color = ThemeUtils.primaryAccentColor(getContext());
+
+        AlertDialog alertDialog = (AlertDialog) getDialog();
+
+        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(color);
+        alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(color);
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        int accentColor = ThemeUtils.primaryAccentColor(getContext());
+        share = getArguments().getParcelable(ARG_SHARE);
+
+        // Inflate the layout for the dialog
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+        View view = inflater.inflate(R.layout.note_dialog, null, false);
+
+        unbinder = ButterKnife.bind(this, view);
+
+        // Setup layout 
+        noteEditText.setText(share.getNote());
+        noteEditText.requestFocus();
+        noteEditText.getBackground().setColorFilter(accentColor, PorterDuff.Mode.SRC_ATOP);
+
+        // Build the dialog  
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setView(view)
+                .setPositiveButton(R.string.note_confirm, this)
+                .setNegativeButton(R.string.common_cancel, this)
+                .setTitle(ThemeUtils.getColoredTitle(getResources().getString(R.string.send_note),
+                        accentColor));
+        Dialog dialog = builder.create();
+
+        Window window = dialog.getWindow();
+
+        if (window != null) {
+            window.setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+        }
+
+        return dialog;
+    }
+
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which == AlertDialog.BUTTON_POSITIVE) {
+            ComponentsGetter componentsGetter = (ComponentsGetter) getActivity();
+
+            if (componentsGetter != null) {
+                componentsGetter.getFileOperationsHelper().updateNoteToShare(share,
+                        noteEditText.getText().toString().trim());
+            } else {
+                DisplayUtils.showSnackMessage(getActivity(), R.string.note_could_not_sent);
+            }
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+
+        unbinder.unbind();
+    }
+}

+ 12 - 0
src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java

@@ -58,6 +58,7 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.adapter.UserListAdapter;
 import com.owncloud.android.ui.decoration.SimpleListItemDividerDecoration;
 import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
+import com.owncloud.android.ui.dialog.NoteDialogFragment;
 import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
 import com.owncloud.android.ui.fragment.util.FileDetailSharingFragmentHelper;
 import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
@@ -317,6 +318,8 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
                 publicShare.getExpirationDate(),
                 res
         );
+
+        menu.findItem(R.id.action_share_send_note).setVisible(capabilities.getVersion().isNoteOnShareSupported());
     }
 
     private boolean optionsItemSelected(MenuItem item) {
@@ -351,6 +354,10 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
                 }
                 return true;
             }
+            case R.id.action_share_send_note:
+                NoteDialogFragment dialog = NoteDialogFragment.newInstance(publicShare);
+                dialog.show(getActivity().getSupportFragmentManager(), NoteDialogFragment.NOTE_FRAGMENT);
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
@@ -441,6 +448,11 @@ public class FileDetailSharingFragment extends Fragment implements UserListAdapt
         return permissions;
     }
 
+    @Override
+    public void updateNoteToShare(OCShare share, String note) {
+        ((FileActivity) getActivity()).getFileOperationsHelper().updateNoteToShare(share, note);
+    }
+
     /**
      * Starts a dialog that requests a password to the user to protect a share link.
      *

+ 10 - 0
src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -669,6 +669,16 @@ public class FileOperationsHelper {
         queueShareIntent(updateShareIntent);
     }
 
+    public void updateNoteToShare(OCShare share, String note) {
+        Intent updateShareIntent = new Intent(mFileActivity, OperationsService.class);
+        updateShareIntent.setAction(OperationsService.ACTION_UPDATE_SHARE_NOTE);
+        updateShareIntent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_ID, share.getId());
+        updateShareIntent.putExtra(OperationsService.EXTRA_SHARE_NOTE, note);
+
+        queueShareIntent(updateShareIntent);
+    }
+
     public void sendShareFile(OCFile file, boolean hideNcSharingOptions) {
         // Show dialog
         FragmentManager fm = mFileActivity.getSupportFragmentManager();

+ 39 - 0
src/main/res/layout/note_dialog.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Nextcloud Android client application
+
+  @author Tobias Kaminsky
+  Copyright (C) 2018 Tobias Kaminsky
+  Copyright (C) 2018 Nextcloud GmbH.
+ 
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+ 
+  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 <https://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:gravity="clip_horizontal"
+              android:orientation="vertical"
+              android:padding="@dimen/standard_padding">
+
+    <EditText
+        android:id="@+id/user_input"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="@string/hint_note"
+        android:inputType="textCapSentences|textMultiLine|textNoSuggestions"
+        android:minLines="3"
+        android:lines="5"
+        android:scrollbars="vertical"/>
+
+</LinearLayout>

+ 6 - 0
src/main/res/menu/file_detail_sharing_link_menu.xml

@@ -44,4 +44,10 @@
         android:title="@string/share_via_link_send_link_label"
         app:showAsAction="never" />
 
+    <item
+        android:id="@+id/action_share_send_note"
+        android:showAsAction="never"
+        android:title="@string/share_send_note"
+        app:showAsAction="never"/>
+
 </menu>

+ 6 - 0
src/main/res/menu/file_detail_sharing_menu.xml

@@ -68,4 +68,10 @@
         android:title="@string/share_privilege_unshare"
         app:showAsAction="never" />
 
+    <item
+        android:id="@+id/action_share_send_note"
+        android:showAsAction="never"
+        android:title="@string/share_send_note"
+        app:showAsAction="never"/>
+
 </menu>

+ 5 - 0
src/main/res/values/strings.xml

@@ -822,5 +822,10 @@
     <string name="single_sign_on_request_token" formatted="true">Allow %1$s to access your Nextcloud account %2$s?</string>
     <string name="permission_deny">Deny</string>
     <string name="permission_allow">Allow</string>
+    <string name="share_send_note">Note to recipient</string>
+    <string name="note_confirm">Send</string>
+    <string name="send_note">Send note to recipient</string>
+    <string name="note_could_not_sent">Could not send note</string>
+    <string name="hint_note">Note</string>
 
 </resources>