Procházet zdrojové kódy

Fix merge conflict

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk před 1 rokem
rodič
revize
2f1e3ea2b4
47 změnil soubory, kde provedl 533 přidání a 484 odebrání
  1. 1 1
      .github/workflows/assembleFlavors.yml
  2. 1 1
      .github/workflows/check.yml
  3. 1 1
      .github/workflows/detectWrongSettings.yml
  4. 1 1
      .github/workflows/qa.yml
  5. 1 1
      .github/workflows/screenShotTest.yml
  6. 1 1
      .github/workflows/unit-tests.yml
  7. 4 0
      app/build.gradle
  8. 3 0
      app/src/main/AndroidManifest.xml
  9. 16 0
      app/src/main/java/com/nextcloud/client/jobs/FilesUploadWorker.kt
  10. 67 46
      app/src/main/java/com/nextcloud/client/widget/DashboardWidgetService.kt
  11. 6 1
      app/src/main/java/com/owncloud/android/files/services/FileDownloader.java
  12. 51 4
      app/src/main/java/com/owncloud/android/files/services/FileUploader.java
  13. 11 7
      app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
  14. 89 70
      app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java
  15. 176 0
      app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt
  16. 0 156
      app/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java
  17. 2 6
      app/src/main/java/com/owncloud/android/ui/events/AccountRemovedEvent.kt
  18. 3 4
      app/src/main/java/com/owncloud/android/ui/events/ChangeMenuEvent.kt
  19. 2 9
      app/src/main/java/com/owncloud/android/ui/events/CommentsEvent.kt
  20. 3 4
      app/src/main/java/com/owncloud/android/ui/events/DummyDrawerEvent.kt
  21. 0 37
      app/src/main/java/com/owncloud/android/ui/events/EncryptionEvent.java
  22. 30 0
      app/src/main/java/com/owncloud/android/ui/events/EncryptionEvent.kt
  23. 0 33
      app/src/main/java/com/owncloud/android/ui/events/FavoriteEvent.java
  24. 6 9
      app/src/main/java/com/owncloud/android/ui/events/FavoriteEvent.kt
  25. 0 35
      app/src/main/java/com/owncloud/android/ui/events/InitiateSyncedFolder.java
  26. 0 33
      app/src/main/java/com/owncloud/android/ui/events/MenuItemClickEvent.java
  27. 2 3
      app/src/main/java/com/owncloud/android/ui/events/TokenPushEvent.kt
  28. 22 0
      app/src/main/java/com/owncloud/android/ui/events/VCardToggleEvent.kt
  29. 4 4
      app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
  30. 9 9
      app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
  31. 1 1
      app/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/BackupListFragment.java
  32. 2 0
      app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java
  33. 2 0
      app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java
  34. 2 0
      app/src/main/java/com/owncloud/android/ui/preview/PreviewTextFileFragment.java
  35. 2 1
      app/src/main/res/layout/receive_external_files.xml
  36. 1 0
      app/src/main/res/values-ar/strings.xml
  37. 1 0
      app/src/main/res/values-cs-rCZ/strings.xml
  38. 1 0
      app/src/main/res/values-de/strings.xml
  39. 1 0
      app/src/main/res/values-gl/strings.xml
  40. 1 0
      app/src/main/res/values-sr/strings.xml
  41. 2 2
      app/src/main/res/values-uk/strings.xml
  42. 1 0
      app/src/main/res/values-zh-rCN/strings.xml
  43. 1 0
      app/src/main/res/values-zh-rTW/strings.xml
  44. 1 1
      build.gradle
  45. 0 1
      gradle.properties
  46. 1 1
      gradle/wrapper/gradle-wrapper.properties
  47. 1 1
      scripts/analysis/lint-results.txt

+ 1 - 1
.github/workflows/assembleFlavors.yml

@@ -21,7 +21,7 @@ jobs:
         steps:
             -   uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
             -   name: set up JDK 17
-                uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
+                uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
                 with:
                     distribution: "temurin"
                     java-version: 17

+ 1 - 1
.github/workflows/check.yml

@@ -21,7 +21,7 @@ jobs:
         steps:
             -   uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
             -   name: Set up JDK 17
-                uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
+                uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
                 with:
                     distribution: "temurin"
                     java-version: 17

+ 1 - 1
.github/workflows/detectWrongSettings.yml

@@ -18,7 +18,7 @@ jobs:
         steps:
             -   uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
             -   name: Set up JDK 17
-                uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
+                uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
                 with:
                     distribution: "temurin"
                     java-version: 17

+ 1 - 1
.github/workflows/qa.yml

@@ -22,7 +22,7 @@ jobs:
             -   uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
                 if: ${{ steps.check-secrets.outputs.ok == 'true' }}
             -   name: set up JDK 17
-                uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
+                uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
                 if: ${{ steps.check-secrets.outputs.ok == 'true' }}
                 with:
                     distribution: "temurin"

+ 1 - 1
.github/workflows/screenShotTest.yml

@@ -40,7 +40,7 @@ jobs:
                         ~/.android/adb*
                     key: avd-${{ matrix.api-level }}
 
-            -   uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
+            -   uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
                 with:
                     distribution: "temurin"
                     java-version: 17

+ 1 - 1
.github/workflows/unit-tests.yml

@@ -20,7 +20,7 @@ jobs:
         steps:
             -   uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
             -   name: Set up JDK 17
-                uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
+                uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
                 with:
                     distribution: "temurin"
                     java-version: 17

+ 4 - 0
app/build.gradle

@@ -126,6 +126,10 @@ android {
             }
         }
 
