Browse Source

add TestActivity to launch fragments in it
fix wrong class cast exception message

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

tobiasKaminsky 4 years ago
parent
commit
a3cb17a829
24 changed files with 442 additions and 52 deletions
  1. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showDetails_Activities.png
  2. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showDetails_Sharing.png
  3. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailActivitiesFragment.png
  4. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailSharingFragment.png
  5. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showFiles.png
  6. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showOneFile.png
  7. 4 4
      scripts/androidScreenshotTest
  8. 78 0
      src/androidTest/java/com/owncloud/android/ui/fragment/FileDetailFragmentStaticServerIT.kt
  9. 79 0
      src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentStaticServerIT.kt
  10. 4 1
      src/debug/AndroidManifest.xml
  11. 37 0
      src/debug/java/com/nextcloud/client/di/BuildTypeComponentsModule.java
  12. 128 0
      src/debug/kotlin/com/nextcloud/TestActivity.kt
  13. 1 1
      src/main/java/com/nextcloud/client/di/AppModule.java
  14. 4 2
      src/main/java/com/nextcloud/client/di/ComponentsModule.java
  15. 1 0
      src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
  16. 7 0
      src/main/java/com/owncloud/android/datamodel/OCFile.java
  17. 3 1
      src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
  18. 3 4
      src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java
  19. 2 2
      src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java
  20. 3 10
      src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
  21. 21 14
      src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
  22. 8 13
      src/main/res/layout/file_details_fragment.xml
  23. 27 0
      src/main/res/layout/test_layout.xml
  24. 32 0
      src/release/java/com/nextcloud/client/di/BuildTypeComponentsModule.java

BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showDetails_Activities.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showDetails_Sharing.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailActivitiesFragment.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailSharingFragment.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showFiles.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showOneFile.png


+ 4 - 4
scripts/androidScreenshotTest

