Browse Source

Merge branch 'master' into bugfix/Despite-connection-is-restored-message-about-unreachable-server-still-present-9652182

Andy Scherzinger 1 year ago
parent
commit
71d2983b31
25 changed files with 839 additions and 898 deletions
  1. 10 5
      app/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.kt
  2. 9 5
      app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java
  3. 1 1
      app/src/androidTest/java/com/owncloud/android/ui/trashbin/TrashbinLocalRepository.kt
  4. 9 2
      app/src/main/java/com/nextcloud/client/jobs/MediaFoldersDetectionWork.kt
  5. 12 8
      app/src/main/java/com/nextcloud/client/onboarding/FirstRunActivity.kt
  6. 39 31
      app/src/main/java/com/owncloud/android/MainApp.java
  7. 19 17
      app/src/main/java/com/owncloud/android/datamodel/MediaFolder.kt
  8. 18 27
      app/src/main/java/com/owncloud/android/datamodel/MediaFolderType.kt
  9. 0 51
      app/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java
  10. 24 0
      app/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.kt
  11. 1 1
      app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java
  12. 7 0
      app/src/main/java/com/owncloud/android/ui/activity/FileActivity.java
  13. 19 19
      app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.java
  14. 1 1
      app/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
  15. 1 1
      app/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java
  16. 2 2
      app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
  17. 0 227
      app/src/main/java/com/owncloud/android/ui/trashbin/RemoteTrashbinRepository.java
  18. 182 0
      app/src/main/java/com/owncloud/android/ui/trashbin/RemoteTrashbinRepository.kt
  19. 0 334
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java
  20. 340 0
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt
  21. 17 33
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinContract.kt
  22. 0 116
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinPresenter.java
  23. 117 0
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinPresenter.kt
  24. 10 16
      app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinRepository.kt
  25. 1 1
      scripts/analysis/lint-results.txt

+ 10 - 5
app/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.kt

@@ -25,6 +25,8 @@ import android.app.Activity
 import androidx.test.espresso.Espresso
 import androidx.test.espresso.Espresso.onView
 import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
+import androidx.test.espresso.action.ViewActions.scrollTo
 import androidx.test.espresso.assertion.ViewAssertions.matches
 import androidx.test.espresso.contrib.DrawerActions
 import androidx.test.espresso.contrib.NavigationViewActions