+        buildFeatures {
+            buildConfig = true
+        }
+
         productFlavors {
             // used for f-droid
             generic {

+ 3 - 0
app/src/main/AndroidManifest.xml

@@ -169,6 +169,9 @@
         <receiver
             android:name="com.nextcloud.client.jobs.NotificationWork$NotificationReceiver"
             android:exported="false" />
+        <receiver
+            android:name="com.owncloud.android.files.services.FileUploader$UploadNotificationActionReceiver"
+            android:exported="false" />
         <receiver
             android:name="com.nextcloud.client.widget.DashboardWidgetProvider"
             android:exported="false">

+ 16 - 0
app/src/main/java/com/nextcloud/client/jobs/FilesUploadWorker.kt

@@ -43,6 +43,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.ThumbnailsCacheManager
 import com.owncloud.android.datamodel.UploadsStorageManager
 import com.owncloud.android.db.OCUpload
+import com.owncloud.android.files.services.FileUploader
 import com.owncloud.android.lib.common.OwnCloudAccount
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
@@ -197,6 +198,18 @@ class FilesUploadWorker(
      * adapted from [com.owncloud.android.files.services.FileUploader.notifyUploadStart]
      */
     private fun createNotification(uploadFileOperation: UploadFileOperation) {
+        val notificationActionIntent = Intent(context, FileUploader.UploadNotificationActionReceiver::class.java)
+        notificationActionIntent.putExtra(FileUploader.EXTRA_ACCOUNT_NAME, uploadFileOperation.user.accountName)
+        notificationActionIntent.putExtra(FileUploader.EXTRA_REMOTE_PATH, uploadFileOperation.remotePath)
+        notificationActionIntent.action = FileUploader.ACTION_CANCEL_BROADCAST
+
+        val pendingIntent = PendingIntent.getBroadcast(
+            context,
+            SecureRandom().nextInt(),
+            notificationActionIntent,
+            PendingIntent.FLAG_IMMUTABLE
+        )
+
         notificationBuilder
             .setOngoing(true)
             .setSmallIcon(R.drawable.notification_icon)
@@ -209,6 +222,8 @@ class FilesUploadWorker(
                     uploadFileOperation.fileName
                 )
             )
+            .clearActions() // to make sure there is only one action
+            .addAction(R.drawable.ic_action_cancel_grey, context.getString(R.string.common_cancel), pendingIntent)
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD)
@@ -275,6 +290,7 @@ class FilesUploadWorker(
                 .setAutoCancel(true)
                 .setOngoing(false)
                 .setProgress(0, 0, false)
+                .clearActions()
 
             val content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, uploadFileOperation, context.resources)
 

+ 67 - 46
app/src/main/java/com/nextcloud/client/widget/DashboardWidgetService.kt

@@ -86,7 +86,7 @@ class StackRemoteViewsFactory(
     val userAccountManager: UserAccountManager,
     val clientFactory: ClientFactory,
     val intent: Intent,
-    val widgetRepository: WidgetRepository
+    private val widgetRepository: WidgetRepository
 ) : RemoteViewsService.RemoteViewsFactory {
 
     private lateinit var widgetConfiguration: WidgetConfiguration
@@ -163,58 +163,20 @@ class StackRemoteViewsFactory(
 
     // we will switch soon to coil and then streamline all of this
     // Kotlin cannot catch multiple exception types at same time
-    @Suppress("NestedBlockDepth", "TooGenericExceptionCaught")
+    @Suppress("NestedBlockDepth")
     private fun createItemView(position: Int): RemoteViews {
         return RemoteViews(context.packageName, R.layout.widget_item).apply {
+            if (widgetItems.isEmpty()) {
+                return@apply
+            }
+
             val widgetItem = widgetItems[position]
 
-            // icon bitmap/svg
             if (widgetItem.iconUrl.isNotEmpty()) {
-                val glide: FutureTarget<Bitmap>
-                if (Uri.parse(widgetItem.iconUrl).encodedPath!!.endsWith(".svg")) {
-                    glide = Glide.with(context)
-                        .using(
-                            CustomGlideUriLoader(userAccountManager.user, clientFactory),
-                            InputStream::class.java
-                        )
-                        .from(Uri::class.java)
-                        .`as`(SVGorImage::class.java)
-                        .transcode(SvgOrImageBitmapTranscoder(SVG_SIZE, SVG_SIZE), Bitmap::class.java)
-                        .sourceEncoder(StreamEncoder())
-                        .cacheDecoder(FileToStreamDecoder(SvgOrImageDecoder()))
-                        .decoder(SvgOrImageDecoder())
-                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
-                        .load(Uri.parse(widgetItem.iconUrl))
-                        .into(SVG_SIZE, SVG_SIZE)
-                } else {
-                    glide = Glide.with(context)
-                        .using(CustomGlideStreamLoader(widgetConfiguration.user.get(), clientFactory))
-                        .load(widgetItem.iconUrl)
-                        .asBitmap()
-                        .into(SVG_SIZE, SVG_SIZE)
-                }
-
-                try {
-                    if (widgetConfiguration.roundIcon) {
-                        setImageViewBitmap(R.id.icon, BitmapUtils.roundBitmap(glide.get()))
-                    } else {
-                        setImageViewBitmap(R.id.icon, glide.get())
-                    }
-                } catch (e: Exception) {
-                    Log_OC.d(TAG, "Error setting icon", e)
-                    setImageViewResource(R.id.icon, R.drawable.ic_dashboard)
-                }
+                loadIcon(widgetItem, this)
             }
 
-            // text
-            setTextViewText(R.id.title, widgetItem.title)
-
-            if (widgetItem.subtitle.isNotEmpty()) {
-                setViewVisibility(R.id.subtitle, View.VISIBLE)
-                setTextViewText(R.id.subtitle, widgetItem.subtitle)
-            } else {
-                setViewVisibility(R.id.subtitle, View.GONE)
-            }
+            updateTexts(widgetItem, this)
 
             if (widgetItem.link.isNotEmpty()) {
                 val clickIntent = Intent(Intent.ACTION_VIEW, Uri.parse(widgetItem.link))
@@ -223,6 +185,65 @@ class StackRemoteViewsFactory(
         }
     }
 
+    @Suppress("TooGenericExceptionCaught")
+    private fun loadIcon(widgetItem: DashboardWidgetItem, remoteViews: RemoteViews) {
+        val isIconSVG = Uri.parse(widgetItem.iconUrl).encodedPath!!.endsWith(".svg")
+        val source: FutureTarget<Bitmap> = if (isIconSVG) {
+            loadSVGIcon(widgetItem)
+        } else {
+            loadBitmapIcon(widgetItem)
+        }
+
+        try {
+            val bitmap: Bitmap = if (widgetConfiguration.roundIcon) {
+                BitmapUtils.roundBitmap(source.get())
+            } else {
+                source.get()
+            }
+
+            remoteViews.setImageViewBitmap(R.id.icon, bitmap)
+        } catch (e: Exception) {
+            Log_OC.d(TAG, "Error setting icon", e)
+            remoteViews.setImageViewResource(R.id.icon, R.drawable.ic_dashboard)
+        }
+    }
+
+    private fun loadSVGIcon(widgetItem: DashboardWidgetItem): FutureTarget<Bitmap> {
+        return Glide.with(context)
+            .using(
+                CustomGlideUriLoader(userAccountManager.user, clientFactory),
+                InputStream::class.java
+            )
+            .from(Uri::class.java)
+            .`as`(SVGorImage::class.java)
+            .transcode(SvgOrImageBitmapTranscoder(SVG_SIZE, SVG_SIZE), Bitmap::class.java)
+            .sourceEncoder(StreamEncoder())
+            .cacheDecoder(FileToStreamDecoder(SvgOrImageDecoder()))
+            .decoder(SvgOrImageDecoder())
+            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
+            .load(Uri.parse(widgetItem.iconUrl))
+            .into(SVG_SIZE, SVG_SIZE)
+    }
+
+    private fun loadBitmapIcon(widgetItem: DashboardWidgetItem): FutureTarget<Bitmap> {
+        return Glide.with(context)
+            .using(CustomGlideStreamLoader(widgetConfiguration.user.get(), clientFactory))
+            .load(widgetItem.iconUrl)
+            .asBitmap()
+            .into(SVG_SIZE, SVG_SIZE)
+    }
+
+    private fun updateTexts(widgetItem: DashboardWidgetItem, remoteViews: RemoteViews) {
+        remoteViews.setTextViewText(R.id.title, widgetItem.title)
+
+        if (widgetItem.subtitle.isNotEmpty()) {
+            remoteViews.setViewVisibility(R.id.subtitle, View.VISIBLE)
+            remoteViews.setTextViewText(R.id.subtitle, widgetItem.subtitle)
+        } else {
+            remoteViews.setViewVisibility(R.id.subtitle, View.GONE)
+        }
+    }
+
     override fun getLoadingView(): RemoteViews? {
         return null
     }

+ 6 - 1
app/src/main/java/com/owncloud/android/files/services/FileDownloader.java

@@ -83,6 +83,7 @@ import java.util.Vector;
 import javax.inject.Inject;
 
 import androidx.core.app.NotificationCompat;
+import androidx.core.app.ServiceCompat;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import dagger.android.AndroidInjection;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -203,7 +204,11 @@ public class FileDownloader extends Service
         Log_OC.d(TAG, "Starting command with id " + startId);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            startForeground(FOREGROUND_SERVICE_ID, mNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
+            ServiceCompat.startForeground(
+                this,
+                FOREGROUND_SERVICE_ID,
+                mNotification,
+                ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
         } else {
             startForeground(FOREGROUND_SERVICE_ID, mNotification);
         }

+ 51 - 4
app/src/main/java/com/owncloud/android/files/services/FileUploader.java

@@ -34,6 +34,7 @@ import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ServiceInfo;
@@ -128,6 +129,10 @@ public class FileUploader extends Service
     public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
     public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
 
+    public static final String EXTRA_ACCOUNT_NAME = "ACCOUNT_NAME";
+    public static final String ACTION_CANCEL_BROADCAST = "CANCEL";
+    public static final String ACTION_PAUSE_BROADCAST = "PAUSE";
+
     private static final int FOREGROUND_SERVICE_ID = 411;
 
     public static final String KEY_FILE = "FILE";
@@ -198,11 +203,13 @@ public class FileUploader extends Service
     private Notification mNotification;
     private Looper mServiceLooper;
     private ServiceHandler mServiceHandler;
-    private IBinder mBinder;
+    private static IBinder mBinder;
     private OwnCloudClient mUploadClient;
     private Account mCurrentAccount;
     private FileDataStorageManager mStorageManager;
 
+    private SecureRandom secureRandomGenerator = new SecureRandom();
+
     @Inject UserAccountManager accountManager;
     @Inject UploadsStorageManager mUploadsStorageManager;
     @Inject ConnectivityService connectivityService;
@@ -233,6 +240,7 @@ public class FileUploader extends Service
     /**
      * Service initialization
      */
+    @SuppressFBWarnings("ST")
     @Override
     public void onCreate() {
         super.onCreate();
@@ -280,6 +288,7 @@ public class FileUploader extends Service
     /**
      * Service clean up
      */
+    @SuppressFBWarnings("ST")
     @Override
     public void onDestroy() {
         Log_OC.v(TAG, "Destroying service");
@@ -708,6 +717,12 @@ public class FileUploader extends Service
      */
     private void notifyUploadStart(UploadFileOperation upload) {
         // / create status notification with a progress bar
+        Intent notificationActionIntent = new Intent(getApplicationContext(),UploadNotificationActionReceiver.class);
+        notificationActionIntent.putExtra(EXTRA_ACCOUNT_NAME,upload.getUser().getAccountName());
+        notificationActionIntent.putExtra(EXTRA_REMOTE_PATH,upload.getRemotePath());
+        notificationActionIntent.setAction(ACTION_CANCEL_BROADCAST);
+
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),secureRandomGenerator.nextInt(),notificationActionIntent, PendingIntent.FLAG_IMMUTABLE);
         mLastPercent = 0;
         mNotificationBuilder = NotificationUtils.newNotificationBuilder(this, viewThemeUtils);
         mNotificationBuilder
@@ -718,7 +733,10 @@ public class FileUploader extends Service
             .setProgress(100, 0, false)
             .setContentText(
                 String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName())
-                           );
+                           )
+            .clearActions() // to make sure there is only one action
+            .addAction(R.drawable.ic_action_cancel_grey,getApplicationContext().getString(R.string.common_cancel),pendingIntent);
+
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             mNotificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD);
@@ -811,7 +829,8 @@ public class FileUploader extends Service
                 .setContentTitle(getString(tickerId))
                 .setAutoCancel(true)
                 .setOngoing(false)
-                .setProgress(0, 0, false);
+                .setProgress(0, 0, false)
+                .clearActions();
 
             content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, upload, getResources());
 
@@ -859,7 +878,7 @@ public class FileUploader extends Service
 
             mNotificationBuilder.setContentText(content);
             if (!uploadResult.isSuccess()) {
-                mNotificationManager.notify((new SecureRandom()).nextInt(), mNotificationBuilder.build());
+                mNotificationManager.notify(secureRandomGenerator.nextInt(), mNotificationBuilder.build());
             }
         }
     }
@@ -1408,4 +1427,32 @@ public class FileUploader extends Service
             mService.stopSelf(msg.arg1);
         }
     }