@@ -10,10 +10,6 @@ if [ $# -lt 2 ]; then
     exit
 fi
 
-sed -i s'#<bool name="is_beta">false</bool>#<bool name="is_beta">true</bool>#'g src/main/res/values/setup.xml
-
-emulator -writable-system -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-audio -skin 500x833 &
-
 cd src/androidTest/java
 
 class=$(find | grep $2 | grep -E "java$|kt$" | head -n1|sed s'/\//\./'g | sed s'#^\.\.##' | sed s'#\.java##'| sed s'#\.kt##')
@@ -49,6 +45,10 @@ else
     darkMode="-Pandroid.testInstrumentationRunnerArguments.DARKMODE=$4"
 fi
 
+sed -i s'#<bool name="is_beta">false</bool>#<bool name="is_beta">true</bool>#'g src/main/res/values/setup.xml
+
+emulator -writable-system -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-audio -skin 500x833 &
+
 if [ -e $5 ] ; then
     color=""
 else

+ 78 - 0
src/androidTest/java/com/owncloud/android/ui/fragment/FileDetailFragmentStaticServerIT.kt

@@ -0,0 +1,78 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.fragment
+
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import com.nextcloud.client.TestActivity
+import com.owncloud.android.AbstractIT
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.utils.ScreenshotTest
+import org.junit.Rule
+import org.junit.Test
+
+class FileDetailFragmentStaticServerIT : AbstractIT() {
+    @get:Rule
+    val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
+
+    val file = OCFile("/", "00000001")
+
+    @Test
+    @ScreenshotTest
+    fun showFileDetailActivitiesFragment() {
+        val sut = testActivityRule.launchActivity(null)
+        sut.addFragment(FileDetailActivitiesFragment.newInstance(file, user))
+
+        waitForIdleSync()
+        screenshot(sut)
+    }
+
+    @Test
+    @ScreenshotTest
+    fun showFileDetailSharingFragment() {
+        val sut = testActivityRule.launchActivity(null)
+        sut.addFragment(FileDetailSharingFragment.newInstance(file, user))
+
+        waitForIdleSync()
+        screenshot(sut)
+    }
+
+    @Test
+    @ScreenshotTest
+    fun showDetails_Activities() {
+        val sut = testActivityRule.launchActivity(null)
+        sut.addFragment(FileDetailFragment.newInstance(file, user, 0))
+
+        waitForIdleSync()
+        screenshot(sut)
+    }
+
+    @Test
+    @ScreenshotTest
+    fun showDetails_Sharing() {
+        val sut = testActivityRule.launchActivity(null)
+        sut.addFragment(FileDetailFragment.newInstance(file, user, 1))
+
+        waitForIdleSync()
+        screenshot(sut)
+    }
+}

+ 79 - 0
src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentStaticServerIT.kt

@@ -0,0 +1,79 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.fragment
+
+import android.Manifest
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import androidx.test.rule.GrantPermissionRule
+import com.facebook.testing.screenshot.Screenshot
+import com.nextcloud.client.TestActivity
+import com.owncloud.android.AbstractIT
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.utils.ScreenshotTest
+import org.junit.Rule
+import org.junit.Test
+
+class OCFileListFragmentStaticServerIT : AbstractIT() {
+    @get:Rule
+    val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
+
+    @get:Rule
+    val permissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+
+    @Test
+    @ScreenshotTest
+    fun showFiles() {
+        val sut = testActivityRule.launchActivity(null)
+
+        val textFile = OCFile("/1.md", "00000001")
+        textFile.mimeType = "text/markdown"
+        textFile.fileLength = 1024000
+        textFile.modificationTimestamp = 1188206955000
+        textFile.parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
+        sut.storageManager.saveFile(textFile)
+
+        val imageFile = OCFile("/image.png", "00000002")
+        imageFile.mimeType = "image/png"
+        imageFile.isPreviewAvailable = true
+        imageFile.fileLength = 3072000
+        imageFile.modificationTimestamp = 746443755000
+        imageFile.parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
+        sut.storageManager.saveFile(imageFile)
+
+        sut.addFragment(OCFileListFragment())
+
+        val fragment = (sut.fragment as OCFileListFragment)
+        val root = sut.storageManager.getFileByEncryptedRemotePath("/")
+
+        shortSleep()
+
+        sut.runOnUiThread { fragment.listDirectory(root, false, false) }
+
+        waitForIdleSync()
+        shortSleep()
+        shortSleep()
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+}

+ 4 - 1
src/debug/AndroidManifest.xml

@@ -14,5 +14,8 @@
 
     <application
         android:testOnly="false"
-        tools:ignore="GoogleAppIndexingWarning"/>
+        tools:ignore="GoogleAppIndexingWarning">
+
+        <activity android:name="com.nextcloud.client.TestActivity" />
+    </application>
 </manifest>

+ 37 - 0
src/debug/java/com/nextcloud/client/di/BuildTypeComponentsModule.java

@@ -0,0 +1,37 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client.di;
+
+import com.nextcloud.client.TestActivity;
+
+import dagger.Module;
+import dagger.android.ContributesAndroidInjector;
+
+/**
+ * Register classes that require dependency injection. This class is used by Dagger compiler only.
+ */
+@Module
+abstract class BuildTypeComponentsModule {
+    @ContributesAndroidInjector
+    abstract TestActivity testActivity();
+}

+ 128 - 0
src/debug/kotlin/com/nextcloud/TestActivity.kt

@@ -0,0 +1,128 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import com.nextcloud.client.network.Connectivity
+import com.nextcloud.client.network.ConnectivityService
+import com.owncloud.android.R
+import com.owncloud.android.datamodel.FileDataStorageManager
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.files.services.FileDownloader
+import com.owncloud.android.files.services.FileUploader
+import com.owncloud.android.services.OperationsService
+import com.owncloud.android.ui.activity.FileActivity
+import com.owncloud.android.ui.activity.OnEnforceableRefreshListener
+import com.owncloud.android.ui.fragment.FileFragment
+import com.owncloud.android.ui.helpers.FileOperationsHelper
+
+class TestActivity :
+    FileActivity(),
+    FileFragment.ContainerActivity,
+    SwipeRefreshLayout.OnRefreshListener,
+    OnEnforceableRefreshListener {
+    lateinit var fragment: Fragment
+    private lateinit var storage: FileDataStorageManager
+    private lateinit var fileOperation: FileOperationsHelper
+
+    private val connectivityServiceMock: ConnectivityService = object : ConnectivityService {
+        override fun isInternetWalled(): Boolean {
+            return false
+        }
+
+        override fun getConnectivity(): Connectivity {
+            return Connectivity.CONNECTED_WIFI
+        }
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContentView(R.layout.test_layout)
+    }
+
+    fun addFragment(fragment: Fragment) {
+        this.fragment = fragment
+        val transaction = supportFragmentManager.beginTransaction()
+        transaction.replace(R.id.root, fragment)
+        transaction.commit()
+    }
+
+    override fun onBrowsedDownTo(folder: OCFile?) {
+        TODO("Not yet implemented")
+    }
+
+    override fun getOperationsServiceBinder(): OperationsService.OperationsServiceBinder? {
+        return null
+    }
+
+    override fun showSortListGroup(show: Boolean) {
+        TODO("Not yet implemented")
+    }
+
+    override fun showDetails(file: OCFile?) {
+        TODO("Not yet implemented")
+    }
+
+    override fun showDetails(file: OCFile?, activeTab: Int) {
+        TODO("Not yet implemented")
+    }
+
+    override fun getFileUploaderBinder(): FileUploader.FileUploaderBinder? {
+        return null
+    }
+
+    override fun getFileDownloaderBinder(): FileDownloader.FileDownloaderBinder? {
+        return null
+    }
+
+    override fun getStorageManager(): FileDataStorageManager {
+        if (!this::storage.isInitialized) {
+            storage = FileDataStorageManager(account, contentResolver)
+        }
+
+        return storage
+    }
+
+    override fun getFileOperationsHelper(): FileOperationsHelper {
+        if (!this::fileOperation.isInitialized) {
+            fileOperation = FileOperationsHelper(this, userAccountManager, connectivityServiceMock)
+        }
+
+        return fileOperation
+    }
+
+    override fun onTransferStateChanged(file: OCFile?, downloading: Boolean, uploading: Boolean) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onRefresh(enforced: Boolean) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onRefresh() {
+        TODO("Not yet implemented")
+    }
+}

+ 1 - 1
src/main/java/com/nextcloud/client/di/AppModule.java

@@ -71,7 +71,7 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
-@Module(includes = {ComponentsModule.class, VariantComponentsModule.class})
+@Module(includes = {ComponentsModule.class, VariantComponentsModule.class, BuildTypeComponentsModule.class})
 class AppModule {
 
     @Provides

+ 4 - 2
src/main/java/com/nextcloud/client/di/ComponentsModule.java

@@ -21,8 +21,8 @@
 package com.nextcloud.client.di;
 
 import com.nextcloud.client.etm.EtmActivity;
-import com.nextcloud.client.jobs.NotificationWork;
 import com.nextcloud.client.files.downloader.DownloaderService;
+import com.nextcloud.client.jobs.NotificationWork;
 import com.nextcloud.client.logger.ui.LogsActivity;
 import com.nextcloud.client.media.PlayerService;
 import com.nextcloud.client.onboarding.FirstRunActivity;
@@ -169,5 +169,7 @@ abstract class ComponentsModule {
     @ContributesAndroidInjector abstract AccountManagerService accountManagerService();
     @ContributesAndroidInjector abstract OperationsService operationsService();
     @ContributesAndroidInjector abstract PlayerService playerService();
-    @ContributesAndroidInjector abstract DownloaderService fileDownloaderService();
+
+    @ContributesAndroidInjector
+    abstract DownloaderService fileDownloaderService();
 }

+ 1 - 0
src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -242,6 +242,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_NOTE, ocFile.getNote());
         cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(ocFile.getSharees()));
         cv.put(ProviderTableMeta.FILE_RICH_WORKSPACE, ocFile.getRichWorkspace());
+        cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, ocFile.isPreviewAvailable() ? 1 : 0);
 
         boolean sameRemotePath = fileExists(ocFile.getRemotePath());
         if (sameRemotePath ||

+ 7 - 0
src/main/java/com/owncloud/android/datamodel/OCFile.java

@@ -41,6 +41,7 @@ import java.io.File;
 import java.util.List;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.content.FileProvider;
 import third_parties.daveKoeller.AlphanumComparator;
 
@@ -121,6 +122,12 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
         remotePath = path;
     }
 