@@ -238,12 +240,15 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
         onView(withId(R.id.sort_button)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
 
         // browse into folder
-        onView(withId(R.id.list_root)).perform(
-            RecyclerViewActions.actionOnItemAtPosition<OCFileListItemViewHolder>(
-                0,
-                click()
+        onView(withId(R.id.list_root))
+            .perform(scrollTo())
+            .perform(closeSoftKeyboard())
+            .perform(
+                RecyclerViewActions.actionOnItemAtPosition<OCFileListItemViewHolder>(
+                    0,
+                    click()
+                )
             )
-        )
         shortSleep()
         checkToolbarTitle(topFolder)
         // sort button should now be visible

+ 9 - 5
app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java

@@ -128,11 +128,15 @@ public abstract class AbstractOnServerIT extends AbstractIT {
 
             if (!remoteFile.getRemotePath().equals("/")) {
                 if (remoteFile.isEncrypted()) {
-                    assertTrue(new ToggleEncryptionRemoteOperation(remoteFile.getLocalId(),
-                                                                   remoteFile.getRemotePath(),
-                                                                   false)
-                                   .execute(client)
-                                   .isSuccess());
+                    ToggleEncryptionRemoteOperation operation = new ToggleEncryptionRemoteOperation(remoteFile.getLocalId(),
+                                                                                                    remoteFile.getRemotePath(),
+                                                                                                    false);
+
+                    boolean operationResult = operation
+                        .execute(client)
+                        .isSuccess();
+
+                    assertTrue(operationResult);
                 }
 
                 boolean removeResult = false;

+ 1 - 1
app/src/androidTest/java/com/owncloud/android/ui/trashbin/TrashbinLocalRepository.kt

@@ -26,7 +26,7 @@ import com.owncloud.android.R
 import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
 import com.owncloud.android.ui.trashbin.TrashbinRepository.LoadFolderCallback
 
-class TrashbinLocalRepository(val testCase: TrashbinActivityIT.TestCase) : TrashbinRepository {
+class TrashbinLocalRepository(private val testCase: TrashbinActivityIT.TestCase) : TrashbinRepository {
     override fun emptyTrashbin(callback: TrashbinRepository.OperationCallback?) {
         TODO("Not yet implemented")
     }

+ 9 - 2
app/src/main/java/com/nextcloud/client/jobs/MediaFoldersDetectionWork.kt

@@ -105,12 +105,19 @@ class MediaFoldersDetectionWork constructor(
         )
         val imageMediaFolderPaths: MutableList<String> = ArrayList()
         val videoMediaFolderPaths: MutableList<String> = ArrayList()
+
         for (imageMediaFolder in imageMediaFolders) {
-            imageMediaFolderPaths.add(imageMediaFolder.absolutePath)
+            imageMediaFolder.absolutePath?.let {
+                imageMediaFolderPaths.add(it)
+            }
         }
+
         for (videoMediaFolder in videoMediaFolders) {
-            imageMediaFolderPaths.add(videoMediaFolder.absolutePath)
+            videoMediaFolder.absolutePath?.let {
+                imageMediaFolderPaths.add(it)
+            }
         }
+
         val arbitraryDataString = arbitraryDataProvider.getValue(ACCOUNT_NAME_GLOBAL, KEY_MEDIA_FOLDERS)
         if (!TextUtils.isEmpty(arbitraryDataString)) {
             mediaFoldersModel = gson.fromJson(arbitraryDataString, MediaFoldersModel::class.java)

+ 12 - 8
app/src/main/java/com/nextcloud/client/onboarding/FirstRunActivity.kt

@@ -198,17 +198,21 @@ class FirstRunActivity : BaseActivity(), ViewPager.OnPageChangeListener, Injecta
             this,
             object : OnBackPressedCallback(true) {
                 override fun handleOnBackPressed() {
-                    onFinish()
+                    val isFromAddAccount = intent.getBooleanExtra(EXTRA_ALLOW_CLOSE, false)
 
-                    if (intent.getBooleanExtra(EXTRA_ALLOW_CLOSE, false)) {
-                        onBackPressedDispatcher.onBackPressed()
+                    val destination: Intent = if (isFromAddAccount) {
+                        Intent(applicationContext, FileDisplayActivity::class.java)
                     } else {
-                        val intent = Intent(applicationContext, AuthenticatorActivity::class.java)
-                        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
-                        intent.putExtra(EXTRA_EXIT, true)
-                        startActivity(intent)
-                        finish()
+                        Intent(applicationContext, AuthenticatorActivity::class.java)
                     }
+
+                    if (!isFromAddAccount) {
+                        destination.putExtra(EXTRA_EXIT, true)
+                    }
+
+                    destination.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+                    startActivity(destination)
+                    finish()
                 }
             }
         )

+ 39 - 31
app/src/main/java/com/owncloud/android/MainApp.java

@@ -254,9 +254,12 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
 
         if (!isCrashReportingProcess && !appInfo.isDebugBuild()) {
             Thread.UncaughtExceptionHandler defaultPlatformHandler = Thread.getDefaultUncaughtExceptionHandler();
-            final ExceptionHandler crashReporter = new ExceptionHandler(this,
-                                                                        defaultPlatformHandler);
-            Thread.setDefaultUncaughtExceptionHandler(crashReporter);
+
+            if (defaultPlatformHandler != null) {
+                final ExceptionHandler crashReporter = new ExceptionHandler(this,
+                                                                            defaultPlatformHandler);
+                Thread.setDefaultUncaughtExceptionHandler(crashReporter);
+            }
         }
     }
 
@@ -791,25 +794,34 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
                     + syncedFolder.getId() + " - " + syncedFolder.getLocalPath());
 
                 for (MediaFolder imageMediaFolder : imageMediaFolders) {
-                    if (imageMediaFolder.absolutePath.equals(syncedFolder.getLocalPath())) {
-                        newSyncedFolder = (SyncedFolder) syncedFolder.clone();
-                        newSyncedFolder.setType(MediaFolderType.IMAGE);
-                        primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
-                        Log_OC.i(TAG, "Migrated image synced_folders record: "
-                            + primaryKey + " - " + newSyncedFolder.getLocalPath());
-                        break;
+                    String absolutePathOfImageFolder = imageMediaFolder.absolutePath;
+
+                    if (absolutePathOfImageFolder != null) {
+                        if (absolutePathOfImageFolder.equals(syncedFolder.getLocalPath())) {
+                            newSyncedFolder = (SyncedFolder) syncedFolder.clone();
+                            newSyncedFolder.setType(MediaFolderType.IMAGE);
+                            primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
+                            Log_OC.i(TAG, "Migrated image synced_folders record: "
+                                + primaryKey + " - " + newSyncedFolder.getLocalPath());
+                            break;
+                        }
                     }
                 }
 
                 for (MediaFolder videoMediaFolder : videoMediaFolders) {
-                    if (videoMediaFolder.absolutePath.equals(syncedFolder.getLocalPath())) {
-                        newSyncedFolder = (SyncedFolder) syncedFolder.clone();
-                        newSyncedFolder.setType(MediaFolderType.VIDEO);
-                        primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
-                        Log_OC.i(TAG, "Migrated video synced_folders record: "
-                            + primaryKey + " - " + newSyncedFolder.getLocalPath());
-                        break;
+                    String absolutePathOfVideoFolder = videoMediaFolder.absolutePath;
+
+                    if (absolutePathOfVideoFolder != null) {
+                        if (absolutePathOfVideoFolder.equals(syncedFolder.getLocalPath())) {
+                            newSyncedFolder = (SyncedFolder) syncedFolder.clone();
+                            newSyncedFolder.setType(MediaFolderType.VIDEO);
+                            primaryKey = syncedFolderProvider.storeSyncedFolder(newSyncedFolder);
+                            Log_OC.i(TAG, "Migrated video synced_folders record: "
+                                + primaryKey + " - " + newSyncedFolder.getLocalPath());
+                            break;
+                        }
                     }
+
                 }
             }
 
@@ -835,19 +847,22 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
 
             List<SyncedFolder> syncedFolderList = syncedFolderProvider.getSyncedFolders();
             Map<Pair<String, String>, Long> syncedFolders = new HashMap<>();
-            ArrayList<Long> ids = new ArrayList<>();
             for (SyncedFolder syncedFolder : syncedFolderList) {
                 Pair<String, String> checkPair = new Pair<>(syncedFolder.getAccount(), syncedFolder.getLocalPath());
                 if (syncedFolders.containsKey(checkPair)) {
-                    if (syncedFolder.getId() > syncedFolders.get(checkPair)) {
-                        syncedFolders.put(checkPair, syncedFolder.getId());
+                    Long folderId = syncedFolders.get(checkPair);
+
+                    if (folderId != null) {
+                        if (syncedFolder.getId() > folderId) {
+                            syncedFolders.put(checkPair, syncedFolder.getId());
+                        }
                     }
                 } else {
                     syncedFolders.put(checkPair, syncedFolder.getId());
                 }
             }
 
-            ids.addAll(syncedFolders.values());
+            ArrayList<Long> ids = new ArrayList<>(syncedFolders.values());
 
             if (ids.size() > 0) {
                 int deletedCount = syncedFolderProvider.deleteSyncedFoldersNotInList(ids);
@@ -865,18 +880,11 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
         return dispatchingAndroidInjector;
     }
 
-
     public static void setAppTheme(DarkMode mode) {
         switch (mode) {
-            case LIGHT:
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
-                break;
-            case DARK:
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
-                break;
-            case SYSTEM:
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
-                break;
+            case LIGHT -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
+            case DARK -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
+            case SYSTEM -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
         }
     }
 }

+ 19 - 17
app/src/main/java/com/owncloud/android/datamodel/MediaFolder.java → app/src/main/java/com/owncloud/android/datamodel/MediaFolder.kt

@@ -16,29 +16,31 @@
  * 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/>.
+ * License along with this program. If not, see <http:></http:>//www.gnu.org/licenses/>.
  */
-package com.owncloud.android.datamodel;
-
-import java.util.ArrayList;
-import java.util.List;
+package com.owncloud.android.datamodel
 
 /**
  * Business object representing a media folder with all information that are gathered via media queries.
  */
-public class MediaFolder {
-    /** name of the folder. */
-    public String folderName;
+class MediaFolder {
+    /** name of the folder.  */
+    @JvmField
+    var folderName: String? = null
+
+    /** absolute path of the folder.  */
+    @JvmField
+    var absolutePath: String? = null
 
-    /** absolute path of the folder. */
-    public String absolutePath;
-    
-    /** list of file paths of the folder's content */
-    public List<String> filePaths = new ArrayList<>();
+    /** list of file paths of the folder's content  */
+    @JvmField
+    var filePaths: List<String> = ArrayList()
 
-    /** total number of files in the media folder. */
-    public long numberOfFiles;
+    /** total number of files in the media folder.  */
+    @JvmField
+    var numberOfFiles: Long = 0
 
-    /** type of media folder. */
-    public MediaFolderType type;
+    /** type of media folder.  */
+    @JvmField
+    var type: MediaFolderType? = null
 }

+ 18 - 27
app/src/main/java/com/owncloud/android/datamodel/MediaFolderType.java → app/src/main/java/com/owncloud/android/datamodel/MediaFolderType.kt

@@ -17,37 +17,28 @@
  * 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/>.
  */
-package com.owncloud.android.datamodel;
+package com.owncloud.android.datamodel
 
-import android.util.SparseArray;
+import android.util.SparseArray
 
 /**
  * Types of media folder.
  */
-public enum MediaFolderType {
-    CUSTOM(0),
-    IMAGE(1),
-    VIDEO(2);
-
-    private Integer id;
-
-    private static SparseArray<MediaFolderType> reverseMap = new SparseArray<>(3);
-
-    static {
-        reverseMap.put(CUSTOM.getId(), CUSTOM);
-        reverseMap.put(IMAGE.getId(), IMAGE);
-        reverseMap.put(VIDEO.getId(), VIDEO);
-    }
-
-    MediaFolderType(Integer id) {
-        this.id = id;
-    }
-
-    public static MediaFolderType getById(Integer id) {
-        return reverseMap.get(id);
-    }
-
-    public Integer getId() {
-        return this.id;
+enum class MediaFolderType(@JvmField val id: Int) {
+    CUSTOM(0), IMAGE(1), VIDEO(2);
+
+    companion object {
+        private val reverseMap = SparseArray<MediaFolderType>(3)
+
+        init {
+            reverseMap.put(CUSTOM.id, CUSTOM)
+            reverseMap.put(IMAGE.id, IMAGE)
+            reverseMap.put(VIDEO.id, VIDEO)
+        }
+
+        @JvmStatic
+        fun getById(id: Int?): MediaFolderType {
+            return reverseMap[id!!]
+        }
     }
 }

+ 0 - 51
app/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.java

@@ -1,51 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2018 Mario Danic
- * Copyright (C) 2018 Andy Scherzinger
- *
- * 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/>.
- */
-
-package com.owncloud.android.datamodel;
-
-import java.util.List;
-
-public class MediaFoldersModel {
-    private List<String> imageMediaFolders;
-    private List<String> videoMediaFolders;
-
-    public MediaFoldersModel(List<String> imageMediaFolders, List<String> videoMediaFolders) {
-        this.imageMediaFolders = imageMediaFolders;
-        this.videoMediaFolders = videoMediaFolders;
-    }
-
-    public List<String> getImageMediaFolders() {
-        return this.imageMediaFolders;
-    }
-
-    public List<String> getVideoMediaFolders() {
-        return this.videoMediaFolders;
-    }
-
-    public void setImageMediaFolders(List<String> imageMediaFolders) {
-        this.imageMediaFolders = imageMediaFolders;
-    }
-
-    public void setVideoMediaFolders(List<String> videoMediaFolders) {
-        this.videoMediaFolders = videoMediaFolders;
-    }
-}

+ 24 - 0
app/src/main/java/com/owncloud/android/datamodel/MediaFoldersModel.kt

@@ -0,0 +1,24 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2018 Mario Danic
+ * Copyright (C) 2018 Andy Scherzinger
+ *
+ * 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/>.
+ */
+package com.owncloud.android.datamodel
+
+class MediaFoldersModel(var imageMediaFolders: List<String>, var videoMediaFolders: List<String>)

+ 1 - 1
app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java

@@ -415,7 +415,7 @@ public class SyncedFolderProvider extends Observable {
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction());
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_NAME_COLLISION_POLICY,
                syncedFolder.getNameCollisionPolicyInt());
-        cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().getId());
+        cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE, syncedFolder.getType().id);
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_HIDDEN, syncedFolder.isHidden());
         cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_RULE, syncedFolder.getSubfolderRule().ordinal());
 

+ 7 - 0
app/src/main/java/com/owncloud/android/ui/activity/FileActivity.java

@@ -786,6 +786,13 @@ public abstract class FileActivity extends DrawerActivity
         }
     }
 
+    public void refreshList() {
+        final Fragment fileListFragment = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_LIST_OF_FILES);
+        if (fileListFragment != null)  {
+            ((OCFileListFragment) fileListFragment).onRefresh();
+        }
+    }
+
     private void onCreateShareViaLinkOperationFinish(CreateShareViaLinkOperation operation,
                                                      RemoteOperationResult result) {
         FileDetailSharingFragment sharingFragment = getShareFileFragment();

+ 19 - 19
app/src/main/java/com/owncloud/android/ui/adapter/ShareeListAdapter.java

@@ -25,6 +25,7 @@
 
 package com.owncloud.android.ui.adapter;
 
+import android.annotation.SuppressLint;
 import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
@@ -94,15 +95,15 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         switch (ShareType.fromValue(viewType)) {
-            case PUBLIC_LINK:
-            case EMAIL:
+            case PUBLIC_LINK, EMAIL -> {
                 return new LinkShareViewHolder(
                     FileDetailsShareLinkShareItemBinding.inflate(LayoutInflater.from(fileActivity),
                                                                  parent,
                                                                  false),
                     fileActivity,
                     viewThemeUtils);
-            case NEW_PUBLIC_LINK:
+            }
+            case NEW_PUBLIC_LINK -> {
                 if (encrypted) {
                     return new NewSecureFileDropViewHolder(
                         FileDetailsShareSecureFileDropAddNewItemBinding.inflate(LayoutInflater.from(fileActivity),
@@ -116,17 +117,20 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
                                                                             false)
                     );
                 }
-            case INTERNAL:
+            }
+            case INTERNAL -> {
                 return new InternalShareViewHolder(
                     FileDetailsShareInternalShareLinkBinding.inflate(LayoutInflater.from(fileActivity), parent, false),
                     fileActivity);
-            default:
+            }
+            default -> {
                 return new ShareViewHolder(FileDetailsShareShareItemBinding.inflate(LayoutInflater.from(fileActivity),
                                                                                     parent,
                                                                                     false),
                                            user,
                                            fileActivity,
                                            viewThemeUtils);
+            }
         }
     }
 
@@ -138,17 +142,13 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
 
         final OCShare share = shares.get(position);
 
-        if (holder instanceof LinkShareViewHolder) {
-            LinkShareViewHolder publicShareViewHolder = (LinkShareViewHolder) holder;
+        if (holder instanceof LinkShareViewHolder publicShareViewHolder) {
             publicShareViewHolder.bind(share, listener);
-        } else if (holder instanceof InternalShareViewHolder) {
-            InternalShareViewHolder internalShareViewHolder = (InternalShareViewHolder) holder;
+        } else if (holder instanceof InternalShareViewHolder internalShareViewHolder) {
             internalShareViewHolder.bind(share, listener);
-        } else if (holder instanceof NewLinkShareViewHolder) {
-            NewLinkShareViewHolder newLinkShareViewHolder = (NewLinkShareViewHolder) holder;
+        } else if (holder instanceof NewLinkShareViewHolder newLinkShareViewHolder) {
             newLinkShareViewHolder.bind(listener);
-        } else if (holder instanceof NewSecureFileDropViewHolder) {
-            NewSecureFileDropViewHolder newSecureFileDropViewHolder = (NewSecureFileDropViewHolder) holder;
+        } else if (holder instanceof NewSecureFileDropViewHolder newSecureFileDropViewHolder) {
             newSecureFileDropViewHolder.bind(listener);
         } else {
             ShareViewHolder userViewHolder = (ShareViewHolder) holder;
@@ -166,6 +166,7 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
         return shares.size();
     }
 
+    @SuppressLint("NotifyDataSetChanged")
     public void addShares(List<OCShare> sharesToAdd) {
         shares.addAll(sharesToAdd);
         sortShares();
@@ -174,22 +175,21 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
 
     @Override
     public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
-        if (callContext instanceof ImageView) {
-            ImageView iv = (ImageView) callContext;
+        if (callContext instanceof ImageView iv) {
             iv.setImageDrawable(avatarDrawable);
         }
     }
 
     @Override
     public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
-        if (callContext instanceof ImageView) {
-            ImageView iv = (ImageView) callContext;
+        if (callContext instanceof ImageView iv) {
             // needs to be changed once federated users have avatars
             return String.valueOf(iv.getTag()).equals(tag.split("@")[0]);
         }
         return false;
     }
 
+    @SuppressLint("NotifyDataSetChanged")
     public void remove(OCShare share) {
         shares.remove(share);
         notifyDataSetChanged();
@@ -210,8 +210,8 @@ public class ShareeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
             }
         }
 
-        Collections.sort(links, (o1, o2) -> Long.compare(o2.getSharedDate(), o1.getSharedDate()));
-        Collections.sort(users, (o1, o2) -> Long.compare(o2.getSharedDate(), o1.getSharedDate()));
+        links.sort((o1, o2) -> Long.compare(o2.getSharedDate(), o1.getSharedDate()));
+        users.sort((o1, o2) -> Long.compare(o2.getSharedDate(), o1.getSharedDate()));
 
         shares = links;
         shares.addAll(users);

+ 1 - 1
app/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java

@@ -248,7 +248,7 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SectionedV
     public int getSectionByLocalPathAndType(String localPath, int type) {
         for (int i = 0; i < filteredSyncFolderItems.size(); i++) {
             if (filteredSyncFolderItems.get(i).getLocalPath().equalsIgnoreCase(localPath) &&
-                filteredSyncFolderItems.get(i).getType().getId().equals(type)) {
+                filteredSyncFolderItems.get(i).getType().id == type) {
                 return i;
             }
         }

+ 1 - 1
app/src/main/java/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java

@@ -105,7 +105,7 @@ public class SyncedFolderParcelable implements Parcelable {
         dest.writeInt(existing ? 1 : 0);
         dest.writeInt(enabled ? 1 : 0);
         dest.writeInt(subfolderByDate ? 1 : 0);
-        dest.writeInt(type.getId());
+        dest.writeInt(type.id);
         dest.writeString(account);
         dest.writeInt(uploadAction);
         dest.writeInt(nameCollisionPolicy.serialize());

+ 2 - 2
app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -932,15 +932,15 @@ public class FileOperationsHelper {
     }
 
     public void renameFile(OCFile file, String newFilename) {
-        // RenameFile
         Intent service = new Intent(fileActivity, OperationsService.class);
+
         service.setAction(OperationsService.ACTION_RENAME);
         service.putExtra(OperationsService.EXTRA_ACCOUNT, fileActivity.getAccount());
         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
         service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
         mWaitingForOpId = fileActivity.getOperationsServiceBinder().queueNewOperation(service);
 
-        fileActivity.showLoadingDialog(fileActivity.getString(R.string.wait_a_moment));
+        fileActivity.refreshList();
     }
 
 

+ 0 - 227
app/src/main/java/com/owncloud/android/ui/trashbin/RemoteTrashbinRepository.java

@@ -1,227 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * @author TSI-mc
- * @author Chris Narkiewicz
- *
- * Copyright (C) 2018 Tobias Kaminsky
- * Copyright (C) 2018 Nextcloud GmbH.
- * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
- * Copyright (C) 2023 TSI-mc
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.trashbin;
-
-import android.os.AsyncTask;
-
-import com.nextcloud.client.account.User;
-import com.nextcloud.client.network.ClientFactory;
-import com.nextcloud.common.NextcloudClient;
-import com.owncloud.android.R;
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.trashbin.EmptyTrashbinRemoteOperation;
-import com.owncloud.android.lib.resources.trashbin.ReadTrashbinFolderRemoteOperation;
-import com.owncloud.android.lib.resources.trashbin.RemoveTrashbinFileRemoteOperation;
-import com.owncloud.android.lib.resources.trashbin.RestoreTrashbinFileRemoteOperation;
-import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
-
-import java.util.List;
-
-import androidx.annotation.NonNull;
-
-public class RemoteTrashbinRepository implements TrashbinRepository {
-
-    private final User user;
-    private final ClientFactory clientFactory;
-
-    RemoteTrashbinRepository(User user, ClientFactory clientFactory) {
-        this.user = user;
-        this.clientFactory = clientFactory;
-    }
-
-    public void removeTrashbinFile(TrashbinFile file, OperationCallback callback) {
-        new RemoveTrashbinFileTask(user, clientFactory, file, callback).execute();
-    }
-
-    private static class RemoveTrashbinFileTask extends AsyncTask<Void, Void, Boolean> {
-
-        private User user;
-        private ClientFactory clientFactory;
-        private TrashbinFile file;
-        private OperationCallback callback;
-
-        private RemoveTrashbinFileTask(User user,
-                                       ClientFactory clientFactory,
-                                       TrashbinFile file,
-                                       OperationCallback callback) {
-            this.user = user;
-            this.clientFactory = clientFactory;
-            this.file = file;
-            this.callback = callback;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            try {
-                OwnCloudClient client = clientFactory.create(user);
-                RemoteOperationResult result = new RemoveTrashbinFileRemoteOperation(file.getFullRemotePath())
-                    .execute(client);
-                return result.isSuccess();
-            } catch (ClientFactory.CreationException e) {
-                Log_OC.e(this, "Cannot create client", e);
-                return Boolean.FALSE;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean success) {
-            super.onPostExecute(success);
-
-            callback.onResult(success);
-        }
-    }
-
-    public void emptyTrashbin(OperationCallback callback) {
-        new EmptyTrashbinTask(user, clientFactory, callback).execute();
-    }
-
-    private static class EmptyTrashbinTask extends AsyncTask<Void, Void, Boolean> {
-
-        private User user;
-        private ClientFactory clientFactory;
-        private OperationCallback callback;
-
-        private EmptyTrashbinTask(User user, ClientFactory clientFactory, OperationCallback callback) {
-            this.user = user;
-            this.clientFactory = clientFactory;
-            this.callback = callback;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            try {
-                NextcloudClient client = clientFactory.createNextcloudClient(user);
-                EmptyTrashbinRemoteOperation emptyTrashbinFileOperation = new EmptyTrashbinRemoteOperation();
-                RemoteOperationResult<Boolean> result = emptyTrashbinFileOperation.execute(client);
-                return result.isSuccess();
-            } catch (ClientFactory.CreationException e) {
-                Log_OC.e(this, "Cannot create client", e);
-                return Boolean.FALSE;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean success) {
-            super.onPostExecute(success);
-
-            callback.onResult(success);
-        }
-    }
-
-    @Override
-    public void restoreFile(TrashbinFile file, OperationCallback callback) {
-        new RestoreTrashbinFileTask(file, user, clientFactory, callback).execute();
-    }
-
-    private static class RestoreTrashbinFileTask extends AsyncTask<Void, Void, Boolean> {
-
-        private TrashbinFile file;
-        private User user;
-        private ClientFactory clientFactory;
-        private TrashbinRepository.OperationCallback callback;
-
-        private RestoreTrashbinFileTask(TrashbinFile file, User user, ClientFactory clientFactory,
-                                        TrashbinRepository.OperationCallback callback) {
-            this.file = file;
-            this.user = user;
-            this.clientFactory = clientFactory;
-            this.callback = callback;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            try {
-                OwnCloudClient client = clientFactory.create(user);
-                RemoteOperationResult result = new RestoreTrashbinFileRemoteOperation(file.getFullRemotePath(),
-                                                                                      file.getFileName()).execute(client);
-
-                return result.isSuccess();
-            } catch (ClientFactory.CreationException e) {
-                Log_OC.e(this, "Cannot create client", e);
-                return Boolean.FALSE;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean success) {
-            super.onPostExecute(success);
-
-            callback.onResult(success);
-        }
-    }
-
-    @Override
-    public void getFolder(String remotePath, @NonNull LoadFolderCallback callback) {
-        new ReadRemoteTrashbinFolderTask(remotePath, user, clientFactory, callback).execute();
-    }
-
-    private static class ReadRemoteTrashbinFolderTask extends AsyncTask<Void, Void, Boolean> {
-
-        private String remotePath;
-        private User user;
-        private ClientFactory clientFactory;
-        private List<TrashbinFile> trashbinFiles;
-        private LoadFolderCallback callback;
-
-        private ReadRemoteTrashbinFolderTask(String remotePath, User user, ClientFactory clientFactory,
-                                             LoadFolderCallback callback) {
-            this.remotePath = remotePath;
-            this.user = user;
-            this.clientFactory = clientFactory;
-            this.callback = callback;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... voids) {
-            try {
-                OwnCloudClient client = clientFactory.create(user);
-                RemoteOperationResult<List<TrashbinFile>> result =
-                    new ReadTrashbinFolderRemoteOperation(remotePath).execute(client);
-                if (result.isSuccess()) {
-                    trashbinFiles = result.getResultData();
-                    return Boolean.TRUE;
-                } else {
-                    return Boolean.FALSE;
-                }
-            } catch (ClientFactory.CreationException e) {
-                return Boolean.FALSE;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean success) {
-            super.onPostExecute(success);
-
-            if (success) {
-                callback.onSuccess(trashbinFiles);
-            } else {
-                callback.onError(R.string.trashbin_loading_failed);
-            }
-        }
-    }
-}

+ 182 - 0
app/src/main/java/com/owncloud/android/ui/trashbin/RemoteTrashbinRepository.kt

@@ -0,0 +1,182 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * @author TSI-mc
+ * @author Chris Narkiewicz
+ *
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
+ * Copyright (C) 2023 TSI-mc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+@file:Suppress("DEPRECATION")
+
+package com.owncloud.android.ui.trashbin
+
+import android.os.AsyncTask
+import com.nextcloud.client.account.User
+import com.nextcloud.client.network.ClientFactory
+import com.nextcloud.client.network.ClientFactory.CreationException
+import com.owncloud.android.R
+import com.owncloud.android.lib.common.utils.Log_OC
+import com.owncloud.android.lib.resources.trashbin.EmptyTrashbinRemoteOperation
+import com.owncloud.android.lib.resources.trashbin.ReadTrashbinFolderRemoteOperation
+import com.owncloud.android.lib.resources.trashbin.RemoveTrashbinFileRemoteOperation
+import com.owncloud.android.lib.resources.trashbin.RestoreTrashbinFileRemoteOperation
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
+import com.owncloud.android.ui.trashbin.TrashbinRepository.LoadFolderCallback
+import com.owncloud.android.ui.trashbin.TrashbinRepository.OperationCallback
+
+class RemoteTrashbinRepository internal constructor(private val user: User, private val clientFactory: ClientFactory) :
+    TrashbinRepository {
+
+    override fun removeTrashbinFile(file: TrashbinFile?, callback: OperationCallback?) {
+        RemoveTrashbinFileTask(user, clientFactory, file, callback).execute()
+    }
+
+    private class RemoveTrashbinFileTask(
+        private val user: User,
+        private val clientFactory: ClientFactory,
+        private val file: TrashbinFile?,
+        private val callback: OperationCallback?
+    ) : AsyncTask<Void?, Void?, Boolean>() {
+
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg voids: Void?): Boolean {
+            return try {
+                val client = clientFactory.create(user)
+                val result = RemoveTrashbinFileRemoteOperation(file!!.fullRemotePath)
+                    .execute(client)
+                result.isSuccess
+            } catch (e: CreationException) {
+                Log_OC.e(this, "Cannot create client", e)
+                false
+            }
+        }
+
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(success: Boolean) {
+            super.onPostExecute(success)
+            callback?.onResult(success)
+        }
+    }
+
+    override fun emptyTrashbin(callback: OperationCallback?) {
+        EmptyTrashbinTask(user, clientFactory, callback).execute()
+    }
+
+    private class EmptyTrashbinTask(
+        private val user: User,
+        private val clientFactory: ClientFactory,
+        private val callback: OperationCallback?
+    ) : AsyncTask<Void?, Void?, Boolean>() {
+
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg voids: Void?): Boolean {
+            return try {
+                val client = clientFactory.createNextcloudClient(user)
+                val emptyTrashbinFileOperation = EmptyTrashbinRemoteOperation()
+                val result = emptyTrashbinFileOperation.execute(client)
+                result.isSuccess
+            } catch (e: CreationException) {
+                Log_OC.e(this, "Cannot create client", e)
+                false
+            }
+        }
+
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(success: Boolean) {
+            super.onPostExecute(success)
+            callback?.onResult(success)
+        }
+    }
+
+    override fun restoreFile(file: TrashbinFile?, callback: OperationCallback?) {
+        RestoreTrashbinFileTask(file, user, clientFactory, callback).execute()
+    }
+
+    private class RestoreTrashbinFileTask(
+        private val file: TrashbinFile?,
+        private val user: User,
+        private val clientFactory: ClientFactory,
+        private val callback: OperationCallback?
+    ) : AsyncTask<Void?, Void?, Boolean>() {
+
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg voids: Void?): Boolean {
+            return try {
+                val client = clientFactory.create(user)
+                val result = RestoreTrashbinFileRemoteOperation(
+                    file!!.fullRemotePath,
+                    file.fileName
+                ).execute(client)
+                result.isSuccess
+            } catch (e: CreationException) {
+                Log_OC.e(this, "Cannot create client", e)
+                false
+            }
+        }
+
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(success: Boolean) {
+            super.onPostExecute(success)
+            callback?.onResult(success)
+        }
+    }
+
+    override fun getFolder(remotePath: String?, callback: LoadFolderCallback?) {
+        callback?.let {
+            ReadRemoteTrashbinFolderTask(remotePath, user, clientFactory, it).execute()
+        }
+    }
+
+    private class ReadRemoteTrashbinFolderTask(
+        private val remotePath: String?,
+        private val user: User,
+        private val clientFactory: ClientFactory,
+        private val callback: LoadFolderCallback
+    ) : AsyncTask<Void?, Void?, Boolean>() {
+        private var trashbinFiles: List<TrashbinFile?>? = null
+
+        @Deprecated("Deprecated in Java")
+        override fun doInBackground(vararg voids: Void?): Boolean {
+            return try {
+                val client = clientFactory.create(user)
+                val result = ReadTrashbinFolderRemoteOperation(remotePath).execute(client)
+                if (result.isSuccess) {
+                    trashbinFiles = result.resultData
+                    true
+                } else {
+                    false
+                }
+            } catch (e: CreationException) {
+                false
+            }
+        }
+
+        @Deprecated("Deprecated in Java")
+        override fun onPostExecute(success: Boolean) {
+            super.onPostExecute(success)
+
+            if (success) {
+                callback.onSuccess(trashbinFiles)
+            } else {
+                callback.onError(R.string.trashbin_loading_failed)
+            }
+        }
+    }
+}

+ 0 - 334
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java

@@ -1,334 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * @author Chris Narkiewicz
- *
- * Copyright (C) 2018 Tobias Kaminsky
- * Copyright (C) 2018 Nextcloud GmbH.
- * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.trashbin;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.PopupMenu;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.google.android.material.snackbar.Snackbar;
-import com.nextcloud.client.account.CurrentAccountProvider;
-import com.nextcloud.client.account.User;
-import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.network.ClientFactory;
-import com.nextcloud.client.preferences.AppPreferences;
-import com.nextcloud.java.util.Optional;
-import com.owncloud.android.R;
-import com.owncloud.android.databinding.TrashbinActivityBinding;
-import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
-import com.owncloud.android.ui.EmptyRecyclerView;
-import com.owncloud.android.ui.activity.DrawerActivity;
-import com.owncloud.android.ui.adapter.TrashbinListAdapter;
-import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
-import com.owncloud.android.ui.interfaces.TrashbinActivityInterface;
-import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.FileSortOrder;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.core.content.res.ResourcesCompat;
-import androidx.recyclerview.widget.LinearLayoutManager;
-
-import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
-
-/**
- * Presenting trashbin data, received from presenter
- */
-public class TrashbinActivity extends DrawerActivity implements
-    TrashbinActivityInterface,
-    SortingOrderDialogFragment.OnSortingOrderListener,
-    TrashbinContract.View,
-    Injectable {
-
-    public static final int EMPTY_LIST_COUNT = 1;
-    @Inject AppPreferences preferences;
-    @Inject CurrentAccountProvider accountProvider;
-    @Inject ClientFactory clientFactory;
-    @Inject ViewThemeUtils viewThemeUtils;
-
-    private TrashbinListAdapter trashbinListAdapter;
-
-    @VisibleForTesting
-    TrashbinPresenter trashbinPresenter;
-
-    private boolean active;
-    private TrashbinActivityBinding binding;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        final User currentUser = getUser().orElse(accountProvider.getUser());
-        final String targetAccount = getIntent().getStringExtra(Intent.EXTRA_USER);
-        if (targetAccount != null && !currentUser.nameEquals(targetAccount)) {
-            final Optional<User> targetUser = getUserAccountManager().getUser(targetAccount);
-            if (targetUser.isPresent()) {
-                setUser(targetUser.get());
-            } else {
-                Toast.makeText(this, R.string.associated_account_not_found, Toast.LENGTH_LONG).show();
-                finish();
-                return;
-            }
-        }
-
-        final RemoteTrashbinRepository trashRepository =
-            new RemoteTrashbinRepository(getUser().orElse(accountProvider.getUser()), clientFactory);
-        trashbinPresenter = new TrashbinPresenter(trashRepository, this);
-
-        binding = TrashbinActivityBinding.inflate(getLayoutInflater());
-        setContentView(binding.getRoot());
-
-        setupToolbar();
-        findViewById(R.id.sort_list_button_group).setVisibility(View.VISIBLE);
-        findViewById(R.id.switch_grid_view_button).setVisibility(View.GONE);
-        updateActionBarTitleAndHomeButtonByString(getString(R.string.trashbin_activity_title));
-        setupDrawer(R.id.nav_trashbin);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        active = true;
-        setupContent();
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        setDrawerMenuItemChecked(R.id.nav_trashbin);
-    }
-
-    private void setupContent() {
-        EmptyRecyclerView recyclerView = binding.list;
-        recyclerView.setEmptyView(binding.emptyList.emptyListView);
-        binding.emptyList.emptyListView.setVisibility(View.GONE);
-        binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete);
-        binding.emptyList.emptyListIcon.setVisibility(View.VISIBLE);
-        binding.emptyList.emptyListViewHeadline.setText(getString(R.string.trashbin_empty_headline));
-        binding.emptyList.emptyListViewText.setText(getString(R.string.trashbin_empty_message));
-        binding.emptyList.emptyListViewText.setVisibility(View.VISIBLE);
-
-        trashbinListAdapter = new TrashbinListAdapter(
-            this,
-            getStorageManager(),
-            preferences,
-            this,
-            getUser().orElse(accountProvider.getUser()),
-            viewThemeUtils
-        );
-        recyclerView.setAdapter(trashbinListAdapter);
-        recyclerView.setHasFixedSize(true);
-        recyclerView.setHasFooter(true);
-        recyclerView.setLayoutManager(new LinearLayoutManager(this));
-
-        viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeContainingList);
-        binding.swipeContainingList.setOnRefreshListener(this::loadFolder);
-
-        viewThemeUtils.material.colorMaterialTextButton(findViewById(R.id.sort_button));
-
-        findViewById(R.id.sort_button).setOnClickListener(l ->
-                                                              openSortingOrderDialogFragment(getSupportFragmentManager(),
-                                                                                             preferences.getSortOrderByType(
-                                                                                                 FileSortOrder.Type.trashBinView,
-                                                                                                 FileSortOrder.sort_new_to_old))
-                                                         );
-
-        loadFolder();
-    }
-
-    protected void loadFolder() {
-        if (trashbinListAdapter.getItemCount() > EMPTY_LIST_COUNT) {
-            binding.swipeContainingList.setRefreshing(true);
-        } else {
-            showInitialLoading();
-        }
-        trashbinPresenter.loadFolder();
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        boolean retval = true;
-        int itemId = item.getItemId();
-        if (itemId == android.R.id.home) {
-            if (isDrawerOpen()) {
-                closeDrawer();
-            } else if (trashbinPresenter.isRoot()) {
-                onBackPressed();
-            } else {
-                openDrawer();
-            }
-        } else if (itemId == R.id.action_empty_trashbin) {
-            trashbinPresenter.emptyTrashbin();
-        } else {
-            retval = super.onOptionsItemSelected(item);
-        }
-
-        return retval;
-    }
-
-    @Override
-    public void onOverflowIconClicked(TrashbinFile file, View view) {
-        PopupMenu popup = new PopupMenu(this, view);
-        popup.inflate(R.menu.item_trashbin);
-
-        popup.setOnMenuItemClickListener(item -> {
-            trashbinPresenter.removeTrashbinFile(file);
-
-            return true;
-        });
-        popup.show();
-    }
-
-    @Override
-    public void onItemClicked(TrashbinFile file) {
-        if (file.isFolder()) {
-            trashbinPresenter.enterFolder(file.getRemotePath());
-
-            mDrawerToggle.setDrawerIndicatorEnabled(false);
-        }
-    }
-
-    @Override
-    public void onRestoreIconClicked(TrashbinFile file, View view) {
-        trashbinPresenter.restoreTrashbinFile(file);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.activity_trashbin, menu);
-
-        return true;
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        active = false;
-
-        trashbinListAdapter.cancelAllPendingTasks();
-    }
-
-    @Override
-    public void onBackPressed() {
-        trashbinPresenter.navigateUp();
-    }
-
-    public void close() {
-        super.onBackPressed();
-    }
-
-    public void setDrawerIndicatorEnabled(boolean bool) {
-        mDrawerToggle.setDrawerIndicatorEnabled(bool);
-    }
-
-
-    @Override
-    public void onSortingOrderChosen(FileSortOrder sortOrder) {
-        TextView sortButton = findViewById(R.id.sort_button);
-        sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder));
-        trashbinListAdapter.setSortOrder(sortOrder);
-    }
-
-    @Override
-    public void showTrashbinFolder(List<TrashbinFile> trashbinFiles) {
-        if (active) {
-            trashbinListAdapter.setTrashbinFiles(trashbinFiles, true);
-            binding.swipeContainingList.setRefreshing(false);
-            binding.loadingContent.setVisibility(View.GONE);
-            binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete);
-            binding.emptyList.emptyListViewHeadline.setText(getString(R.string.trashbin_empty_headline));
-            binding.emptyList.emptyListViewText.setText(getString(R.string.trashbin_empty_message));
-            binding.list.setVisibility(View.VISIBLE);
-        }
-    }
-
-    @Override
-    public void removeFile(TrashbinFile file) {
-        if (active) {
-            trashbinListAdapter.removeFile(file);
-        }
-    }
-
-    @Override
-    public void removeAllFiles() {
-        trashbinListAdapter.removeAllFiles();
-    }
-
-    @Override
-    public void showSnackbarError(int message, TrashbinFile file) {
-        if (active) {
-            binding.swipeContainingList.setRefreshing(false);
-            Snackbar.make(binding.list,
-                          String.format(getString(message), file.getFileName()), Snackbar.LENGTH_LONG)
-                .show();
-        }
-    }
-
-    @VisibleForTesting
-    public void showInitialLoading() {
-        binding.emptyList.emptyListView.setVisibility(View.GONE);
-        binding.list.setVisibility(View.GONE);
-        binding.loadingContent.setVisibility(View.VISIBLE);
-    }
-
-    @VisibleForTesting
-    public void showUser() {
-        binding.loadingContent.setVisibility(View.GONE);
-        binding.list.setVisibility(View.VISIBLE);
-        binding.swipeContainingList.setRefreshing(false);
-
-        binding.emptyList.emptyListViewText.setText(getUser().get().getAccountName());
-        binding.emptyList.emptyListViewText.setVisibility(View.VISIBLE);
-        binding.emptyList.emptyListView.setVisibility(View.VISIBLE);
-    }
-
-    @Override
-    public void showError(int message) {
-        if (active) {
-            trashbinListAdapter.removeAllFiles();
-            
-            binding.loadingContent.setVisibility(View.GONE);
-            binding.list.setVisibility(View.VISIBLE);
-            binding.swipeContainingList.setRefreshing(false);
-
-            binding.emptyList.emptyListViewHeadline.setText(R.string.common_error);
-            binding.emptyList.emptyListIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(),
-                                                                                         R.drawable.ic_list_empty_error,
-                                                                                         null));
-            binding.emptyList.emptyListViewText.setText(message);
-            binding.emptyList.emptyListViewText.setVisibility(View.VISIBLE);
-            binding.emptyList.emptyListIcon.setVisibility(View.VISIBLE);
-            binding.emptyList.emptyListView.setVisibility(View.VISIBLE);
-        }
-    }
-}