+
+
+    /**
+     * When cancel action in upload notification is pressed, cancel upload of item
+     */
+    public static class UploadNotificationActionReceiver extends BroadcastReceiver {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+
+            String accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME);
+            String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
+            String action = intent.getAction();
+
+            if (ACTION_CANCEL_BROADCAST.equals(action)) {
+                Log_OC.d(TAG, "Cancel broadcast received for file " + remotePath + " at " + System.currentTimeMillis());
+
+                if (accountName == null || remotePath == null) return;
+
+                FileUploaderBinder uploadBinder = (FileUploaderBinder) mBinder;
+                uploadBinder.cancel(accountName, remotePath, null);
+            }else if(ACTION_PAUSE_BROADCAST.equals(action)){
+
+            } else {
+                Log_OC.d(TAG, "Unknown action to perform as UploadNotificationActionReceiver.");
+            }
+        }
+    }
 }

+ 11 - 7
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -350,14 +350,18 @@ public class FileDisplayActivity extends FileActivity
     public void onConfigurationChanged(@NonNull Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        StoragePermissionDialogFragment fragment = (StoragePermissionDialogFragment) getSupportFragmentManager().findFragmentByTag(PERMISSION_CHOICE_DIALOG_TAG);
-        if (fragment != null) {
-            Dialog dialog = fragment.getDialog();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            StoragePermissionDialogFragment fragment =
+                (StoragePermissionDialogFragment) getSupportFragmentManager()
+                    .findFragmentByTag(PERMISSION_CHOICE_DIALOG_TAG);
+            if (fragment != null) {
+                Dialog dialog = fragment.getDialog();
 
-            if (dialog != null && dialog.isShowing()) {
-                dialog.dismiss();
-                getSupportFragmentManager().beginTransaction().remove(fragment).commitNowAllowingStateLoss();
-                PermissionUtil.requestExternalStoragePermission(this, viewThemeUtils);
+                if (dialog != null && dialog.isShowing()) {
+                    dialog.dismiss();
+                    getSupportFragmentManager().beginTransaction().remove(fragment).commitNowAllowingStateLoss();
+                    PermissionUtil.requestExternalStoragePermission(this, viewThemeUtils);
+                }
             }
         }
     }

+ 89 - 70
app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

@@ -41,10 +41,21 @@ import android.os.Looper;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.text.format.DateFormat;
-import android.view.*;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
-import android.widget.*;
+import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
 
 import com.google.android.material.button.MaterialButton;
 import com.nextcloud.client.account.User;
@@ -66,13 +77,21 @@ import com.owncloud.android.operations.CreateFolderOperation;
 import com.owncloud.android.operations.RefreshFolderOperation;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.syncadapter.FileSyncAdapter;
-import com.owncloud.android.ui.adapter.UploaderAdapter;
+import com.owncloud.android.ui.adapter.ReceiveExternalFilesAdapter;
 import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
-import com.owncloud.android.ui.dialog.*;
+import com.owncloud.android.ui.dialog.AccountChooserInterface;
+import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
+import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
+import com.owncloud.android.ui.dialog.MultipleAccountsDialog;
+import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
 import com.owncloud.android.ui.fragment.TaskRetainerFragment;
 import com.owncloud.android.ui.helpers.FileOperationsHelper;
 import com.owncloud.android.ui.helpers.UriUploader;
-import com.owncloud.android.utils.*;
+import com.owncloud.android.utils.DataHolderUtil;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.ErrorMessageAdapter;
+import com.owncloud.android.utils.FileSortOrder;
+import com.owncloud.android.utils.MimeType;
 import com.owncloud.android.utils.theme.ViewThemeUtils;
 
 import java.io.File;
@@ -80,7 +99,12 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.nio.charset.Charset;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
 
 import javax.inject.Inject;
 
@@ -96,6 +120,7 @@ import androidx.core.view.MenuItemCompat;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
 
 import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
 
@@ -103,8 +128,8 @@ import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFrag
  * This can be used to upload things to an ownCloud instance.
  */
 public class ReceiveExternalFilesActivity extends FileActivity
-    implements OnItemClickListener, View.OnClickListener, CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener,
-    SortingOrderDialogFragment.OnSortingOrderListener, Injectable, AccountChooserInterface {
+    implements View.OnClickListener, CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener,
+    SortingOrderDialogFragment.OnSortingOrderListener, Injectable, AccountChooserInterface, ReceiveExternalFilesAdapter.OnItemClickListener {
 
     private static final String TAG = ReceiveExternalFilesActivity.class.getSimpleName();
 
@@ -125,6 +150,7 @@ public class ReceiveExternalFilesActivity extends FileActivity
     private OCFile mFile;
 
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
+    private ReceiveExternalFilesAdapter receiveExternalFilesAdapter;
     private boolean mSyncInProgress;
 
     private final static int REQUEST_CODE__SETUP_ACCOUNT = REQUEST_CODE__LAST_SHARED + 1;
@@ -273,6 +299,22 @@ public class ReceiveExternalFilesActivity extends FileActivity
         populateDirectoryList();
     }
 
+    @Override
+    public void selectFile(OCFile file) {
+        if (file.isFolder()) {
+            if (file.isEncrypted() &&
+                !FileOperationsHelper.isEndToEndEncryptionSetup(this, getUser().orElseThrow(IllegalAccessError::new))) {
+                DisplayUtils.showSnackMessage(this, R.string.e2e_not_yet_setup);
+
+                return;
+            }
+
+            startSyncFolderOperation(file);
+            mParents.push(file.getFileName());
+            populateDirectoryList();
+        }
+    }
+
     public static class DialogNoAccount extends DialogFragment {
         @NonNull
         @Override
@@ -611,39 +653,6 @@ public class ReceiveExternalFilesActivity extends FileActivity
         }
     }
 
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        // click on folder in the list
-        Log_OC.d(TAG, "on item click");
-        List<OCFile> tmpFiles = getStorageManager().getFolderContent(mFile, false);
-        tmpFiles = sortFileList(tmpFiles);
-
-        if (tmpFiles.isEmpty()) {
-            return;
-        }
-        // filter on dirtype
-        Vector<OCFile> files = new Vector<>();
-        files.addAll(tmpFiles);
-
-        if (files.size() < position) {
-            throw new IndexOutOfBoundsException("Incorrect item selected");
-        }
-        OCFile ocFile = files.get(position);
-        if (ocFile.isFolder()) {
-            if (ocFile.isEncrypted() &&
-                !FileOperationsHelper.isEndToEndEncryptionSetup(this, getUser().orElseThrow(IllegalAccessError::new))) {
-                DisplayUtils.showSnackMessage(this, R.string.e2e_not_yet_setup);
-
-                return;
-            }
-
-            OCFile folderToEnter = files.get(position);
-            startSyncFolderOperation(folderToEnter);
-            mParents.push(folderToEnter.getFileName());
-            populateDirectoryList();
-        }
-    }
-
     @Override
     public void onClick(View v) {
         // click on button
@@ -740,29 +749,10 @@ public class ReceiveExternalFilesActivity extends FileActivity
                 binding.list.setVisibility(View.GONE);
             } else {
                 mEmptyListContainer.setVisibility(View.GONE);
-
                 files = sortFileList(files);
-
-                List<Map<String, Object>> data = new LinkedList<>();
-                for (OCFile f : files) {
-                    Map<String, Object> h = new HashMap<>();
-                    h.put("dirname", f);
-                    data.add(h);
-                }
-
-                UploaderAdapter sa = new UploaderAdapter(this,
-                                                         data,
-                                                         R.layout.uploader_list_item_layout,
-                                                         new String[]{"dirname"},
-                                                         new int[]{R.id.filename},
-                                                         getStorageManager(),
-                                                         getUser().get(),
-                                                         syncedFolderProvider,
-                                                         viewThemeUtils);
-
-                binding.list.setAdapter(sa);
-                binding.list.setVisibility(View.VISIBLE);
+                setupReceiveExternalFilesAdapter(files);
             }
