Browse Source

Add circle support for searching / displaying

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 5 years ago
parent
commit
7eb0f66079

+ 11 - 0
.drone.yml

@@ -1,4 +1,5 @@
 kind: pipeline
+type: docker
 name: generic
 
 steps:
@@ -48,6 +49,7 @@ trigger:
 
 ---
 kind: pipeline
+type: docker
 name: gplay
 
 steps:
@@ -116,6 +118,13 @@ services:
       - su www-data -c "php /var/www/html/occ app:enable activity"
       - su www-data -c "git clone -b master https://github.com/nextcloud/text.git /var/www/html/apps/text/"
       - su www-data -c "php /var/www/html/occ app:enable text"
+      - su www-data -c "git clone -b master https://github.com/nextcloud/circles.git /var/www/html/apps/circles/"
+      - apt-get update; apt-get -y install composer
+      - su www-data -c "cd /var/www/html/apps/circles; composer install"
+      - su www-data -c "php /var/www/html/occ app:enable -f circles"
+      - su www-data -c "occ config:app:set circles --value 1 allow_non_ssl_links"
+      - su www-data -c "occ config:app:set circles --value 1 local_is_non_ssl"
+      - su www-data -c "php /var/www/html/occ circles:manage:create test public publicCircle
       - /usr/local/bin/run.sh
 
 trigger:
@@ -126,6 +135,7 @@ trigger:
     - pull_request
 ---
 kind: pipeline
+type: docker
 name: analysis
 
 steps:
@@ -175,6 +185,7 @@ trigger:
     - pull_request
 ---
 kind: pipeline
+type: docker
 name: qa
 
 steps:

+ 1 - 1
build.gradle