+    @VisibleForTesting
+    public OCFile(String path, String remoteId) {
+        this(path);
+        setRemoteId(remoteId);
+    }
+
     /**
      * Reconstruct from parcel
      *

+ 3 - 1
src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -83,6 +83,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  * Manager for concurrent access to thumbnails cache.
  */
 public final class ThumbnailsCacheManager {
+    private static final int READ_TIMEOUT = 40000;
+    private static final int CONNECTION_TIMEOUT = 5000;
 
     public static final String PREFIX_RESIZED_IMAGE = "r";
     public static final String PREFIX_THUMBNAIL = "t";
@@ -632,7 +634,7 @@ public final class ThumbnailsCacheManager {
                                 getMethod.setRequestHeader(RemoteOperation.OCS_API_HEADER,
                                         RemoteOperation.OCS_API_HEADER_VALUE);
 
-                                int status = mClient.executeMethod(getMethod);
+                                int status = mClient.executeMethod(getMethod, READ_TIMEOUT, CONNECTION_TIMEOUT);
                                 if (status == HttpStatus.SC_OK) {
                                     InputStream inputStream = getMethod.getResponseBodyAsStream();
                                     Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

+ 3 - 4
src/main/java/com/owncloud/android/ui/adapter/FileDetailTabAdapter.java

@@ -20,13 +20,12 @@
 
 package com.owncloud.android.ui.adapter;
 
-import android.accounts.Account;
-
 import com.nextcloud.client.account.User;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.ui.fragment.FileDetailActivitiesFragment;
 import com.owncloud.android.ui.fragment.FileDetailSharingFragment;
 
+import androidx.annotation.NonNull;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentStatePagerAdapter;
@@ -47,17 +46,17 @@ public class FileDetailTabAdapter extends FragmentStatePagerAdapter {
         this.user = user;
     }
 
+    @NonNull
     @Override
     public Fragment getItem(int position) {
         switch (position) {
             case 0:
+            default:
                 fileDetailActivitiesFragment = FileDetailActivitiesFragment.newInstance(file, user);
                 return fileDetailActivitiesFragment;
             case 1:
                 fileDetailSharingFragment = FileDetailSharingFragment.newInstance(file, user);
                 return fileDetailSharingFragment;
-            default:
-                return null;
         }
     }
 

+ 2 - 2
src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java

@@ -23,7 +23,6 @@
 
 package com.owncloud.android.ui.fragment;
 
-import android.accounts.Account;
 import android.content.ContentResolver;
 import android.graphics.PorterDuff;
 import android.os.AsyncTask;
@@ -340,7 +339,8 @@ public class FileDetailActivitiesFragment extends Fragment implements
                 }
 
                 Log_OC.d(TAG, "BEFORE getRemoteActivitiesOperation.execute");
-                final RemoteOperationResult result = nextcloudClient.execute(getRemoteNotificationOperation);
+                RemoteOperationResult result = nextcloudClient.execute(getRemoteNotificationOperation);
+                result = new RemoteOperationResult(RemoteOperationResult.ResultCode.UNHANDLED_HTTP_CODE);
 
                 ArrayList<Object> versions = null;
                 if (restoreFileVersionSupported) {

+ 3 - 10
src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -25,8 +25,6 @@
  */
 package com.owncloud.android.ui.fragment;
 
-import android.accounts.Account;
-import android.app.Activity;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
@@ -225,11 +223,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
         return ((FileDetailTabAdapter) viewPager.getAdapter()).getFileDetailActivitiesFragment();
     }
 
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-    }
-
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
@@ -396,7 +389,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
     }
 
     @Override