+
             MaterialButton btnChooseFolder = binding.uploaderChooseFolder;
             viewThemeUtils.material.colorMaterialButtonPrimaryFilled(btnChooseFolder);
             btnChooseFolder.setOnClickListener(this);
@@ -774,8 +764,6 @@ public class ReceiveExternalFilesActivity extends FileActivity
             viewThemeUtils.material.colorMaterialButtonPrimaryOutlined(binding.uploaderCancel);
             binding.uploaderCancel.setOnClickListener(this);
 
-            binding.list.setOnItemClickListener(this);
-
             sortButton = binding.toolbarLayout.sortButton;
             FileSortOrder sortOrder = preferences.getSortOrderByFolder(mFile);
             sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder));
@@ -783,6 +771,21 @@ public class ReceiveExternalFilesActivity extends FileActivity
         }
     }
 
+    private void setupReceiveExternalFilesAdapter(List<OCFile> files) {
+        receiveExternalFilesAdapter = new ReceiveExternalFilesAdapter(files,
+                                                                      this,
+                                                                      getUser().get(),
+                                                                      getStorageManager(),
+                                                                      viewThemeUtils,
+                                                                      syncedFolderProvider,
+                                                                      this);
+
+
+        binding.list.setLayoutManager(new LinearLayoutManager(this));
+        binding.list.setAdapter(receiveExternalFilesAdapter);
+        binding.list.setVisibility(View.VISIBLE);
+    }
+
     protected void setupEmptyList() {
         mEmptyListContainer = binding.emptyView.emptyListView;
         mEmptyListMessage = binding.emptyView.emptyListViewText;
@@ -1016,19 +1019,35 @@ public class ReceiveExternalFilesActivity extends FileActivity
             menu.findItem(R.id.action_create_dir).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         }
 
-        // tint search event
-        final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
-        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
+        setupSearchView(menu);
 
         MenuItem newFolderMenuItem = menu.findItem(R.id.action_create_dir);
         newFolderMenuItem.setEnabled(mFile.canWrite());
 
-        // hacky as no default way is provided
-        viewThemeUtils.androidx.themeToolbarSearchView(searchView);
-
         return true;
     }
 
+    private void setupSearchView(Menu menu) {
+        final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
+
+        SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
+        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                receiveExternalFilesAdapter.filter(query);
+                return false;
+            }
+
+            @Override
+            public boolean onQueryTextChange(String newText) {
+                receiveExternalFilesAdapter.filter(newText);
+                return false;
+            }
+        });
+
+        viewThemeUtils.androidx.themeToolbarSearchView(searchView);
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         boolean retval = true;

+ 176 - 0
app/src/main/java/com/owncloud/android/ui/adapter/ReceiveExternalFilesAdapter.kt