+ 340 - 0
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt

@@ -0,0 +1,340 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * @author Chris Narkiewicz
+ *
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.trashbin
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.PopupMenu
+import android.widget.TextView
+import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
+import androidx.annotation.VisibleForTesting
+import androidx.core.content.res.ResourcesCompat
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.client.account.CurrentAccountProvider
+import com.nextcloud.client.di.Injectable
+import com.nextcloud.client.network.ClientFactory
+import com.nextcloud.client.preferences.AppPreferences
+import com.owncloud.android.R
+import com.owncloud.android.databinding.TrashbinActivityBinding
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
+import com.owncloud.android.ui.activity.DrawerActivity
+import com.owncloud.android.ui.adapter.TrashbinListAdapter
+import com.owncloud.android.ui.dialog.SortingOrderDialogFragment.OnSortingOrderListener
+import com.owncloud.android.ui.interfaces.TrashbinActivityInterface
+import com.owncloud.android.utils.DisplayUtils
+import com.owncloud.android.utils.FileSortOrder
+import com.owncloud.android.utils.theme.ViewThemeUtils
+import javax.inject.Inject
+
+/**
+ * Presenting trashbin data, received from presenter
+ */
+class TrashbinActivity :
+    DrawerActivity(),
+    TrashbinActivityInterface,
+    OnSortingOrderListener,
+    TrashbinContract.View,
+    Injectable {
+
+    @JvmField
+    @Inject
+    var preferences: AppPreferences? = null
+
+    @JvmField
+    @Inject
+    var accountProvider: CurrentAccountProvider? = null
+
+    @JvmField
+    @Inject
+    var clientFactory: ClientFactory? = null
+
+    @JvmField
+    @Inject
+    var viewThemeUtils: ViewThemeUtils? = null
+
+    private var trashbinListAdapter: TrashbinListAdapter? = null
+
+    @VisibleForTesting
+    var trashbinPresenter: TrashbinPresenter? = null
+
+    private var active = false
+    private lateinit var binding: TrashbinActivityBinding
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        val currentUser = user.orElse(accountProvider!!.user)
+        val targetAccount = intent.getStringExtra(Intent.EXTRA_USER)
+
+        if (targetAccount != null && !currentUser.nameEquals(targetAccount)) {
+            val targetUser = userAccountManager.getUser(targetAccount)
+            if (targetUser.isPresent) {
+                setUser(targetUser.get())
+            } else {
+                Toast.makeText(this, R.string.associated_account_not_found, Toast.LENGTH_LONG).show()
+                finish()
+                return
+            }
+        }
+
+        clientFactory?.let {
+            val trashRepository = RemoteTrashbinRepository(user.orElse(accountProvider!!.user), it)
+            trashbinPresenter = TrashbinPresenter(trashRepository, this)
+        }
+
+        binding = TrashbinActivityBinding.inflate(layoutInflater)
+
+        setContentView(binding.root)
+        setupToolbar()
+
+        findViewById<View>(R.id.sort_list_button_group).visibility = View.VISIBLE
+        findViewById<View>(R.id.switch_grid_view_button).visibility =
+            View.GONE
+
+        updateActionBarTitleAndHomeButtonByString(getString(R.string.trashbin_activity_title))
+        setupDrawer(R.id.nav_trashbin)
+    }
+
+    override fun onStart() {
+        super.onStart()
+
+        active = true
+        setupContent()
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        setDrawerMenuItemChecked(R.id.nav_trashbin)
+    }
+
+    private fun setupContent() {
+        val recyclerView = binding.list
+        recyclerView.setEmptyView(binding.emptyList.emptyListView)
+
+        binding.emptyList.emptyListView.visibility = View.GONE
+        binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete)
+        binding.emptyList.emptyListIcon.visibility = View.VISIBLE
+        binding.emptyList.emptyListViewHeadline.text = getString(R.string.trashbin_empty_headline)
+        binding.emptyList.emptyListViewText.text = getString(R.string.trashbin_empty_message)
+        binding.emptyList.emptyListViewText.visibility = View.VISIBLE
+
+        trashbinListAdapter = TrashbinListAdapter(
+            this,
+            storageManager,
+            preferences,
+            this,
+            user.orElse(accountProvider!!.user),
+            viewThemeUtils
+        )
+
+        recyclerView.adapter = trashbinListAdapter
+        recyclerView.setHasFixedSize(true)
+        recyclerView.setHasFooter(true)
+        recyclerView.layoutManager = LinearLayoutManager(this)
+
+        viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeContainingList)
+        binding.swipeContainingList.setOnRefreshListener { loadFolder() }
+        viewThemeUtils.material.colorMaterialTextButton(findViewById(R.id.sort_button))
+
+        findViewById<View>(R.id.sort_button).setOnClickListener {
+            DisplayUtils.openSortingOrderDialogFragment(
+                supportFragmentManager,
+                preferences?.getSortOrderByType(
+                    FileSortOrder.Type.trashBinView,
+                    FileSortOrder.sort_new_to_old
+                )
+            )
+        }
+
+        loadFolder()
+
+        handleOnBackPressed()
+    }
+
+    private fun handleOnBackPressed() {
+        onBackPressedDispatcher.addCallback(
+            this,
+            object : OnBackPressedCallback(true) {
+                override fun handleOnBackPressed() {
+                    trashbinPresenter?.navigateUp()
+                }
+            }
+        )
+    }
+
+    fun loadFolder() {
+        trashbinListAdapter?.let {
+            if (it.itemCount > EMPTY_LIST_COUNT) {
+                binding.swipeContainingList.isRefreshing = true
+            } else {
+                showInitialLoading()
+            }
+
+            trashbinPresenter?.loadFolder()
+        }
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        var retval = true
+        val itemId = item.itemId
+        if (itemId == android.R.id.home) {
+            if (isDrawerOpen) {
+                closeDrawer()
+            } else if (trashbinPresenter?.isRoot == true) {
+                trashbinPresenter?.navigateUp()
+            } else {
+                openDrawer()
+            }
+        } else if (itemId == R.id.action_empty_trashbin) {
+            trashbinPresenter?.emptyTrashbin()
+        } else {
+            retval = super.onOptionsItemSelected(item)
+        }
+        return retval
+    }
+
+    override fun onOverflowIconClicked(file: TrashbinFile, view: View) {
+        val popup = PopupMenu(this, view)
+        popup.inflate(R.menu.item_trashbin)
+        popup.setOnMenuItemClickListener {
+            trashbinPresenter?.removeTrashbinFile(file)
+            true
+        }
+        popup.show()
+    }
+
+    override fun onItemClicked(file: TrashbinFile) {
+        if (file.isFolder) {
+            trashbinPresenter?.enterFolder(file.remotePath)
+            mDrawerToggle.isDrawerIndicatorEnabled = false
+        }
+    }
+
+    override fun onRestoreIconClicked(file: TrashbinFile, view: View) {
+        trashbinPresenter?.restoreTrashbinFile(file)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        menuInflater.inflate(R.menu.activity_trashbin, menu)
+        return true
+    }
+
+    override fun onPause() {
+        super.onPause()
+        active = false
+        trashbinListAdapter?.cancelAllPendingTasks()
+    }
+
+    override fun close() {
+        trashbinPresenter?.navigateUp()
+    }
+
+    override fun setDrawerIndicatorEnabled(bool: Boolean) {
+        mDrawerToggle.isDrawerIndicatorEnabled = bool
+    }
+
+    override fun onSortingOrderChosen(sortOrder: FileSortOrder?) {
+        val sortButton = findViewById<TextView>(R.id.sort_button)
+        sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder))
+        trashbinListAdapter?.setSortOrder(sortOrder)
+    }
+
+    override fun showTrashbinFolder(trashbinFiles: List<TrashbinFile?>?) {
+        if (active) {
+            trashbinListAdapter?.setTrashbinFiles(trashbinFiles, true)
+            binding.swipeContainingList.isRefreshing = false
+            binding.loadingContent.visibility = View.GONE
+            binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete)
+            binding.emptyList.emptyListViewHeadline.text = getString(R.string.trashbin_empty_headline)
+            binding.emptyList.emptyListViewText.text = getString(R.string.trashbin_empty_message)
+            binding.list.visibility = View.VISIBLE
+        }
+    }
+
+    override fun removeFile(file: TrashbinFile?) {
+        if (active) {
+            trashbinListAdapter?.removeFile(file)
+        }
+    }
+
+    override fun removeAllFiles() {
+        trashbinListAdapter?.removeAllFiles()
+    }
+
+    override fun showSnackbarError(message: Int, file: TrashbinFile?) {
+        if (active) {
+            binding.swipeContainingList.isRefreshing = false
+            Snackbar.make(binding.list, String.format(getString(message), file?.fileName), Snackbar.LENGTH_LONG)
+                .show()
+        }
+    }
+
+    @VisibleForTesting
+    fun showInitialLoading() {
+        binding.emptyList.emptyListView.visibility = View.GONE
+        binding.list.visibility = View.GONE
+        binding.loadingContent.visibility = View.VISIBLE
+    }
+
+    @VisibleForTesting
+    fun showUser() {
+        binding.loadingContent.visibility = View.GONE
+        binding.list.visibility = View.VISIBLE
+        binding.swipeContainingList.isRefreshing = false
+        binding.emptyList.emptyListViewText.text = user.get().accountName
+        binding.emptyList.emptyListViewText.visibility = View.VISIBLE
+        binding.emptyList.emptyListView.visibility = View.VISIBLE
+    }
+
+    override fun showError(message: Int) {
+        if (active) {
+            trashbinListAdapter?.removeAllFiles()
+            binding.loadingContent.visibility = View.GONE
+            binding.list.visibility = View.VISIBLE
+            binding.swipeContainingList.isRefreshing = false
+            binding.emptyList.emptyListViewHeadline.setText(R.string.common_error)
+            binding.emptyList.emptyListIcon.setImageDrawable(
+                ResourcesCompat.getDrawable(
+                    resources,
+                    R.drawable.ic_list_empty_error,
+                    null
+                )
+            )
+            binding.emptyList.emptyListViewText.setText(message)
+            binding.emptyList.emptyListViewText.visibility = View.VISIBLE
+            binding.emptyList.emptyListIcon.visibility = View.VISIBLE
+            binding.emptyList.emptyListView.visibility = View.VISIBLE
+        }
+    }
+
+    companion object {
+        const val EMPTY_LIST_COUNT = 1
+    }
+}