@@ -63,7 +63,7 @@ ext {
     daggerVersion = "2.27"
     markwonVersion =  "4.2.2"
     prismVersion = "2.0.0"
-    androidLibraryVersion = "master-SNAPSHOT"
+    androidLibraryVersion = "circle-SNAPSHOT"
 
     travisBuild = System.getenv("TRAVIS") == "true"
 

+ 27 - 0
drawable_resources/circles.svg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" viewBox="0 0 57 57" width="64" height="64"
+    version="1.1" id="svg10" sodipodi:docname="circles.svg" inkscape:version="0.92.4 5da689c313, 2019-01-14">
+    <metadata id="metadata16">
+        <rdf:RDF>
+            <cc:Work rdf:about="">
+                <dc:format>image/svg+xml</dc:format>
+                <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+            </cc:Work>
+        </rdf:RDF>
+    </metadata>
+    <defs id="defs14" />
+    <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10"
+        gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2"
+        inkscape:window-width="1920" inkscape:window-height="1141" id="namedview12" showgrid="false"
+        inkscape:zoom="7.375" inkscape:cx="33.445579" inkscape:cy="41.701636" inkscape:window-x="0"
+        inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg10" />
+    <path d="M7.1 28.5A21.4 21.4 0 0 1 28.5 7.1m10.7 40A21.4 21.4 0 0 1 10 39M39.2 10A21.4 21.4 0 0 1 47 39.2"
+        fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" id="path2"
+        style="stroke:#000000;stroke-opacity:1;stroke-width:3.99979687;stroke-miterlimit:4;stroke-dasharray:none;fill:none;fill-opacity:1" />
+    <circle cx="28.5" cy="7.1" r="6.5" fill="#fff" id="circle4" style="fill:#000000" />
+    <circle cx="39.2" cy="-10" r="6.5" transform="rotate(90)" fill="#fff" id="circle6" style="fill:#000000" />
+    <circle cx="39.2" cy="-47" r="6.5" transform="rotate(90)" fill="#fff" id="circle8" style="fill:#000000" />
+</svg>

BIN
screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToCircle.png


BIN
screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToGroup.png


BIN
screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToUser.png


BIN
screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png


+ 20 - 3
scripts/updateScreenshots.sh

@@ -11,11 +11,15 @@ if ( [[ ! $(emulator -list-avds | grep uiComparison -c) -eq 0 ]] ); then
     (sleep 5; echo "no") | avdmanager create avd -n uiComparison -c 100M -k "system-images;android-27;google_apis;x86" --abi "google_apis/x86"
 fi
 
-emulator -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 1>/dev/null &
+if [ $1 == "debug" ]; then
+  emulator -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-audio -skin 500x833 1>/dev/null &
+else
+  emulator -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 1>/dev/null &
+fi
 PID=$(echo $!)
 
 ## server
-docker run --name=uiComparison nextcloudci/server:server-17 1>/dev/null &
+docker run --name=uiComparison nextcloudci/server --entrypoint '/usr/local/bin/initnc.sh' 1>/dev/null &
 sleep 5
 IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' uiComparison)
 
@@ -24,13 +28,15 @@ if [[ $IP = "" ]]; then
     exit 1
 fi
 
+## wait for server to finish
+scripts/wait_for_server.sh $IP
+
 ## run on server
 cp gradle.properties gradle.properties_
 sed -i s"/server/$IP/" gradle.properties
 scripts/wait_for_emulator.sh
 
 # setup test server
-docker exec uiComparison /bin/sh -c "/usr/local/bin/initnc.sh"
 docker exec uiComparison /bin/sh -c "su www-data -c \"OC_PASS=user1 php /var/www/html/occ user:add --password-from-env --display-name='User One' user1\""
 docker exec uiComparison /bin/sh -c "su www-data -c \"OC_PASS=user2 php /var/www/html/occ user:add --password-from-env --display-name='User Two' user2\""
 docker exec uiComparison /bin/sh -c "su www-data -c \"OC_PASS=user3 php /var/www/html/occ user:add --password-from-env --display-name='User Three' user3\""
@@ -40,6 +46,13 @@ docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ grou
 docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ group:adduser users user2\""
 docker exec uiComparison /bin/sh -c "su www-data -c \"git clone -b master https://github.com/nextcloud/text.git /var/www/html/apps/text/\""
 docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ app:enable text\""
+docker exec uiComparison /bin/sh -c "su www-data -c \"git clone -b master https://github.com/nextcloud/circles.git /var/www/html/apps/circles/\""
+docker exec uiComparison /bin/sh -c "apt-get update; apt-get -y install composer"
+docker exec uiComparison /bin/sh -c "su www-data -c \"cd /var/www/html/apps/circles; composer install\""
+docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ app:enable -f circles\""
+docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ config:app:set circles --value 1 allow_non_ssl_links\""
+docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ config:app:set circles --value 1 local_is_non_ssl\""
+docker exec uiComparison /bin/sh -c "su www-data -c \"php /var/www/html/occ circles:manage:create test public publicCircle\""
 docker exec uiComparison /bin/sh -c "/usr/local/bin/run.sh"
 
 ## update/create all screenshots
@@ -59,6 +72,10 @@ docker exec uiComparison /bin/sh -c "/usr/local/bin/run.sh"
 
 mv gradle.properties_ gradle.properties
 
+if [ $1 == "debug" ]; then
+  exit
+fi
+
 # tidy up
 kill $PID
 docker stop uiComparison

+ 6 - 1
scripts/wait_for_server.sh

@@ -1,10 +1,12 @@
 #!/usr/bin/env bash
 
-counter=0
 status=""
+counter=0
+checkcounter=0
 
 until [[ $status = "false" ]]; do
     status=$(curl 2>/dev/null "http://$1/status.php" | jq .maintenance)
+    echo "($checkcounter) $status"
 
     if [[ "$status" =~ "false" || "$status" = "" ]]; then
         let "counter += 1"
@@ -14,5 +16,8 @@ until [[ $status = "false" ]]; do
         fi
     fi
 
+    let "checkcounter += 1"
     sleep 10
 done
+
+echo "($checkcounter) Done"

+ 23 - 7
src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java

@@ -29,10 +29,12 @@ import com.facebook.testing.screenshot.Screenshot;
 import com.owncloud.android.AbstractIT;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation;
 import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
 import com.owncloud.android.lib.resources.files.SearchRemoteOperation;
 import com.owncloud.android.lib.resources.shares.CreateShareRemoteOperation;
+import com.owncloud.android.lib.resources.shares.GetShareesRemoteOperation;
 import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
 import com.owncloud.android.operations.CreateFolderOperation;
@@ -40,6 +42,8 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.events.SearchEvent;
 
 import org.greenrobot.eventbus.EventBus;
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
@@ -85,12 +89,13 @@ public class FileDisplayActivityIT extends AbstractIT {
     }
 
     @Test
-    public void showShares() {
+    public void showShares() throws JSONException {
         assertTrue(new ExistenceCheckRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess());
         assertTrue(new CreateFolderRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess());
         assertTrue(new CreateFolderRemoteOperation("/shareToGroup/", true).execute(client).isSuccess());
         assertTrue(new CreateFolderRemoteOperation("/shareViaLink/", true).execute(client).isSuccess());
         assertTrue(new CreateFolderRemoteOperation("/noShare/", true).execute(client).isSuccess());
+        assertTrue(new CreateFolderRemoteOperation("/shareToCircle/", true).execute(client).isSuccess());
 
         // share folder to user "admin"
         assertTrue(new CreateShareRemoteOperation("/shareToAdmin/",
@@ -119,12 +124,27 @@ public class FileDisplayActivityIT extends AbstractIT {
                                                          OCShare.DEFAULT_PERMISSION)
                               .execute(client).isSuccess());
 
+        // share folder to circle
+        // get share
+        RemoteOperationResult searchResult = new GetShareesRemoteOperation("publicCircle", 1, 50).execute(client);
+        assertTrue(searchResult.getLogMessage(), searchResult.isSuccess());
+
+        JSONObject resultJson = (JSONObject) searchResult.getData().get(0);
+        String circleId = resultJson.getJSONObject("value").getString("shareWith");
+
+        assertTrue(new CreateShareRemoteOperation("/shareToCircle/",
+                                                  ShareType.CIRCLE,
+                                                  circleId,
+                                                  false,
+                                                  "",
+                                                  OCShare.DEFAULT_PERMISSION)
+                       .execute(client).isSuccess());
+
         Activity sut = activityRule.launchActivity(null);
 
         getInstrumentation().waitForIdleSync();
 
-        EventBus.getDefault().post(new SearchEvent("",
-                                                   SearchRemoteOperation.SearchType.SHARED_FILTER));
+        EventBus.getDefault().post(new SearchEvent("", SearchRemoteOperation.SearchType.SHARED_FILTER));
 
         getInstrumentation().waitForIdleSync();
 
@@ -150,8 +170,6 @@ public class FileDisplayActivityIT extends AbstractIT {
         assertTrue(new CreateFolderOperation("/test/", true).execute(client, getStorageManager()).isSuccess());
 
         // navigate into it
-        // sut.onActivity(activity -> activity.onBrowsedDownTo(getStorageManager().getFileByPath("/test/")));
-        //sut.onBrowsedDownTo(getStorageManager().getFileByPath("/test/"));
         OCFile test = getStorageManager().getFileByPath("/test/");
         sut.setFile(test);
         sut.startSyncFolderOperation(test, false);
@@ -168,7 +186,5 @@ public class FileDisplayActivityIT extends AbstractIT {
         // then should be in root again
         Thread.sleep(2000);
         assertEquals(getStorageManager().getFileByPath("/"), sut.getCurrentDir());
-
-
     }
 }

+ 6 - 0
src/androidTest/java/com/owncloud/android/AbstractIT.java

@@ -97,6 +97,8 @@ public abstract class AbstractIT {
             createDummyFiles();
 
             waitForServer(client, baseUrl);
+
+            deleteAllFiles(); // makes sure that no file/folder is in root
         } catch (OperationCanceledException e) {
             e.printStackTrace();
         } catch (AuthenticatorException e) {
@@ -110,6 +112,10 @@ public abstract class AbstractIT {
 
     @After
     public void after() {
+        deleteAllFiles();
+    }
+
+    public static void deleteAllFiles() {
         RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client);
         assertTrue(result.getLogMessage(), result.isSuccess());
 

+ 112 - 6
src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt

@@ -23,8 +23,11 @@ package com.owncloud.android.ui.fragment
 
 import android.Manifest
 import androidx.test.core.app.ActivityScenario
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.rule.GrantPermissionRule
 import com.evernote.android.job.JobRequest
+import com.facebook.testing.screenshot.Screenshot
 import com.nextcloud.client.account.UserAccountManagerImpl
 import com.nextcloud.client.device.PowerManagementService
 import com.nextcloud.client.network.ConnectivityService
@@ -36,16 +39,25 @@ import com.owncloud.android.MainApp
 import com.owncloud.android.datamodel.UploadsStorageManager
 import com.owncloud.android.db.OCUpload
 import com.owncloud.android.files.services.FileUploader
+import com.owncloud.android.lib.resources.shares.CreateShareRemoteOperation
+import com.owncloud.android.lib.resources.shares.GetShareesRemoteOperation
+import com.owncloud.android.lib.resources.shares.OCShare
+import com.owncloud.android.lib.resources.shares.ShareType
 import com.owncloud.android.operations.CreateFolderOperation
 import com.owncloud.android.operations.RefreshFolderOperation
 import com.owncloud.android.operations.UploadFileOperation
 import com.owncloud.android.ui.activity.FileDisplayActivity
 import com.owncloud.android.utils.FileStorageUtils
-import junit.framework.Assert.assertTrue
+import junit.framework.TestCase
+import org.json.JSONObject
+import org.junit.Assert.assertTrue
 import org.junit.Rule
 import org.junit.Test
 
 class OCFileListFragmentIT : AbstractIT() {
+    @get:Rule
+    val activityRule = IntentsTestRule(FileDisplayActivity::class.java, true, false)
+
     @get:Rule
     val permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
 
@@ -92,10 +104,9 @@ class OCFileListFragmentIT : AbstractIT() {
             FileUploader.LOCAL_BEHAVIOUR_COPY,
             targetContext,
             false,
-            false
-        )
-        newUpload.addRenameUploadListener {}
+            false)
 
+        newUpload.addRenameUploadListener {}
         newUpload.setRemoteFolderToBeCreated()
 
         assertTrue(newUpload.execute(client, storageManager).isSuccess)
@@ -114,7 +125,7 @@ class OCFileListFragmentIT : AbstractIT() {
         Thread.sleep(2000)
 
         sut.onActivity { activity ->
-            com.facebook.testing.screenshot.Screenshot.snapActivity(activity).setName("richworkspaces_light").record()
+            Screenshot.snapActivity(activity).setName("richworkspaces_light").record()
         }
 
         val preferences: AppPreferences = AppPreferencesImpl.fromContext(targetContext)
@@ -130,7 +141,7 @@ class OCFileListFragmentIT : AbstractIT() {
         Thread.sleep(2000)
 
         sut.onActivity { activity ->
-            com.facebook.testing.screenshot.Screenshot.snapActivity(activity).setName("richworkspaces_dark").record()
+            Screenshot.snapActivity(activity).setName("richworkspaces_dark").record()
         }
 
         // switch back to light mode
@@ -141,4 +152,99 @@ class OCFileListFragmentIT : AbstractIT() {
 
         sut.recreate()
     }
+
+    @Test
+    fun createAndShowShareToUser() {
+        val path = "/shareToAdmin/"
+        TestCase.assertTrue(CreateFolderOperation(path, true).execute(client, storageManager).isSuccess)
+
+        // share folder to user "admin"
+        TestCase.assertTrue(CreateShareRemoteOperation(path,
+            ShareType.USER,
+            "admin",
+            false,
+            "",
+            OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER)
+            .execute(client).isSuccess)
+
+        val sut: FileDisplayActivity = activityRule.launchActivity(null)
+        sut.startSyncFolderOperation(storageManager.getFileByPath("/"), true)
+
+        Thread.sleep(2000)
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    fun createAndShowShareToGroup() {
+        val path = "/shareToGroup/"
+        TestCase.assertTrue(CreateFolderOperation(path, true).execute(client, storageManager).isSuccess)
+
+        // share folder to group
+        assertTrue(CreateShareRemoteOperation("/shareToGroup/",
+            ShareType.GROUP,
+            "users",
+            false,
+            "",
+            OCShare.DEFAULT_PERMISSION)
+            .execute(client).isSuccess)
+
+        val sut: FileDisplayActivity = activityRule.launchActivity(null)
+        sut.startSyncFolderOperation(storageManager.getFileByPath("/"), true)
+
+        Thread.sleep(2000)
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    fun createAndShowShareToCircle() {
+        val path = "/shareToCircle/"
+        TestCase.assertTrue(CreateFolderOperation(path, true).execute(client, storageManager).isSuccess)
+
+        // share folder to circle
+        // get circleId
+        val searchResult = GetShareesRemoteOperation("publicCircle", 1, 50).execute(client)
+        assertTrue(searchResult.logMessage, searchResult.isSuccess)
+
+        val resultJson: JSONObject = searchResult.data[0] as JSONObject
+        val circleId: String = resultJson.getJSONObject("value").getString("shareWith")
+
+        assertTrue(CreateShareRemoteOperation("/shareToCircle/",
+            ShareType.CIRCLE,
+            circleId,
+            false,
+            "",
+            OCShare.DEFAULT_PERMISSION)
+            .execute(client).isSuccess)
+
+        val sut: FileDisplayActivity = activityRule.launchActivity(null)
+        sut.startSyncFolderOperation(storageManager.getFileByPath("/"), true)
+
+        Thread.sleep(2000)
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    fun createAndShowShareViaLink() {
+        val path = "/shareViaLink/"
+        TestCase.assertTrue(CreateFolderOperation(path, true).execute(client, storageManager).isSuccess)
+
+        // share folder via public link
+        TestCase.assertTrue(CreateShareRemoteOperation("/shareViaLink/",
+            ShareType.PUBLIC_LINK,
+            "",
+            true,
+            "",
+            OCShare.READ_PERMISSION_FLAG)
+            .execute(client).isSuccess)
+
+        val sut: FileDisplayActivity = activityRule.launchActivity(null)
+        sut.startSyncFolderOperation(storageManager.getFileByPath("/"), true)
+
+        Thread.sleep(2000)
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+        Screenshot.snapActivity(sut).record()
+    }
 }

+ 13 - 8
src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -1692,15 +1692,20 @@ public class FileDataStorageManager {
                 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
                 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
                 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
+            + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
                 + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? ) ";
-        String[] whereArgs = new String[]{filePath, accountName,
-                Integer.toString(ShareType.USER.getValue()),
-                Integer.toString(ShareType.GROUP.getValue()),
-                Integer.toString(ShareType.EMAIL.getValue()),
-                Integer.toString(ShareType.FEDERATED.getValue()),
-                Integer.toString(ShareType.ROOM.getValue())};
-
-        Cursor cursor = null;
+        String[] whereArgs = new String[]{
+            filePath,
+            accountName,
+            Integer.toString(ShareType.USER.getValue()),
+            Integer.toString(ShareType.GROUP.getValue()),
+            Integer.toString(ShareType.EMAIL.getValue()),
+            Integer.toString(ShareType.FEDERATED.getValue()),
+            Integer.toString(ShareType.ROOM.getValue()),
+            Integer.toString(ShareType.CIRCLE.getValue())
+        };
+
+        Cursor cursor;
         if (getContentResolver() != null) {
             cursor = getContentResolver().query(ProviderTableMeta.CONTENT_URI_SHARE, null, where, whereArgs, null);
         } else {

+ 7 - 3
src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java

@@ -45,7 +45,11 @@ public class CreateShareWithShareeOperation extends SyncOperation {
     private int permissions;
 
     private static final List<ShareType> supportedShareTypes = new ArrayList<>(Arrays.asList(ShareType.USER,
-            ShareType.GROUP, ShareType.FEDERATED, ShareType.EMAIL, ShareType.ROOM));
+                                                                                             ShareType.GROUP,
+                                                                                             ShareType.FEDERATED,
+                                                                                             ShareType.EMAIL,
+                                                                                             ShareType.ROOM,
+                                                                                             ShareType.CIRCLE));
 
     /**
      * Constructor.
@@ -74,8 +78,8 @@ public class CreateShareWithShareeOperation extends SyncOperation {
             path,
             shareType,
             shareeName,
-                false,
-                "",
+            false,
+            "",
             permissions
         );
         operation.setGetShareDetails(true);

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

@@ -402,6 +402,7 @@ public class FileContentProvider extends ContentProvider {
             case EMAIL:
             case FEDERATED:
             case ROOM:
+            case CIRCLE:
                 fileValues.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, 1);
                 break;
 

+ 10 - 1
src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java

@@ -20,7 +20,6 @@
 
 package com.owncloud.android.providers;
 
-import android.accounts.Account;
 import android.app.SearchManager;
 import android.content.ContentProvider;
 import android.content.ContentValues;
@@ -90,6 +89,7 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
     private String DATA_ROOM;
     private String DATA_REMOTE;
     private String DATA_EMAIL;
+    private String DATA_CIRCLE;
 
     private UriMatcher mUriMatcher;
 
@@ -129,12 +129,14 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
         DATA_ROOM = AUTHORITY + ".data.room";
         DATA_REMOTE = AUTHORITY + ".data.remote";
         DATA_EMAIL = AUTHORITY + ".data.email";
+        DATA_CIRCLE = AUTHORITY + ".data.circle";
 
         sShareTypes.put(DATA_USER, ShareType.USER);
         sShareTypes.put(DATA_GROUP, ShareType.GROUP);
         sShareTypes.put(DATA_ROOM, ShareType.ROOM);
         sShareTypes.put(DATA_REMOTE, ShareType.FEDERATED);
         sShareTypes.put(DATA_EMAIL, ShareType.EMAIL);
+        sShareTypes.put(DATA_CIRCLE, ShareType.CIRCLE);
 
         mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
         mUriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH);
@@ -213,6 +215,7 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
             Uri roomBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_ROOM).build();
             Uri remoteBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_REMOTE).build();
             Uri emailBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_EMAIL).build();
+            Uri circleBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_CIRCLE).build();
 
             FileDataStorageManager manager = new FileDataStorageManager(user.toPlatformAccount(),
                                                                         getContext().getContentResolver());
@@ -276,6 +279,12 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
                             dataUri = Uri.withAppendedPath(roomBaseUri, shareWith);
                             break;
 
+                        case CIRCLE:
+                            icon = R.drawable.ic_circles;
+                            displayName = userName;
+                            dataUri = Uri.withAppendedPath(circleBaseUri, shareWith);
+                            break;
+
                         default:
                             break;
                     }

+ 12 - 5
src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java

@@ -30,7 +30,6 @@ import android.content.ContentValues;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.Color;
 import android.graphics.LinearGradient;
 import android.graphics.PorterDuff;
 import android.graphics.Shader;
@@ -407,7 +406,9 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
 
                     // use fileOwner if not oneself, then add at first
                     ShareeUser fileOwnerSharee = new ShareeUser(fileOwner, file.getOwnerDisplayName(), ShareType.USER);
-                    if (fileOwner != null && !fileOwner.equals(userId) && !sharees.contains(fileOwnerSharee)) {
+                    if (!TextUtils.isEmpty(fileOwner) &&
+                        !fileOwner.equals(userId) &&
+                        !sharees.contains(fileOwnerSharee)) {
                         sharees.add(fileOwnerSharee);
                     }
 
@@ -421,7 +422,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
                     int size = 60 * (shareeSize - 1) + w;
 
                     for (int i = 0; i < shareeSize; i++) {
-                        ShareeUser sharee = file.getSharees().get(i);
+                        ShareeUser sharee = sharees.get(i);
 
                         ImageView avatar = new ImageView(activity);
 
@@ -436,6 +437,8 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
                                     Log_OC.e(TAG, "Error calculating RGB value for active account icon.", e);
                                     avatar.setImageResource(R.drawable.ic_people);
                                 }
+                            } else if (sharee.getShareType().equals(ShareType.CIRCLE)) {
+                                avatar.setImageResource(R.drawable.ic_circles);
                             } else if (sharee.getUserId().contains("@")) {
                                 showFederatedShareAvatar(sharee.getUserId(), avatarRadius, resources, avatar);
                             } else {
@@ -899,8 +902,12 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
                     ShareType newShareType = ocShare.getShareType();
                     if (newShareType == ShareType.PUBLIC_LINK) {
                         file.setSharedViaLink(true);
-                    } else if (newShareType == ShareType.USER || newShareType == ShareType.GROUP ||
-                        newShareType == ShareType.EMAIL || newShareType == ShareType.FEDERATED) {
+                    } else if (newShareType == ShareType.USER ||
+                        newShareType == ShareType.GROUP ||
+                        newShareType == ShareType.EMAIL ||
+                        newShareType == ShareType.FEDERATED ||
+                        newShareType == ShareType.ROOM ||
+                        newShareType == ShareType.CIRCLE) {
                         file.setSharedWithSharee(true);
                     }
 

+ 3 - 0
src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.java

@@ -119,6 +119,9 @@ public class ShareeListAdapter extends RecyclerView.Adapter<ShareeListAdapter.Us
                     name = context.getString(R.string.share_room_clarification, name);
                     setImage(holder, name, R.drawable.ic_chat_bubble);
                     break;
+                case CIRCLE:
+                    holder.avatar.setImageResource(R.drawable.ic_circles);
+                    break;
                 default:
                     setImage(holder, name, R.drawable.ic_user);
                     break;

+ 25 - 0
src/main/res/drawable/ic_circles.xml

@@ -0,0 +1,25 @@
+<vector android:autoMirrored="true"
+    android:height="64dp"
+    android:viewportHeight="57"
+    android:viewportWidth="57"
+    android:width="64dp"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <path
+        android:fillAlpha="1"
+        android:fillColor="#00000000"
+        android:pathData="M7.1,28.5A21.4,21.4 0,0 1,28.5 7.1m10.7,40A21.4,21.4 0,0 1,10 39M39.2,10A21.4,21.4 0,0 1,47 39.2"
+        android:strokeAlpha="1"
+        android:strokeColor="#000000"
+        android:strokeLineCap="round"
+        android:strokeLineJoin="round"
+        android:strokeWidth="3.99979687" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M28.5,7.1m-6.5,0a6.5,6.5 0,1 1,13 0a6.5,6.5 0,1 1,-13 0" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,39.2m-0,-6.5a6.5,6.5 0,1 1,-0 13a6.5,6.5 0,1 1,-0 -13" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M47,39.2m-0,-6.5a6.5,6.5 0,1 1,-0 13a6.5,6.5 0,1 1,-0 -13" />
+</vector>