@@ -0,0 +1,176 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alper Ozturk
+ * Copyright (C) 2023 Alper Ozturk
+ * Copyright (C) 2023 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.owncloud.android.ui.adapter
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.recyclerview.widget.RecyclerView
+import com.nextcloud.client.account.User
+import com.owncloud.android.databinding.UploaderListItemLayoutBinding
+import com.owncloud.android.datamodel.FileDataStorageManager
+import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.datamodel.SyncedFolderProvider
+import com.owncloud.android.datamodel.ThumbnailsCacheManager
+import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncThumbnailDrawable
+import com.owncloud.android.datamodel.ThumbnailsCacheManager.ThumbnailGenerationTask
+import com.owncloud.android.datamodel.ThumbnailsCacheManager.ThumbnailGenerationTaskObject
+import com.owncloud.android.utils.DisplayUtils
+import com.owncloud.android.utils.MimeTypeUtil
+import com.owncloud.android.utils.theme.ViewThemeUtils
+
+@Suppress("LongParameterList")
+class ReceiveExternalFilesAdapter(
+    private val files: List<OCFile>,
+    private val context: Context,
+    private val user: User,
+    private val storageManager: FileDataStorageManager,
+    private val viewThemeUtils: ViewThemeUtils,
+    private val syncedFolderProvider: SyncedFolderProvider,
+    private val onItemClickListener: OnItemClickListener
+) : RecyclerView.Adapter<ReceiveExternalFilesAdapter.ReceiveExternalViewHolder>() {
+
+    private var filteredFiles: List<OCFile> = files
+
+    interface OnItemClickListener {
+        fun selectFile(file: OCFile)
+    }
+
+    inner class ReceiveExternalViewHolder(val binding: UploaderListItemLayoutBinding) :
+        RecyclerView.ViewHolder(binding.root) {
+        init {
+            binding.root.setOnClickListener {
+                val position = bindingAdapterPosition
+                if (position != RecyclerView.NO_POSITION) {
+                    onItemClickListener.selectFile(filteredFiles[position])
+                }
+            }
+        }
+    }
+
+    @SuppressLint("NotifyDataSetChanged")
+    fun filter(query: String) {
+        filteredFiles = if (query.isEmpty()) {
+            files
+        } else {
+            files.filter { file ->
+                file.fileName.contains(query, ignoreCase = true)
+            }
+        }
+        notifyDataSetChanged()
+    }
+
+    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ReceiveExternalViewHolder {
+        val binding = UploaderListItemLayoutBinding
+            .inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
+        return ReceiveExternalViewHolder(binding)
+    }
+
+    override fun onBindViewHolder(viewHolder: ReceiveExternalViewHolder, position: Int) {
+        val file = filteredFiles[position]
+
+        viewHolder.binding.filename.text = file.fileName
+        viewHolder.binding.lastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
+
+        if (!file.isFolder) {
+            viewHolder.binding.fileSize.text = DisplayUtils.bytesToHumanReadable(file.fileLength)
+        }
+
+        viewHolder.binding.fileSize.visibility = if (file.isFolder) {
+            View.GONE
+        } else {
+            View.VISIBLE
+        }
+        viewHolder.binding.fileSeparator.visibility = if (file.isFolder) {
+            View.GONE
+        } else {
+            View.VISIBLE
+        }
+
+        val thumbnailImageView = viewHolder.binding.thumbnail
+        setupThumbnail(thumbnailImageView, file)
+    }
+
+    private fun setupThumbnail(thumbnailImageView: ImageView, file: OCFile) {
+        thumbnailImageView.tag = file.fileId
+
+        if (file.isFolder) {
+            setupThumbnailForFolder(thumbnailImageView, file)
+        } else if (MimeTypeUtil.isImage(file) && file.remoteId != null) {
+            setupThumbnailForImage(thumbnailImageView, file)
+        } else {
+            setupDefaultThumbnail(thumbnailImageView, file)
+        }
+    }
+
+    private fun setupThumbnailForFolder(thumbnailImageView: ImageView, file: OCFile) {
+        val isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user)
+        val isDarkModeActive = syncedFolderProvider.preferences.isDarkModeEnabled
+        val overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder)
+        val icon = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, context, viewThemeUtils)
+        thumbnailImageView.setImageDrawable(icon)
+    }
+
+    @Suppress("NestedBlockDepth")
+    private fun setupThumbnailForImage(thumbnailImageView: ImageView, file: OCFile) {
+        var thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId.toString())
+        if (thumbnail != null && !file.isUpdateThumbnailNeeded) {
+            thumbnailImageView.setImageBitmap(thumbnail)
+        } else {
+            // generate new Thumbnail
+            if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailImageView)) {
+                val task = ThumbnailGenerationTask(thumbnailImageView, storageManager, user)
+                if (thumbnail == null) {
+                    thumbnail = if (MimeTypeUtil.isVideo(file)) {
+                        ThumbnailsCacheManager.mDefaultVideo
+                    } else {
+                        ThumbnailsCacheManager.mDefaultImg
+                    }
+                }
+                val asyncDrawable = AsyncThumbnailDrawable(
+                    context.resources,
+                    thumbnail,
+                    task
+                )
+                thumbnailImageView.setImageDrawable(asyncDrawable)
+
+                @Suppress("DEPRECATION")
+                task.execute(ThumbnailGenerationTaskObject(file, file.remoteId))
+            }
+        }
+    }
+
+    private fun setupDefaultThumbnail(thumbnailImageView: ImageView, file: OCFile) {
+        val icon = MimeTypeUtil.getFileTypeIcon(
+            file.mimeType,
+            file.fileName,
+            context,
+            viewThemeUtils
+        )
+        thumbnailImageView.setImageDrawable(icon)
+    }
+
+    override fun getItemCount() = filteredFiles.size
+}

+ 0 - 156
app/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java