+ 17 - 33
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinContract.java → app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinContract.kt

@@ -18,47 +18,31 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.trashbin;
+package com.owncloud.android.ui.trashbin
 
-import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
-
-import java.util.List;
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
 
 /**
  * Contract between view (TrashbinActivity) and presenter (TrashbinPresenter)
  */
-public interface TrashbinContract {
-
+interface TrashbinContract {
     interface View {
-        void showTrashbinFolder(List<TrashbinFile> trashbinFiles);
-
-        void showSnackbarError(int message, TrashbinFile file);
-
-        void showError(int message);
-
-        void removeFile(TrashbinFile file);
-
-        void removeAllFiles();
-
-        void close();
-
-        void setDrawerIndicatorEnabled(boolean bool);
+        fun showTrashbinFolder(trashbinFiles: List<TrashbinFile?>?)
+        fun showSnackbarError(message: Int, file: TrashbinFile?)
+        fun showError(message: Int)
+        fun removeFile(file: TrashbinFile?)
+        fun removeAllFiles()
+        fun close()
+        fun setDrawerIndicatorEnabled(bool: Boolean)
     }
 
     interface Presenter {
-
-        boolean isRoot();
-
-        void loadFolder();
-
-        void navigateUp();
-
-        void enterFolder(String folder);
-
-        void restoreTrashbinFile(TrashbinFile file);
-
-        void removeTrashbinFile(TrashbinFile file);
-
-        void emptyTrashbin();
+        val isRoot: Boolean
+        fun loadFolder()
+        fun navigateUp()
+        fun enterFolder(folder: String?)
+        fun restoreTrashbinFile(file: TrashbinFile?)
+        fun removeTrashbinFile(file: TrashbinFile?)
+        fun emptyTrashbin()
     }
 }

+ 0 - 116
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinPresenter.java

@@ -1,116 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * Copyright (C) 2018 Tobias Kaminsky
- * Copyright (C) 2018 Nextcloud GmbH.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.trashbin;
-
-import com.owncloud.android.R;
-import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
-
-import java.io.File;
-import java.util.List;
-
-import static com.owncloud.android.datamodel.OCFile.ROOT_PATH;
-
-/**
- * Coordinates between model and view: querying model, updating view, react to UI input
- */
-public class TrashbinPresenter implements TrashbinContract.Presenter {
-
-    private TrashbinContract.View trashbinView;
-    private TrashbinRepository trashbinRepository;
-    private String currentPath = ROOT_PATH;
-
-    public TrashbinPresenter(TrashbinRepository trashbinRepository, TrashbinContract.View trashbinView) {
-        this.trashbinRepository = trashbinRepository;
-        this.trashbinView = trashbinView;
-    }
-
-    @Override
-    public void enterFolder(String folder) {
-        currentPath = folder;
-        loadFolder();
-    }
-
-    @Override
-    public boolean isRoot() {
-        return !ROOT_PATH.equals(currentPath);
-    }
-
-    @Override
-    public void navigateUp() {
-        if (ROOT_PATH.equals(currentPath)) {
-            trashbinView.close();
-        } else {
-            currentPath = new File(currentPath).getParent();
-
-            loadFolder();
-        }
-
-        trashbinView.setDrawerIndicatorEnabled(ROOT_PATH.equals(currentPath));
-    }
-
-    @Override
-    public void loadFolder() {
-        trashbinRepository.getFolder(currentPath, new TrashbinRepository.LoadFolderCallback() {
-            @Override
-            public void onSuccess(List<TrashbinFile> files) {
-                trashbinView.showTrashbinFolder(files);
-            }
-
-            @Override
-            public void onError(int error) {
-                trashbinView.showError(error);
-            }
-        });
-    }
-
-    @Override
-    public void restoreTrashbinFile(TrashbinFile file) {
-        trashbinRepository.restoreFile(file, success -> {
-            if (success) {
-                trashbinView.removeFile(file);
-            } else {
-                trashbinView.showSnackbarError(R.string.trashbin_file_not_restored, file);
-            }
-        });
-    }
-
-    @Override
-    public void removeTrashbinFile(TrashbinFile file) {
-        trashbinRepository.removeTrashbinFile(file, success -> {
-            if (success) {
-                trashbinView.removeFile(file);
-            } else {
-                trashbinView.showSnackbarError(R.string.trashbin_file_not_deleted, file);
-            }
-        });
-    }
-
-    @Override
-    public void emptyTrashbin() {
-        trashbinRepository.emptyTrashbin(success -> {
-            if (success) {
-                trashbinView.removeAllFiles();
-            } else {
-                trashbinView.showError(R.string.trashbin_not_emptied);
-            }
-        });
-    }
-}

+ 117 - 0
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinPresenter.kt

@@ -0,0 +1,117 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.trashbin
+
+import com.owncloud.android.R
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
+import com.owncloud.android.ui.trashbin.TrashbinContract.Presenter
+import com.owncloud.android.ui.trashbin.TrashbinRepository.LoadFolderCallback
+import java.io.File
+
+/**
+ * Coordinates between model and view: querying model, updating view, react to UI input
+ */
+class TrashbinPresenter(
+    private val trashbinRepository: TrashbinRepository,
+    private val trashbinView: TrashbinContract.View
+) : Presenter {
+
+    private var currentPath: String? = OCFile.ROOT_PATH
+
+    override fun enterFolder(folder: String?) {
+        currentPath = folder
+        loadFolder()
+    }
+
+    override val isRoot: Boolean
+        get() = OCFile.ROOT_PATH != currentPath
+
+    override fun navigateUp() {
+        if (OCFile.ROOT_PATH == currentPath) {
+            trashbinView.close()
+        } else {
+            currentPath?.let {
+                currentPath = File(it).parent
+                loadFolder()
+            }
+        }
+
+        trashbinView.setDrawerIndicatorEnabled(OCFile.ROOT_PATH == currentPath)
+    }
+
+    override fun loadFolder() {
+        trashbinRepository.getFolder(
+            currentPath,
+            object : LoadFolderCallback {
+                override fun onSuccess(files: List<TrashbinFile?>?) {
+                    trashbinView.showTrashbinFolder(files)
+                }
+
+                override fun onError(error: Int) {
+                    trashbinView.showError(error)
+                }
+            }
+        )
+    }
+
+    override fun restoreTrashbinFile(file: TrashbinFile?) {
+        trashbinRepository.restoreFile(
+            file,
+            object : TrashbinRepository.OperationCallback {
+                override fun onResult(success: Boolean) {
+                    if (success) {
+                        trashbinView.removeFile(file)
+                    } else {
+                        trashbinView.showSnackbarError(R.string.trashbin_file_not_restored, file)
+                    }
+                }
+            }
+        )
+    }
+
+    override fun removeTrashbinFile(file: TrashbinFile?) {
+        trashbinRepository.removeTrashbinFile(
+            file,
+            object : TrashbinRepository.OperationCallback {
+                override fun onResult(success: Boolean) {
+                    if (success) {
+                        trashbinView.removeFile(file)
+                    } else {
+                        trashbinView.showSnackbarError(R.string.trashbin_file_not_deleted, file)
+                    }
+                }
+            }
+        )
+    }
+
+    override fun emptyTrashbin() {
+        trashbinRepository.emptyTrashbin(object : TrashbinRepository.OperationCallback {
+            override fun onResult(success: Boolean) {
+                if (success) {
+                    trashbinView.removeAllFiles()
+                } else {
+                    trashbinView.showError(R.string.trashbin_not_emptied)
+                }
+            }
+        })
+    }
+}

+ 10 - 16
app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinRepository.java → app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinRepository.kt

@@ -18,31 +18,25 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.trashbin;
+package com.owncloud.android.ui.trashbin
 
-import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
-
-import java.util.List;
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
 
 /**
  * Contract between presenter and model
  */
-public interface TrashbinRepository {
+interface TrashbinRepository {
     interface LoadFolderCallback {
-        void onSuccess(List<TrashbinFile> files);
-
-        void onError(int error);
+        fun onSuccess(files: List<TrashbinFile?>?)
+        fun onError(error: Int)
     }
 
     interface OperationCallback {
-        void onResult(boolean success);
+        fun onResult(success: Boolean)
     }
 
-    void getFolder(String remotePath, LoadFolderCallback callback);
-
-    void restoreFile(TrashbinFile file, OperationCallback callback);
-
-    void emptyTrashbin(OperationCallback callback);
-
-    void removeTrashbinFile(TrashbinFile file, OperationCallback callback);
+    fun getFolder(remotePath: String?, callback: LoadFolderCallback?)
+    fun restoreFile(file: TrashbinFile?, callback: OperationCallback?)
+    fun emptyTrashbin(callback: OperationCallback?)
+    fun removeTrashbinFile(file: TrashbinFile?, callback: OperationCallback?)
 }

+ 1 - 1
scripts/analysis/lint-results.txt

@@ -1,2 +1,2 @@
 DO NOT TOUCH; GENERATED BY DRONE
-      <span class="mdl-layout-title">Lint Report: 77 warnings</span>
+      <span class="mdl-layout-title">Lint Report: 75 warnings</span>