diff --git a/.drone.yml b/.drone.yml
index 8fbf6f2d22fa..39d40183a4a6 100644
--- a/.drone.yml
+++ b/.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:
diff --git a/drawable_resources/circles.svg b/drawable_resources/circles.svg
new file mode 100644
index 000000000000..f908e89543b7
--- /dev/null
+++ b/drawable_resources/circles.svg
@@ -0,0 +1,27 @@
+
+
diff --git a/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToCircle.png b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToCircle.png
new file mode 100644
index 000000000000..d846734141bb
Binary files /dev/null and b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToCircle.png differ
diff --git a/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToGroup.png b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToGroup.png
new file mode 100644
index 000000000000..efa4f3f13146
Binary files /dev/null and b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToGroup.png differ
diff --git a/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToUser.png b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToUser.png
new file mode 100644
index 000000000000..8e720454beb6
Binary files /dev/null and b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareToUser.png differ
diff --git a/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png
new file mode 100644
index 000000000000..40d5d4185313
Binary files /dev/null and b/screenshots/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png differ
diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt
index 385dc9a0803c..7fa79531c206 100644
--- a/scripts/analysis/lint-results.txt
+++ b/scripts/analysis/lint-results.txt
@@ -1,2 +1,2 @@
DO NOT TOUCH; GENERATED BY DRONE
- Lint Report: 76 warnings
+ Lint Report: 78 warnings
diff --git a/scripts/updateScreenshots.sh b/scripts/updateScreenshots.sh
index a7f2ff81a217..ec14f59be21a 100755
--- a/scripts/updateScreenshots.sh
+++ b/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
diff --git a/scripts/wait_for_server.sh b/scripts/wait_for_server.sh
index 66b150045c4e..0157dc65cd10 100755
--- a/scripts/wait_for_server.sh
+++ b/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"
diff --git a/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java b/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java
index 71ed3b670813..10863285f810 100644
--- a/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java
+++ b/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java
@@ -29,10 +29,12 @@
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.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;
@@ -67,10 +71,10 @@ public class FileDisplayActivityIT extends AbstractIT {
Manifest.permission.WRITE_EXTERNAL_STORAGE);
@Test
- public void open() throws InterruptedException {
+ public void open() {
Activity sut = activityRule.launchActivity(null);
- Thread.sleep(3000);
+ shortSleep();
Screenshot.snapActivity(sut).record();
}
@@ -85,12 +89,13 @@ public void drawer() {
}
@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 void showShares() {
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();
@@ -142,7 +162,7 @@ public void showAccounts() {
}
@Test
- public void allFiles() throws InterruptedException {
+ public void allFiles() {
// ActivityScenario sut = ActivityScenario.launch(FileDisplayActivity.class);
FileDisplayActivity sut = activityRule.launchActivity(null);
@@ -150,8 +170,6 @@ public void allFiles() throws InterruptedException {
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);
@@ -166,9 +184,7 @@ public void allFiles() throws InterruptedException {
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files));
// then should be in root again
- Thread.sleep(2000);
+ shortSleep();
assertEquals(getStorageManager().getFileByPath("/"), sut.getCurrentDir());
-
-
}
}
diff --git a/src/androidTest/java/com/owncloud/android/AbstractIT.java b/src/androidTest/java/com/owncloud/android/AbstractIT.java
index 5ddc81a410db..cc2a550691e7 100644
--- a/src/androidTest/java/com/owncloud/android/AbstractIT.java
+++ b/src/androidTest/java/com/owncloud/android/AbstractIT.java
@@ -97,6 +97,8 @@ public static void beforeAll() {
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 static void beforeAll() {
@After
public void after() {
+ deleteAllFiles();
+ }
+
+ public static void deleteAllFiles() {
RemoteOperationResult result = new ReadFolderRemoteOperation("/").execute(client);
assertTrue(result.getLogMessage(), result.isSuccess());
@@ -186,7 +192,7 @@ protected void waitForIdleSync() {
protected void openDrawer(IntentsTestRule activityRule) throws InterruptedException {
Activity sut = activityRule.launchActivity(null);
- Thread.sleep(3000);
+ shortSleep();
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
@@ -208,4 +214,20 @@ protected Activity getCurrentActivity() {
return currentActivity;
}
+
+ protected void shortSleep() {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void longSleep() {
+ try {
+ Thread.sleep(20000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/src/androidTest/java/com/owncloud/android/ScreenshotsIT.java b/src/androidTest/java/com/owncloud/android/ScreenshotsIT.java
index 53d61c032ade..c4f8cf471363 100644
--- a/src/androidTest/java/com/owncloud/android/ScreenshotsIT.java
+++ b/src/androidTest/java/com/owncloud/android/ScreenshotsIT.java
@@ -60,7 +60,7 @@ public void gridViewScreenshot() throws InterruptedException {
openOverflowMenu();
onView(anyOf(withText(R.string.action_switch_grid_view), withId(R.id.action_switch_view))).perform(click());
- Thread.sleep(1000);
+ shortSleep();
Screengrab.screenshot("01_gridView");
@@ -70,12 +70,12 @@ public void gridViewScreenshot() throws InterruptedException {
Assert.assertTrue(true); // if we reach this, everything is ok
}
- private void openOverflowMenu() throws InterruptedException {
+ private void openOverflowMenu() {
try {
Espresso.openContextualActionModeOverflowMenu();
} catch (NoActivityResumedException e) {
ActivityScenario.launch(FileDisplayActivity.class);
- Thread.sleep(1000);
+ shortSleep();
Espresso.openContextualActionModeOverflowMenu();
}
}
@@ -143,12 +143,12 @@ public void autoUploadScreenshot() {
}
@Test
- public void davdroidScreenshot() throws InterruptedException {
+ public void davdroidScreenshot() {
ActivityScenario.launch(SettingsActivity.class);
onData(PreferenceMatchers.withTitle(R.string.prefs_category_more)).perform(ViewActions.scrollTo());
- Thread.sleep(1000);
+ shortSleep();
Screengrab.screenshot("06_davdroid");
diff --git a/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt b/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt
index 724390f37c4d..8a38892a165b 100644
--- a/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt
+++ b/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt
@@ -42,9 +42,6 @@ import org.junit.Test
import java.io.File
class FileUploaderIT : AbstractIT() {
- val SHORT_WAIT: Long = 5000
- val LONG_WAIT: Long = 20000
-
var uploadsStorageManager: UploadsStorageManager? = null
val connectivityServiceMock: ConnectivityService = object : ConnectivityService {
@@ -149,7 +146,7 @@ class FileUploaderIT : AbstractIT() {
false,
FileUploader.NameCollisionPolicy.DEFAULT)
- Thread.sleep(LONG_WAIT)
+ longSleep()
val result = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result.isSuccess)
@@ -166,7 +163,7 @@ class FileUploaderIT : AbstractIT() {
FileUploader.LOCAL_BEHAVIOUR_COPY,
FileUploader.NameCollisionPolicy.OVERWRITE)
- Thread.sleep(SHORT_WAIT)
+ shortSleep()
val result2 = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result2.isSuccess)
@@ -256,7 +253,7 @@ class FileUploaderIT : AbstractIT() {
false,
FileUploader.NameCollisionPolicy.DEFAULT)
- Thread.sleep(LONG_WAIT)
+ longSleep()
val result = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result.isSuccess)
@@ -273,7 +270,7 @@ class FileUploaderIT : AbstractIT() {
FileUploader.LOCAL_BEHAVIOUR_COPY,
FileUploader.NameCollisionPolicy.RENAME)
- Thread.sleep(SHORT_WAIT)
+ shortSleep()
val result2 = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result2.isSuccess)
@@ -356,7 +353,7 @@ class FileUploaderIT : AbstractIT() {
false,
FileUploader.NameCollisionPolicy.DEFAULT)
- Thread.sleep(LONG_WAIT)
+ longSleep()
val result = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result.isSuccess)
@@ -373,7 +370,7 @@ class FileUploaderIT : AbstractIT() {
FileUploader.LOCAL_BEHAVIOUR_COPY,
FileUploader.NameCollisionPolicy.CANCEL)
- Thread.sleep(SHORT_WAIT)
+ shortSleep()
val result2 = ReadFileRemoteOperation("/testFile.txt").execute(client)
assertTrue(result2.isSuccess)
diff --git a/src/androidTest/java/com/owncloud/android/ui/activity/ConflictsResolveActivityIT.java b/src/androidTest/java/com/owncloud/android/ui/activity/ConflictsResolveActivityIT.java
index bfe237f0319f..8dc32f8faf43 100644
--- a/src/androidTest/java/com/owncloud/android/ui/activity/ConflictsResolveActivityIT.java
+++ b/src/androidTest/java/com/owncloud/android/ui/activity/ConflictsResolveActivityIT.java
@@ -59,7 +59,7 @@ public class ConflictsResolveActivityIT extends AbstractIT {
private boolean returnCode;
@Test
- public void screenshotTextFiles() throws InterruptedException {
+ public void screenshotTextFiles() {
OCFile newFile = new OCFile("/newFile.txt");
newFile.setFileLength(56000);
newFile.setModificationTimestamp(1522019340);
@@ -88,13 +88,13 @@ public void screenshotTextFiles() throws InterruptedException {
getInstrumentation().waitForIdleSync();
- Thread.sleep(2000);
+ shortSleep();
Screenshot.snap(dialog.getDialog().getWindow().getDecorView()).record();
}
@Test
- public void screenshotImages() throws InterruptedException, IOException {
+ public void screenshotImages() throws IOException {
FileDataStorageManager storageManager = new FileDataStorageManager(account,
targetContext.getContentResolver());
@@ -141,13 +141,13 @@ public void screenshotImages() throws InterruptedException, IOException {
dialog.listener = listener;
getInstrumentation().waitForIdleSync();
- Thread.sleep(2000);
+ shortSleep();
Screenshot.snap(dialog.getDialog().getWindow().getDecorView()).record();
}
@Test
- public void cancel() throws InterruptedException {
+ public void cancel() {
returnCode = false;
OCUpload newUpload = new OCUpload(FileStorageUtils.getSavePath(account.name) + "/nonEmpty.txt",
@@ -179,7 +179,7 @@ public void cancel() throws InterruptedException {
};
getInstrumentation().waitForIdleSync();
- Thread.sleep(2000);
+ shortSleep();
onView(withText("Cancel")).perform(click());
diff --git a/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java b/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java
index e0de88c845f0..58aa429de820 100644
--- a/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java
+++ b/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java
@@ -40,22 +40,22 @@ public class ManageAccountsActivityIT extends AbstractIT {
false);
@Test
- public void open() throws InterruptedException {
+ public void open() {
Activity sut = activityRule.launchActivity(null);
- Thread.sleep(2000);
+ shortSleep();
Screenshot.snapActivity(sut).record();
}
@Test
- public void userInfoDetail() throws InterruptedException {
+ public void userInfoDetail() {
ManageAccountsActivity sut = activityRule.launchActivity(null);
User user = sut.accountManager.getUser();
sut.onClick(user);
- Thread.sleep(2000);
+ shortSleep();
Screenshot.snapActivity(getCurrentActivity()).record();
}
diff --git a/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt b/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt
index d46694e471ed..2e4750ff9f82 100644
--- a/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt
+++ b/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,30 @@ 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() {
+ companion object {
+ val SECOND_IN_MILLIS = 1000L
+ val RESULT_PER_PAGE = 50
+ }
+
+ @get:Rule
+ val activityRule = IntentsTestRule(FileDisplayActivity::class.java, true, false)
+
@get:Rule
val permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
@@ -92,16 +109,15 @@ class OCFileListFragmentIT : AbstractIT() {
FileUploader.LOCAL_BEHAVIOUR_COPY,
targetContext,
false,
- false
- )
- newUpload.addRenameUploadListener {}
+ false)
+ newUpload.addRenameUploadListener {}
newUpload.setRemoteFolderToBeCreated()
assertTrue(newUpload.execute(client, storageManager).isSuccess)
assertTrue(RefreshFolderOperation(storageManager.getFileByPath("/test/"),
- System.currentTimeMillis() / 1000,
+ System.currentTimeMillis() / SECOND_IN_MILLIS,
false,
true,
storageManager,
@@ -111,10 +127,10 @@ class OCFileListFragmentIT : AbstractIT() {
val sut = ActivityScenario.launch(FileDisplayActivity::class.java)
sut.onActivity { activity -> activity.onBrowsedDownTo(storageManager.getFileByPath("/test/")) }
- Thread.sleep(2000)
+ shortSleep()
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)
@@ -127,10 +143,10 @@ class OCFileListFragmentIT : AbstractIT() {
sut.onActivity { activity -> activity.onBrowsedDownTo(storageManager.getFileByPath("/test/")) }
- Thread.sleep(2000)
+ shortSleep()
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 +157,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)
+
+ shortSleep()
+ 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)
+
+ shortSleep()
+ 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, RESULT_PER_PAGE).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)
+
+ shortSleep()
+ 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)
+
+ shortSleep()
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ Screenshot.snapActivity(sut).record()
+ }
}
diff --git a/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java b/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java
index ad7f04bce4ef..0c64a9894111 100644
--- a/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java
+++ b/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java
@@ -53,7 +53,7 @@ public class PreviewTextFileFragmentTest extends AbstractIT {
public void displaySimpleTextFile() throws InterruptedException {
FileDisplayActivity sut = activityRule.launchActivity(null);
- Thread.sleep(3000);
+ shortSleep();
File file = new File(FileStorageUtils.getSavePath(account.name) + "/nonEmpty.txt");
OCFile test = new OCFile("/text.md");
@@ -61,7 +61,7 @@ public void displaySimpleTextFile() throws InterruptedException {
test.setStoragePath(file.getAbsolutePath());
sut.startTextPreview(test, false);
- Thread.sleep(3000);
+ shortSleep();
Screenshot.snapActivity(sut).record();
}
@@ -70,7 +70,7 @@ public void displaySimpleTextFile() throws InterruptedException {
public void displayJavaSnippetFile() throws IOException, InterruptedException {
FileDisplayActivity sut = activityRule.launchActivity(null);
- Thread.sleep(3000);
+ shortSleep();
File file = getFile("java.md");
OCFile test = new OCFile("/java.md");
@@ -78,7 +78,7 @@ public void displayJavaSnippetFile() throws IOException, InterruptedException {
test.setStoragePath(file.getAbsolutePath());
sut.startTextPreview(test, false);
- Thread.sleep(3000);
+ shortSleep();
Screenshot.snapActivity(sut).record();
}
diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
index 60bbc4652923..5da0cb4e90f1 100644
--- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
+++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
@@ -1695,15 +1695,20 @@ public List getSharesWithForAFile(String filePath, String accountName)
+ 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 {
diff --git a/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java b/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java
index e9b13895334b..c32f46d7e3e8 100644
--- a/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java
+++ b/src/main/java/com/owncloud/android/operations/CreateShareWithShareeOperation.java
@@ -47,7 +47,11 @@ public class CreateShareWithShareeOperation extends SyncOperation {
private int permissions;
private static final List 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.
@@ -76,8 +80,8 @@ protected RemoteOperationResult run(OwnCloudClient client) {
path,
shareType,
shareeName,
- false,
- "",
+ false,
+ "",
permissions
);
operation.setGetShareDetails(true);
diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java
index 3fd9a3af48da..95b95108e292 100644
--- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java
+++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java
@@ -402,6 +402,7 @@ private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, Conten
case EMAIL:
case FEDERATED:
case ROOM:
+ case CIRCLE:
fileValues.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, 1);
break;
diff --git a/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java b/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java
index 0daa551ab90a..f04bcde178ea 100644
--- a/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java
+++ b/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 boolean onCreate() {
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 @@ private Cursor searchForUsersOrGroups(Uri uri) {
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 @@ private Cursor searchForUsersOrGroups(Uri uri) {
dataUri = Uri.withAppendedPath(roomBaseUri, shareWith);
break;
+ case CIRCLE:
+ icon = R.drawable.ic_circles;
+ displayName = userName;
+ dataUri = Uri.withAppendedPath(circleBaseUri, shareWith);
+ break;
+
default:
break;
}
diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
index 5c09d8ba50f1..ff08e048d5ac 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
@@ -30,7 +30,6 @@
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;
@@ -408,7 +407,9 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
// 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);
}
@@ -422,7 +423,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
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);
@@ -437,6 +438,8 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi
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 {
@@ -900,8 +903,12 @@ private void parseShares(List