@@ -1,156 +0,0 @@
-/*
- *   ownCloud Android client application
- *
- *   @author Tobias Kaminsky
- *   Copyright (C) 2016 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   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 <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.ui.adapter;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.SimpleAdapter;
-import android.widget.TextView;
-
-import com.nextcloud.client.account.User;
-import com.nextcloud.client.preferences.DarkMode;
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.SyncedFolderProvider;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncThumbnailDrawable;
-import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.MimeTypeUtil;
-import com.owncloud.android.utils.theme.ViewThemeUtils;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class UploaderAdapter extends SimpleAdapter {
-
-    private final Context mContext;
-    private final User user;
-    private final FileDataStorageManager mStorageManager;
-    private final LayoutInflater inflater;
-    private final ViewThemeUtils viewThemeUtils;
-    private SyncedFolderProvider syncedFolderProvider;
-
-    public UploaderAdapter(Context context,
-                           List<? extends Map<String, ?>> data,
-                           int resource,
-                           String[] from,
-                           int[] to,
-                           FileDataStorageManager storageManager,
-                           User user,
-                           SyncedFolderProvider syncedFolderProvider,
-                           ViewThemeUtils viewThemeUtils) {
-        super(context, data, resource, from, to);
-        this.user = user;
-        mStorageManager = storageManager;
-        mContext = context;
-        this.syncedFolderProvider = syncedFolderProvider;
-        inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        this.viewThemeUtils = viewThemeUtils;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        View vi = convertView;
-        if (convertView == null) {
-            vi = inflater.inflate(R.layout.uploader_list_item_layout, parent, false);
-        }
-
-        HashMap<String, OCFile> data = (HashMap<String, OCFile>) getItem(position);
-        OCFile file = data.get("dirname");
-
-        TextView filename = vi.findViewById(R.id.filename);
-        filename.setText(file.getFileName());
-
-        ImageView fileIcon = vi.findViewById(R.id.thumbnail);
-        fileIcon.setTag(file.getFileId());
-
-        TextView lastModV = vi.findViewById(R.id.last_mod);
-        lastModV.setText(DisplayUtils.getRelativeTimestamp(mContext, file.getModificationTimestamp()));
-
-        TextView fileSizeV = vi.findViewById(R.id.file_size);
-        TextView fileSizeSeparatorV = vi.findViewById(R.id.file_separator);
-
-        if(!file.isFolder()) {
-            fileSizeV.setVisibility(View.VISIBLE);
-            fileSizeSeparatorV.setVisibility(View.VISIBLE);
-            fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
-        } else {
-            fileSizeV.setVisibility(View.GONE);
-            fileSizeSeparatorV.setVisibility(View.GONE);
-        }
-
-        if (file.isFolder()) {
-            boolean isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user);
-            boolean isDarkModeActive = syncedFolderProvider.getPreferences().isDarkModeEnabled();
-
-            Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder);
-            final LayerDrawable icon = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, mContext, viewThemeUtils);
-            fileIcon.setImageDrawable(icon);
-        } else {
-            // get Thumbnail if file is image
-            if (MimeTypeUtil.isImage(file) && file.getRemoteId() != null) {
-                // Thumbnail in Cache?
-                Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
-                        String.valueOf(file.getRemoteId())
-                );
-                if (thumbnail != null && !file.isUpdateThumbnailNeeded()) {
-                    fileIcon.setImageBitmap(thumbnail);
-                } else {
-                    // generate new Thumbnail
-                    if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
-                        final ThumbnailsCacheManager.ThumbnailGenerationTask task =
-                                new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, mStorageManager, user);
-                        if (thumbnail == null) {
-                            if (MimeTypeUtil.isVideo(file)) {
-                                thumbnail = ThumbnailsCacheManager.mDefaultVideo;
-                            } else {
-                                thumbnail = ThumbnailsCacheManager.mDefaultImg;
-                            }
-                        }
-                        final AsyncThumbnailDrawable asyncDrawable = new AsyncThumbnailDrawable(
-                                mContext.getResources(),
-                                thumbnail,
-                                task
-                        );
-                        fileIcon.setImageDrawable(asyncDrawable);
-                        task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
-                    }
-                }
-            } else {
-                final Drawable icon = MimeTypeUtil.getFileTypeIcon(file.getMimeType(),
-                                                                   file.getFileName(),
-                                                                   mContext,
-                                                                   viewThemeUtils);
-                fileIcon.setImageDrawable(icon);
-            }
-        }
-
-        return vi;
-    }
-}

+ 2 - 6
app/src/main/java/com/owncloud/android/ui/events/AccountRemovedEvent.java → app/src/main/java/com/owncloud/android/ui/events/AccountRemovedEvent.kt

@@ -18,13 +18,9 @@
  * 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.ui.events;
+package com.owncloud.android.ui.events
 
 /**
  * Event that notifies that an account was removed
  */
-
-public class AccountRemovedEvent {
-
-}
+class AccountRemovedEvent

+ 3 - 4
app/src/main/java/com/owncloud/android/ui/events/ChangeMenuEvent.java → app/src/main/java/com/owncloud/android/ui/events/ChangeMenuEvent.kt

@@ -15,12 +15,11 @@
  * 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/>.
+ * along with this program.  If not, see <http:></http:>//www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.events;
+package com.owncloud.android.ui.events
 
 /**
  * Currently a dummy event to restore grid view, sort, and search
  */
-public class ChangeMenuEvent {
-}
+class ChangeMenuEvent

+ 2 - 9
app/src/main/java/com/owncloud/android/ui/events/CommentsEvent.java → app/src/main/java/com/owncloud/android/ui/events/CommentsEvent.kt

@@ -18,16 +18,9 @@
  * 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.events;
+package com.owncloud.android.ui.events
 
 /**
  * Event for refreshing comment state of a file
  */
-public class CommentsEvent {
-    public final String remoteId;
-
-    public CommentsEvent(String remoteId) {
-        this.remoteId = remoteId;
-    }
-}
+class CommentsEvent(val remoteId: String)

+ 3 - 4
app/src/main/java/com/owncloud/android/ui/events/DummyDrawerEvent.java → app/src/main/java/com/owncloud/android/ui/events/DummyDrawerEvent.kt

@@ -15,12 +15,11 @@
  * 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/>.
+ * along with this program.  If not, see <http:></http:>//www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.events;
+package com.owncloud.android.ui.events
 
 /**
  * Dummy drawer event
  */
-public class DummyDrawerEvent {
-}
+class DummyDrawerEvent

+ 0 - 37
app/src/main/java/com/owncloud/android/ui/events/EncryptionEvent.java

@@ -1,37 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * Copyright (C) 2017 Tobias Kaminsky
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.events;
-
-/**
- * Event for set folder as encrypted/decrypted
- */
-public class EncryptionEvent {
-    public final long localId;
-    public final String remotePath;
-    public final String remoteId;
-    public final boolean shouldBeEncrypted;
-
-    public EncryptionEvent(long localId, String remoteId, String remotePath, boolean shouldBeEncrypted) {
-        this.localId = localId;
-        this.remoteId = remoteId;
-        this.remotePath = remotePath;
-        this.shouldBeEncrypted = shouldBeEncrypted;
-    }
-}

+ 30 - 0
app/src/main/java/com/owncloud/android/ui/events/EncryptionEvent.kt

@@ -0,0 +1,30 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2017 Tobias Kaminsky
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.events
+
+/**
+ * Event for set folder as encrypted/decrypted
+ */
+class EncryptionEvent(
+    val localId: Long,
+    val remoteId: String,
+    val remotePath: String,
+    val shouldBeEncrypted: Boolean
+)

+ 0 - 33
app/src/main/java/com/owncloud/android/ui/events/FavoriteEvent.java

@@ -1,33 +0,0 @@
-/**
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.events;
-
-/**
- * Event for making favoriting work
- */
-public class FavoriteEvent {
-    public final String remotePath;
-    public final boolean shouldFavorite;
-
-    public FavoriteEvent(String remotePath, boolean shouldFavorite) {
-        this.remotePath = remotePath;
-        this.shouldFavorite = shouldFavorite;
-    }
-}

+ 6 - 9
app/src/main/java/com/owncloud/android/ui/events/VCardToggleEvent.java → app/src/main/java/com/owncloud/android/ui/events/FavoriteEvent.kt

@@ -15,14 +15,11 @@
  * 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/>.
+ * along with this program.  If not, see <http:></http:>//www.gnu.org/licenses/>.
  */
-package com.owncloud.android.ui.events;
+package com.owncloud.android.ui.events
 
-public class VCardToggleEvent {
-    public boolean showRestoreButton;
-
-    public VCardToggleEvent(boolean showRestore) {
-        this.showRestoreButton = showRestore;
-    }
-}
+/**
+ * Event for making favoriting work
+ */
+class FavoriteEvent(val remotePath: String, val shouldFavorite: Boolean)

+ 0 - 35
app/src/main/java/com/owncloud/android/ui/events/InitiateSyncedFolder.java

@@ -1,35 +0,0 @@
-/**
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.events;
-
-import com.owncloud.android.datamodel.SyncedFolder;
-
-public class InitiateSyncedFolder {
-    private final SyncedFolder syncedFolder;
-
-
-    public InitiateSyncedFolder(SyncedFolder syncedFolder) {
-        this.syncedFolder = syncedFolder;
-    }
-
-    public SyncedFolder getSyncedFolder() {
-        return syncedFolder;
-    }
-}

+ 0 - 33
app/src/main/java/com/owncloud/android/ui/events/MenuItemClickEvent.java

@@ -1,33 +0,0 @@
-/**
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.ui.events;
-
-import android.view.MenuItem;
-
-/**
- * Menu item click event
- */
-public class MenuItemClickEvent {
-    public final MenuItem menuItem;
-
-    public MenuItemClickEvent(MenuItem menuItem) {
-        this.menuItem = menuItem;
-    }
-}