-    public void onPrepareOptionsMenu(Menu menu) {
+    public void onPrepareOptionsMenu(@NonNull Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
         FileMenuFilter.hideAll(menu);
@@ -528,8 +521,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
      * TODO Remove parameter when the transferring state of files is kept in database.
      *
      * @param transferring Flag signaling if the file should be considered as downloading or uploading,
-     *                     although {@link FileDownloaderBinder#isDownloading(Account, OCFile)}  and
-     *                     {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
+     *                     although {@link FileDownloaderBinder#isDownloading(User, OCFile)}  and
+     *                     {@link FileUploaderBinder#isUploading(User, OCFile)} return false.
      * @param refresh      If 'true', try to refresh the whole file from the database
      */
     public void updateFileDetails(boolean transferring, boolean refresh) {

+ 21 - 14
src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -130,7 +130,6 @@ import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
 import static com.owncloud.android.datamodel.OCFile.ROOT_PATH;
 import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
@@ -261,7 +260,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
 
         } catch (ClassCastException e) {
             throw new IllegalArgumentException(context.toString() + " must implement " +
-                    SwipeRefreshLayout.OnRefreshListener.class.getSimpleName(), e);
+                                                   OnEnforceableRefreshListener.class.getSimpleName(), e);
         }
     }
 
@@ -368,17 +367,21 @@ public class OCFileListFragment extends ExtendedListFragment implements
         }
         prepareCurrentSearch(searchEvent);
 
-        mSortButton.setOnClickListener(v -> openSortingOrderDialogFragment(requireFragmentManager(),
-                                                                           preferences.getSortOrderByFolder(mFile)));
+        if (mSortButton != null) {
+            mSortButton.setOnClickListener(v -> openSortingOrderDialogFragment(requireFragmentManager(),
+                                                                               preferences.getSortOrderByFolder(mFile)));
+        }
 
-        mSwitchGridViewButton.setOnClickListener(v -> {
-            if (isGridEnabled()) {
-                setListAsPreferred();
-            } else {
-                setGridAsPreferred();
-            }
-            setGridSwitchButton();
-        });
+        if (mSwitchGridViewButton != null) {
+            mSwitchGridViewButton.setOnClickListener(v -> {
+                if (isGridEnabled()) {
+                    setListAsPreferred();
+                } else {
+                    setGridAsPreferred();
+                }
+                setGridSwitchButton();
+            });
+        }
 
         setTitle();
 
@@ -1305,8 +1308,12 @@ public class OCFileListFragment extends ExtendedListFragment implements
             switchToListView();
         }
 
-        mSortButton.setText(DisplayUtils.getSortOrderStringId(preferences.getSortOrderByFolder(mFile)));
-        setGridSwitchButton();
+        if (mSortButton != null) {
+            mSortButton.setText(DisplayUtils.getSortOrderStringId(preferences.getSortOrderByFolder(mFile)));
+        }
+        if (mSwitchGridViewButton != null) {
+            setGridSwitchButton();
+        }
 
         if (mHideFab) {
             setFabVisible(false);

+ 8 - 13
src/main/res/layout/file_details_fragment.xml

@@ -18,7 +18,7 @@
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/scrollView"
@@ -27,13 +27,8 @@
     android:fillViewport="true">
 
     <LinearLayout
+        android:id="@+id/detail_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-
-        <LinearLayout
-            android:id="@+id/detail_container"
-            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
@@ -192,12 +187,12 @@
                 app:tabTextColor="@color/text_color"
                 app:tabTextAppearance="@style/AppTabTextAppearance" />
 
-            <androidx.viewpager.widget.ViewPager
-                android:id="@+id/pager"
-                android:layout_width="match_parent"
-                android:layout_height="fill_parent" />
-        </LinearLayout>
+        <androidx.viewpager.widget.ViewPager
+            android:id="@+id/pager"
+            android:layout_width="match_parent"
+            android:layout_height="fill_parent" />
 
         <include layout="@layout/empty_list" />
+
     </LinearLayout>
-</ScrollView>
+</LinearLayout>

+ 27 - 0
src/main/res/layout/test_layout.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Nextcloud Android client application
+
+  Copyright (C) 2020 Tobias Kaminsky
+  Copyright (C) 2020 Nextcloud.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  License as published by the Free Software Foundation; either
+  version 3 of the License, or 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+
+  You should have received a copy of the GNU Affero General Public
+  License along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true"
+    android:orientation="vertical">
+
+</LinearLayout>

+ 32 - 0
src/release/java/com/nextcloud/client/di/BuildTypeComponentsModule.java

@@ -0,0 +1,32 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.client.di;
+
+import dagger.Module;
+
+/**
+ * Register classes that require dependency injection. This class is used by Dagger compiler only.
+ */
+@Module
+abstract class BuildTypeComponentsModule {
+}