+ 2 - 3
app/src/main/java/com/owncloud/android/ui/events/TokenPushEvent.java → app/src/main/java/com/owncloud/android/ui/events/TokenPushEvent.kt

@@ -17,10 +17,9 @@
  * 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.ui.events;
+package com.owncloud.android.ui.events
 
 /**
  * Event to send push token where it belongs
  */
-public class TokenPushEvent {
-}
+class TokenPushEvent 

+ 22 - 0
app/src/main/java/com/owncloud/android/ui/events/VCardToggleEvent.kt

@@ -0,0 +1,22 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic
+ *
+ * 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 <http:></http:>//www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.events
+
+class VCardToggleEvent(var showRestoreButton: Boolean)

+ 4 - 4
app/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -783,13 +783,13 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
             OwnCloudClient client = clientFactory.create(user);
 
             ToggleFavoriteRemoteOperation toggleFavoriteOperation = new ToggleFavoriteRemoteOperation(
-                event.shouldFavorite, event.remotePath);
+                event.getShouldFavorite(), event.getRemotePath());
             RemoteOperationResult remoteOperationResult = toggleFavoriteOperation.execute(client);
 
             if (remoteOperationResult.isSuccess()) {
-                getFile().setFavorite(event.shouldFavorite);
-                OCFile file = storageManager.getFileByEncryptedRemotePath(event.remotePath);
-                file.setFavorite(event.shouldFavorite);
+                getFile().setFavorite(event.getShouldFavorite());
+                OCFile file = storageManager.getFileByEncryptedRemotePath(event.getRemotePath());
+                file.setFavorite(event.getShouldFavorite());
                 storageManager.saveFile(file);
             }
 

+ 9 - 9
app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -1588,7 +1588,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
 
     @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onMessageEvent(CommentsEvent event) {
-        mAdapter.refreshCommentsCount(event.remoteId);
+        mAdapter.refreshCommentsCount(event.getRemoteId());
     }
 
     @Subscribe(threadMode = ThreadMode.BACKGROUND)
@@ -1598,13 +1598,13 @@ public class OCFileListFragment extends ExtendedListFragment implements
             OwnCloudClient client = clientFactory.create(user);
 
             ToggleFavoriteRemoteOperation toggleFavoriteOperation = new ToggleFavoriteRemoteOperation(
-                event.shouldFavorite, event.remotePath);
+                event.getShouldFavorite(), event.getRemotePath());
             RemoteOperationResult remoteOperationResult = toggleFavoriteOperation.execute(client);
 
             if (remoteOperationResult.isSuccess()) {
-                boolean removeFromList = currentSearchType == SearchType.FAVORITE_SEARCH && !event.shouldFavorite;
+                boolean removeFromList = currentSearchType == SearchType.FAVORITE_SEARCH && !event.getShouldFavorite();
                 setEmptyListMessage(SearchType.FAVORITE_SEARCH);
-                mAdapter.setFavoriteAttributeForItemID(event.remotePath, event.shouldFavorite, removeFromList);
+                mAdapter.setFavoriteAttributeForItemID(event.getRemotePath(), event.getShouldFavorite(), removeFromList);
             }
 
         } catch (ClientFactory.CreationException e) {
@@ -1692,7 +1692,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         String privateKey = arbitraryDataProvider.getValue(user, EncryptionUtils.PRIVATE_KEY);
 
         FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-        OCFile file = storageManager.getFileByRemoteId(event.remoteId);
+        OCFile file = storageManager.getFileByRemoteId(event.getRemoteId());
 
         if (publicKey.isEmpty() || privateKey.isEmpty()) {
             Log_OC.d(TAG, "no public key for " + user.getAccountName());
@@ -1706,10 +1706,10 @@ public class OCFileListFragment extends ExtendedListFragment implements
             dialog.show(getParentFragmentManager(), SETUP_ENCRYPTION_DIALOG_TAG);
         } else {
             encryptFolder(file,
-                          event.localId,
-                          event.remoteId,
-                          event.remotePath,
-                          event.shouldBeEncrypted,
+                          event.getLocalId(),
+                          event.getRemoteId(),
+                          event.getRemotePath(),
+                          event.getShouldBeEncrypted(),
                           publicKey,
                           privateKey);
         }

+ 1 - 1
app/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/BackupListFragment.java

@@ -270,7 +270,7 @@ public class BackupListFragment extends FileFragment implements Injectable {
 
     @Subscribe(threadMode = ThreadMode.MAIN)
     public void onMessageEvent(VCardToggleEvent event) {
-        if (event.showRestoreButton) {
+        if (event.getShowRestoreButton()) {
             binding.contactlistRestoreSelectedContainer.setVisibility(View.VISIBLE);
         } else {
             binding.contactlistRestoreSelectedContainer.setVisibility(View.GONE);

+ 2 - 0
app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -436,6 +436,8 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
             seeDetails();
         } else if (itemId == R.id.action_download_file || itemId == R.id.action_sync_file) {
             containerActivity.getFileOperationsHelper().syncFile(getFile());
+        }else if(itemId == R.id.action_cancel_sync){
+            containerActivity.getFileOperationsHelper().cancelTransference(getFile());
         } else if (itemId == R.id.action_set_as_wallpaper) {
             containerActivity.getFileOperationsHelper().setPictureAs(getFile(), getImageView());
         } else if (itemId == R.id.action_export_file) {

+ 2 - 0
app/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -482,6 +482,8 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
             seeDetails();
         } else if (itemId == R.id.action_sync_file) {
             containerActivity.getFileOperationsHelper().syncFile(getFile());
+        } else if (itemId == R.id.action_cancel_sync) {
+            containerActivity.getFileOperationsHelper().cancelTransference(getFile());
         } else if (itemId == R.id.action_stream_media) {
             containerActivity.getFileOperationsHelper().streamMediaFile(getFile());
         } else if (itemId == R.id.action_export_file) {

+ 2 - 0
app/src/main/java/com/owncloud/android/ui/preview/PreviewTextFileFragment.java

@@ -330,6 +330,8 @@ public class PreviewTextFileFragment extends PreviewTextFragment {
             seeDetails();
         } else if (itemId == R.id.action_sync_file) {
             containerActivity.getFileOperationsHelper().syncFile(getFile());
+        } else if(itemId == R.id.action_cancel_sync){
+            containerActivity.getFileOperationsHelper().cancelTransference(getFile());
         } else if (itemId == R.id.action_edit) {
             containerActivity.getFileOperationsHelper().openFileWithTextEditor(getFile(), getContext());
         }

+ 2 - 1
app/src/main/res/layout/receive_external_files.xml

@@ -34,10 +34,11 @@
         android:layout_height="0dp"
         android:layout_weight="1">
 
-        <ListView
+        <androidx.recyclerview.widget.RecyclerView
             android:id="@android:id/list"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:orientation="vertical"
             android:background="@color/bg_default"
             android:divider="@color/transparent"
             android:dividerHeight="0dip"

+ 1 - 0
app/src/main/res/values-ar/strings.xml

@@ -891,6 +891,7 @@
     <string name="upload_lock_failed">فشل قفّل المجلد</string>
     <string name="upload_old_android">التشفير ممكن فقط مع &gt;= Android 5.0</string>
     <string name="upload_query_move_foreign_files">يمنع وجود مساحة غير كافية نسخ الملفات المحددة إلى المجلد %1$s. هل ترغب في نقلهم إلى هناك بدلاً من ذلك؟</string>
+    <string name="upload_quota_exceeded">الحصة التخزينية تمّ استنفاذها</string>
     <string name="upload_scan_doc_upload">مسح مستند عبر الكاميرا</string>
     <string name="upload_sync_conflict">تعارض المزامنة ، يرجى حلها يدويًا</string>
     <string name="upload_unknown_error">خطأ غير معروف</string>

+ 1 - 0
app/src/main/res/values-cs-rCZ/strings.xml

@@ -884,6 +884,7 @@
     <string name="upload_lock_failed">Uzamčení složky se nezdařilo</string>
     <string name="upload_old_android">Šifrování je možné pouze na systému Android verze 5.0 a novějším</string>
     <string name="upload_query_move_foreign_files">Pro zkopírování vybraných souborů do složky %1$s není dostatek volného místa. Chcete je tam namísto toho přesunout?</string>
+    <string name="upload_quota_exceeded">Kvóta úložiště překročena</string>
     <string name="upload_scan_doc_upload">Naskenovat dokument kamerou</string>
     <string name="upload_sync_conflict">Konflikt synchronizace – vyřešte ručně</string>
     <string name="upload_unknown_error">Neznámá chyba</string>

+ 1 - 0
app/src/main/res/values-de/strings.xml

@@ -885,6 +885,7 @@
     <string name="upload_lock_failed">Fehler beim Sperren des Ordners</string>
     <string name="upload_old_android">Verschlüsselung ist nur möglich mit &gt;= Android 5.0</string>
     <string name="upload_query_move_foreign_files">Es steht nicht genügend Speicherplatz zur Verfügung, um die ausgewählten Dateien in das Verzeichnis %1$s zu kopieren. Sollen diese stattdessen verschoben werden?</string>
+    <string name="upload_quota_exceeded">Speicherkontingent überschritten</string>
     <string name="upload_scan_doc_upload">Dokument von der Kamera scannen</string>
     <string name="upload_sync_conflict">Synchronisierungskonflikt, bitte manuell beheben</string>
     <string name="upload_unknown_error">Unbekannter Fehler</string>

+ 1 - 0
app/src/main/res/values-gl/strings.xml

@@ -885,6 +885,7 @@
     <string name="upload_lock_failed">Produciuse un fallo ao bloquear o cartafol</string>
     <string name="upload_old_android">O cifrado só é posíbel con &gt;= Android 5.0</string>
     <string name="upload_query_move_foreign_files">Non hai espazo abondo para copiar os ficheiros seleccionados no cartafol %1$s. No canto diso, gustaríalle movelos?</string>
+    <string name="upload_quota_exceeded">Superouse a cota de almacenamento</string>
     <string name="upload_scan_doc_upload">Escanear o documento dende a cámara</string>
     <string name="upload_sync_conflict">Conflito ao sincronizar, resólvao manualmente</string>
     <string name="upload_unknown_error">Produciuse un erro descoñecido</string>

+ 1 - 0
app/src/main/res/values-sr/strings.xml

@@ -884,6 +884,7 @@
     <string name="upload_lock_failed">Неуспело закључавање фасцикле</string>
     <string name="upload_old_android">Шифровање је могуће само са &gt;= Андроидом 5.0</string>
     <string name="upload_query_move_foreign_files">Недостатак простора  спречава копирање фајлова у фасциклу %1$s. Желите ли да их преместите тамо?</string>
+    <string name="upload_quota_exceeded">Прекорачена је квота за складиште</string>
     <string name="upload_scan_doc_upload">Скенирање документа камером</string>
     <string name="upload_sync_conflict">Сукоб синхронизације. Разрешите га ручно</string>
     <string name="upload_unknown_error">Непозната грешка</string>

+ 2 - 2
app/src/main/res/values-uk/strings.xml

@@ -731,7 +731,7 @@
     <string name="shared_icon_share">поділитися</string>
     <string name="shared_icon_shared">надано доступ</string>
     <string name="shared_icon_shared_via_link">доступ надано за посиланням</string>
-    <string name="shared_with_you_by">%1$s поділився з вами</string>
+    <string name="shared_with_you_by">%1$s поділив(-ла-)ся з вами</string>
     <string name="sharee_add_failed">Помилка додавання користувача, з яким ви хочете поділитися</string>
     <string name="show_images">Показувати зображення</string>
     <string name="show_video">Показувати відео</string>
@@ -793,7 +793,7 @@
     <string name="sub_folder_rule_month">Рік/місяць</string>
     <string name="sub_folder_rule_year">Рік</string>
     <string name="subject_shared_with_you">Вам було надано доступ до \"%1$s\"</string>
-    <string name="subject_user_shared_with_you">%1$s поділився %2$s з вами</string>
+    <string name="subject_user_shared_with_you">%1$s поділив(-ла-)ся %2$s з вами</string>
     <string name="subtitle_photos_only">Лише зображення</string>
     <string name="subtitle_photos_videos">Зображення та відео</string>
     <string name="subtitle_videos_only">Лише відео</string>

+ 1 - 0
app/src/main/res/values-zh-rCN/strings.xml

@@ -887,6 +887,7 @@
     <string name="upload_lock_failed">锁定文件夹失败</string>
     <string name="upload_old_android">加密功能仅适用于安卓 5.0 及以上版本</string>
     <string name="upload_query_move_foreign_files">空间不足将阻止将所选文件复制到%1$s文件夹中。 你想把它们移到那里吗?</string>
+    <string name="upload_quota_exceeded">超出存储限额</string>
     <string name="upload_scan_doc_upload">使用相机扫描文档</string>
     <string name="upload_sync_conflict">同步时发生异常,请手动同步</string>
     <string name="upload_unknown_error">未知错误</string>

+ 1 - 0
app/src/main/res/values-zh-rTW/strings.xml

@@ -884,6 +884,7 @@
     <string name="upload_lock_failed">鎖定資料夾失敗</string>
     <string name="upload_old_android">加密功能僅適用於 Android 5.0 及更新版本</string>
     <string name="upload_query_move_foreign_files">空間不足以將選擇的檔案複製到 %1$s 資料夾,是否要改成移動它們?</string>
+    <string name="upload_quota_exceeded">超過儲存空間配額</string>
     <string name="upload_scan_doc_upload">使用相機掃描文件</string>
     <string name="upload_sync_conflict">同步發生衝突,請手動處理</string>
     <string name="upload_unknown_error">未知的錯誤</string>

+ 1 - 1
build.gradle

@@ -1,6 +1,6 @@
 buildscript {
     ext {
-        androidPluginVersion = '8.1.4'
+        androidPluginVersion = '8.2.0'
         appCompatVersion = '1.6.1'
         jacoco_version = '0.8.10'
         kotlin_version = '1.8.22'

+ 0 - 1
gradle.properties

@@ -4,7 +4,6 @@ NC_TEST_SERVER_USERNAME=test
 NC_TEST_SERVER_PASSWORD=test
 android.enableJetifier=true
 android.useAndroidX=true
-android.defaults.buildfeatures.buildconfig=true
 android.nonTransitiveRClass=false
 android.nonFinalResIds=false
 #android.debug.obsoleteApi=true

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
 #Fri Jan 13 08:21:45 CET 2023
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME

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

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