瀏覽代碼

Merge pull request #12003 from nextcloud/bugfix/Update-folder-icons

Bugfix/update folder icons
Tobias Kaminsky 1 年之前
父節點
當前提交
c9f9b02cce
共有 50 個文件被更改,包括 640 次插入581 次删除
  1. 1 1
      .github/workflows/analysis.yml
  2. 二進制
      app/screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailDetailsFragment.png
  3. 二進制
      app/screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showFolderTypes.png
  4. 21 6
      app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt
  5. 13 0
      app/src/androidTest/java/com/owncloud/android/AbstractIT.java
  6. 8 2
      app/src/androidTest/java/com/owncloud/android/UploadIT.java
  7. 105 0
      app/src/androidTest/java/com/owncloud/android/datamodel/OCFileIconTests.kt
  8. 0 1
      app/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java
  9. 1 1
      app/src/androidTest/java/com/owncloud/android/ui/dialog/DialogFragmentIT.java
  10. 25 0
      app/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentStaticServerIT.kt
  11. 63 0
      app/src/androidTest/java/com/owncloud/android/utils/DrawableUtilTests.kt
  12. 2 2
      app/src/gplay/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt
  13. 1 0
      app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java
  14. 5 0
      app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java
  15. 6 10
      app/src/main/java/com/nextcloud/utils/ShortcutUtil.kt
  16. 1 1
      app/src/main/java/com/nextcloud/utils/extensions/Extensions.kt
  17. 19 12
      app/src/main/java/com/nmc/android/ui/LauncherActivity.kt
  18. 27 0
      app/src/main/java/com/owncloud/android/datamodel/OCFile.java
  19. 9 0
      app/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java
  20. 2 2
      app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
  21. 7 9
      app/src/main/java/com/owncloud/android/ui/activity/EditorWebView.java
  22. 7 9
      app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java
  23. 2 2
      app/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java
  24. 8 10
      app/src/main/java/com/owncloud/android/ui/adapter/GroupfolderListAdapter.kt
  25. 1 0
      app/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
  26. 2 2
      app/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java
  27. 7 9
      app/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java
  28. 9 9
      app/src/main/java/com/owncloud/android/utils/DisplayUtils.java
  29. 47 0
      app/src/main/java/com/owncloud/android/utils/DrawableUtil.kt
  30. 29 45
      app/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
  31. 0 29
      app/src/main/res/drawable/folder_auto_upload.xml
  32. 0 28
      app/src/main/res/drawable/folder_encrypted.xml
  33. 0 28
      app/src/main/res/drawable/folder_external.xml
  34. 0 28
      app/src/main/res/drawable/folder_group.xml
  35. 0 28
      app/src/main/res/drawable/folder_shared_link.xml
  36. 0 28
      app/src/main/res/drawable/folder_shared_users.xml
  37. 30 0
      app/src/main/res/drawable/ic_folder_overlay_account_group.xml
  38. 30 0
      app/src/main/res/drawable/ic_folder_overlay_external.xml
  39. 30 0
      app/src/main/res/drawable/ic_folder_overlay_key.xml
  40. 30 0
      app/src/main/res/drawable/ic_folder_overlay_link.xml
  41. 30 0
      app/src/main/res/drawable/ic_folder_overlay_lock.xml
  42. 30 0
      app/src/main/res/drawable/ic_folder_overlay_share.xml
  43. 30 0
      app/src/main/res/drawable/ic_folder_overlay_upload.xml
  44. 2 2
      app/src/test/java/com/nextcloud/android/utils/ExtensionsTest.kt
  45. 0 5
      drawable_resources/folder_auto_upload.svg
  46. 0 67
      drawable_resources/folder_encrypted.svg
  47. 0 5
      drawable_resources/folder_external.svg
  48. 0 67
      drawable_resources/folder_group.svg
  49. 0 67
      drawable_resources/folder_shared_link.svg
  50. 0 66
      drawable_resources/folder_shared_users.svg

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

@@ -17,7 +17,7 @@ concurrency:
 
 jobs:
     analysis:
-        runs-on: ubuntu-latest
+        runs-on: ubuntu-22.04
         steps:
             -   name: Setup variables
                 id: get-vars

二進制
app/screenshots/gplay/debug/com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT_showFileDetailDetailsFragment.png


二進制
app/screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT_showFolderTypes.png


+ 21 - 6
app/src/androidTest/java/com/nmc/android/ui/LauncherActivityIT.kt

@@ -23,9 +23,10 @@ package com.nmc.android.ui
 
 import androidx.test.espresso.Espresso.onView
 import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers
 import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
+import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
 import androidx.test.espresso.matcher.ViewMatchers.withId
-import androidx.test.espresso.matcher.ViewMatchers.withText
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.owncloud.android.AbstractIT
@@ -33,6 +34,7 @@ import com.owncloud.android.R
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.AdditionalMatchers.not
 
 @RunWith(AndroidJUnit4::class)
 class LauncherActivityIT : AbstractIT() {
@@ -41,13 +43,26 @@ class LauncherActivityIT : AbstractIT() {
     val activityRule = ActivityScenarioRule(LauncherActivity::class.java)
 
     @Test
-    fun verifyUIElements() {
+    fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
+        waitForIdleSync()
+
+        onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
+
+        onView(withId(R.id.splashScreenBold)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
+        onView(withId(R.id.splashScreenNormal)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
+    }
+
+    @Test
+    fun testSplashScreenWithTitlesShouldShowTitles() {
         waitForIdleSync()
         onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
-        onView(withId(R.id.splashScreenBold)).check(matches(isCompletelyDisplayed()))
-        onView(withId(R.id.splashScreenNormal)).check(matches(isCompletelyDisplayed()))
 
-        onView(withId(R.id.splashScreenBold)).check(matches(withText("Magenta")))
-        onView(withId(R.id.splashScreenNormal)).check(matches(withText("CLOUD")))
+        activityRule.scenario.onActivity {
+            it.setSplashTitles("Example", "Cloud")
+        }
+
+        val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
+        onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
+        onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
     }
 }

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

@@ -37,7 +37,9 @@ import com.owncloud.android.lib.common.OwnCloudClientFactory;
 import com.owncloud.android.lib.common.accounts.AccountUtils;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
+import com.owncloud.android.lib.resources.status.GetCapabilitiesRemoteOperation;
 import com.owncloud.android.lib.resources.status.OCCapability;
+import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.operations.CreateFolderOperation;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.utils.FileStorageUtils;
@@ -71,6 +73,7 @@ import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
 
 /**
@@ -187,6 +190,16 @@ public abstract class AbstractIT {
         }
     }
 
+    protected void testOnlyOnServer(OwnCloudVersion version) throws AccountUtils.AccountNotFoundException {
+        NextcloudClient client = OwnCloudClientFactory.createNextcloudClient(user, targetContext);
+
+        OCCapability ocCapability = (OCCapability) new GetCapabilitiesRemoteOperation()
+            .execute(client)
+            .getSingleData();
+
+        assumeTrue(ocCapability.getVersion().isNewerOrEqual(version));
+    }
+
     @Before
     public void enableAccessibilityChecks() {
         androidx.test.espresso.accessibility.AccessibilityChecks.enable().setRunChecksFromRootView(true);

+ 8 - 2
app/src/androidTest/java/com/owncloud/android/UploadIT.java

@@ -31,9 +31,11 @@ import com.owncloud.android.datamodel.UploadsStorageManager;
 import com.owncloud.android.db.OCUpload;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.NameCollisionPolicy;
+import com.owncloud.android.lib.common.accounts.AccountUtils;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.resources.files.model.GeoLocation;
 import com.owncloud.android.lib.resources.files.model.ImageDimension;
+import com.owncloud.android.lib.resources.status.NextcloudVersion;
 import com.owncloud.android.operations.RefreshFolderOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.UploadFileOperation;
@@ -424,7 +426,9 @@ public class UploadIT extends AbstractOnServerIT {
     }
 
     @Test
-    public void testCreationAndUploadTimestamp() throws IOException {
+    public void testCreationAndUploadTimestamp() throws IOException, AccountUtils.AccountNotFoundException {
+        testOnlyOnServer(NextcloudVersion.nextcloud_27);
+
         File file = getDummyFile("empty.txt");
         String remotePath = "/testFile.txt";
         OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);
@@ -476,7 +480,9 @@ public class UploadIT extends AbstractOnServerIT {
     }
 
     @Test
-    public void testMetadata() throws IOException {
+    public void testMetadata() throws IOException, AccountUtils.AccountNotFoundException {
+        testOnlyOnServer(NextcloudVersion.nextcloud_27);
+
         File file = getFile("gps.jpg");
         String remotePath = "/gps.jpg";
         OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);

+ 105 - 0
app/src/androidTest/java/com/owncloud/android/datamodel/OCFileIconTests.kt

@@ -0,0 +1,105 @@
+/*
+ * 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.datamodel
+
+import com.owncloud.android.R
+import com.owncloud.android.lib.common.network.WebdavEntry.MountType
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+
+class OCFileIconTests {
+
+    private val path = "/path/to/a/file.txt"
+    private var sut: OCFile? = null
+
+    @Before
+    fun setup() {
+        sut = OCFile(path)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsAutoUploadFolderShouldReturnFolderOverlayUploadIcon() {
+        val fileOverlayIcon = sut?.getFileOverlayIconId(true)
+        val expectedDrawable = R.drawable.ic_folder_overlay_upload
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsEncryptedShouldReturnFolderOverlayKeyIcon() {
+        sut?.isEncrypted = true
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_key
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsGroupFolderShouldReturnFolderOverlayAccountGroupIcon() {
+        sut?.mountType = MountType.GROUP
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_account_group
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsSharedViaLinkShouldReturnFolderOverlayLinkIcon() {
+        sut?.isSharedViaLink = true
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_link
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsSharedShouldReturnFolderOverlayShareIcon() {
+        sut?.isSharedWithSharee = true
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_share
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsExternalShouldReturnFolderOverlayExternalIcon() {
+        sut?.mountType = MountType.EXTERNAL
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_external
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsLockedShouldReturnFolderOverlayLockIcon() {
+        sut?.isLocked = true
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        val expectedDrawable = R.drawable.ic_folder_overlay_lock
+        assert(fileOverlayIcon == expectedDrawable)
+    }
+
+    @Test
+    fun testGetFileOverlayIconWhenFileIsFolderShouldReturnNull() {
+        val fileOverlayIcon = sut?.getFileOverlayIconId(false)
+        assert(fileOverlayIcon == null)
+    }
+
+    @After
+    fun destroy() {
+        sut = null
+    }
+}

+ 0 - 1
app/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java

@@ -70,7 +70,6 @@ public class OCFileUnitTest {
         mFile = new OCFile(PATH);
     }
 
-
     @Test
     public void writeThenReadAsParcelable() {
 

+ 1 - 1
app/src/androidTest/java/com/owncloud/android/ui/dialog/DialogFragmentIT.java

@@ -539,8 +539,8 @@ public class DialogFragmentIT extends AbstractIT {
 
         final SslCertificate certificate = new SslCertificate("foo", "bar", "2022/01/10", "2022/01/30");
         final SslError sslError = new SslError(SslError.SSL_UNTRUSTED, certificate);
-        final SslErrorHandler handler = Mockito.mock(SslErrorHandler.class);
 
+        final SslErrorHandler handler = Mockito.mock(SslErrorHandler.class);
 
         SslUntrustedCertDialog sut = SslUntrustedCertDialog.newInstanceForEmptySslError(sslError, handler);
         showDialog(sut);

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

@@ -242,6 +242,22 @@ class OCFileListFragmentStaticServerIT : AbstractIT() {
             sut.storageManager.saveFile(this)
         }
 
+        OCFile("/sharedViaLink/").apply {
+            mimeType = MimeType.DIRECTORY
+            isSharedViaLink = true
+            modificationTimestamp = 1619003571000
+            parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
+            sut.storageManager.saveFile(this)
+        }
+
+        OCFile("/share/").apply {
+            mimeType = MimeType.DIRECTORY
+            isSharedWithSharee = true
+            modificationTimestamp = 1619303571000
+            parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
+            sut.storageManager.saveFile(this)
+        }
+
         OCFile("/groupFolder/").apply {
             mimeType = MimeType.DIRECTORY
             modificationTimestamp = 1615003571000
@@ -259,6 +275,15 @@ class OCFileListFragmentStaticServerIT : AbstractIT() {
             sut.storageManager.saveFile(this)
         }
 
+        OCFile("/locked/").apply {
+            mimeType = MimeType.DIRECTORY
+            isLocked = true
+            decryptedRemotePath = "/locked/"
+            modificationTimestamp = 1613003571000
+            parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
+            sut.storageManager.saveFile(this)
+        }
+
         sut.addFragment(fragment)
 
         shortSleep()

+ 63 - 0
app/src/androidTest/java/com/owncloud/android/utils/DrawableUtilTests.kt

@@ -0,0 +1,63 @@
+/*
+ * 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.utils
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.After
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+
+class DrawableUtilTests {
+
+    private var sut: DrawableUtil? = null
+    private var context: Context? = null
+
+    @Before
+    fun setUp() {
+        sut = DrawableUtil()
+        context = InstrumentationRegistry.getInstrumentation().context
+    }
+
+    @Test
+    fun testAddDrawableAsOverlayWhenGivenValidDrawablesShouldContainTwoDrawable() {
+        val bitmap: Bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888)
+        val drawable = BitmapDrawable(context?.resources, bitmap)
+
+        val layerDrawable = sut?.addDrawableAsOverlay(drawable, drawable)
+
+        if (layerDrawable == null) {
+            fail("Layer drawable expected to be not null")
+        }
+
+        assert(layerDrawable?.numberOfLayers == 2)
+    }
+
+    @After
+    fun destroy() {
+        sut = null
+        context = null
+    }
+}

+ 2 - 2
app/src/gplay/java/com/nextcloud/android/appReview/InAppReviewHelperImpl.kt

@@ -29,8 +29,8 @@ import com.google.android.play.core.review.ReviewManagerFactory
 import com.nextcloud.appReview.AppReviewShownModel
 import com.nextcloud.appReview.InAppReviewHelper
 import com.nextcloud.client.preferences.AppPreferences
-import com.nextcloud.utils.getFormattedStringDate
-import com.nextcloud.utils.isCurrentYear
+import com.nextcloud.utils.extensions.getFormattedStringDate
+import com.nextcloud.utils.extensions.isCurrentYear
 import com.owncloud.android.lib.common.utils.Log_OC
 
 // Reference: https://developer.android.com/guide/playcore/in-app-review

+ 1 - 0
app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java

@@ -71,6 +71,7 @@ public interface AppPreferences {
 
     boolean instantPictureUploadEnabled();
     boolean instantVideoUploadEnabled();
+    boolean isDarkModeEnabled();
 
     boolean isShowHiddenFilesEnabled();
     void setShowHiddenFilesEnabled(boolean enabled);

+ 5 - 0
app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java

@@ -435,6 +435,11 @@ public final class AppPreferencesImpl implements AppPreferences {
         return preferences.getInt(AUTO_PREF__UPLOADER_BEHAVIOR, 1);
     }
 
+    @Override
+    public boolean isDarkModeEnabled() {
+        return getDarkThemeMode() == DarkMode.DARK;
+    }
+
     @Override
     public void setDarkThemeMode(DarkMode mode) {
         preferences.edit().putString(PREF__DARK_THEME, mode.name()).apply();

+ 6 - 10
app/src/main/java/com/nextcloud/utils/ShortcutUtil.kt

@@ -71,16 +71,12 @@ class ShortcutUtil @Inject constructor(private val mContext: Context) {
                 thumbnail = bitmapToAdaptiveBitmap(thumbnail)
                 icon = IconCompat.createWithAdaptiveBitmap(thumbnail)
             } else if (file.isFolder) {
-                val bitmapIcon = MimeTypeUtil.getFolderTypeIcon(
-                    file.isSharedWithMe || file.isSharedWithSharee,
-                    file.isSharedViaLink,
-                    file.isEncrypted,
-                    syncedFolderProvider.findByRemotePathAndAccount(file.remotePath, user),
-                    file.isGroupFolder,
-                    file.mountType,
-                    mContext,
-                    viewThemeUtils
-                ).toBitmap()
+                val isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user)
+                val isDarkModeActive = syncedFolderProvider.preferences.isDarkModeEnabled
+
+                val overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder)
+                val drawable = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, mContext, viewThemeUtils)
+                val bitmapIcon = drawable.toBitmap()
                 icon = IconCompat.createWithBitmap(bitmapIcon)
             } else {
                 icon = IconCompat.createWithResource(

+ 1 - 1
app/src/main/java/com/nextcloud/utils/Extensions.kt → app/src/main/java/com/nextcloud/utils/extensions/Extensions.kt

@@ -20,7 +20,7 @@
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.utils
+package com.nextcloud.utils.extensions
 
 import android.text.Selection
 import android.text.Spannable

+ 19 - 12
app/src/main/java/com/nmc/android/ui/LauncherActivity.kt

@@ -23,8 +23,10 @@ package com.nmc.android.ui
 import android.content.Intent
 import android.os.Bundle
 import android.os.Handler
+import android.os.Looper
 import android.text.TextUtils
 import android.view.View
+import androidx.annotation.VisibleForTesting
 import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
 import com.nextcloud.client.preferences.AppPreferences
 import com.owncloud.android.R
@@ -54,6 +56,15 @@ class LauncherActivity : BaseActivity() {
         scheduleSplashScreen()
     }
 
+    @VisibleForTesting
+    fun setSplashTitles(boldText: String, normalText: String) {
+        binding.splashScreenBold.visibility = View.VISIBLE
+        binding.splashScreenNormal.visibility = View.VISIBLE
+
+        binding.splashScreenBold.text = boldText
+        binding.splashScreenNormal.text = normalText
+    }
+
     private fun updateTitleVisibility() {
         if (TextUtils.isEmpty(resources.getString(R.string.splashScreenBold))) {
             binding.splashScreenBold.visibility = View.GONE
@@ -64,18 +75,14 @@ class LauncherActivity : BaseActivity() {
     }
 
     private fun scheduleSplashScreen() {
-        Handler().postDelayed(
-            {
-                // if user is null then go to authenticator activity
-                if (!user.isPresent) {
-                    startActivity(Intent(this, AuthenticatorActivity::class.java))
-                } else {
-                    startActivity(Intent(this, FileDisplayActivity::class.java))
-                }
-                finish()
-            },
-            SPLASH_DURATION
-        )
+        Handler(Looper.getMainLooper()).postDelayed({
+            if (!user.isPresent) {
+                startActivity(Intent(this, AuthenticatorActivity::class.java))
+            } else {
+                startActivity(Intent(this, FileDisplayActivity::class.java))
+            }
+            finish()
+        }, SPLASH_DURATION)
     }
 
     companion object {

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

@@ -24,11 +24,14 @@ package com.owncloud.android.datamodel;
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.network.WebdavEntry;
 import com.owncloud.android.lib.common.network.WebdavUtils;
@@ -38,7 +41,9 @@ import com.owncloud.android.lib.resources.files.model.GeoLocation;
 import com.owncloud.android.lib.resources.files.model.ImageDimension;
 import com.owncloud.android.lib.resources.files.model.ServerFileInterface;
 import com.owncloud.android.lib.resources.shares.ShareeUser;
+import com.owncloud.android.utils.DrawableUtil;
 import com.owncloud.android.utils.MimeType;
+import com.owncloud.android.utils.theme.ViewThemeUtils;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -47,6 +52,7 @@ import java.util.List;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.content.ContextCompat;
 import androidx.core.content.FileProvider;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import third_parties.daveKoeller.AlphanumComparator;
@@ -642,6 +648,26 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
         return permissions != null && permissions.contains(PERMISSION_GROUPFOLDER);
     }
 
+    public Integer getFileOverlayIconId(boolean isAutoUploadFolder) {
+        if (WebdavEntry.MountType.GROUP == mountType || isGroupFolder()) {
+            return R.drawable.ic_folder_overlay_account_group;
+        } else if (sharedViaLink && !encrypted) {
+            return R.drawable.ic_folder_overlay_link;
+        } else if (isSharedWithMe() || sharedWithSharee) {
+            return R.drawable.ic_folder_overlay_share;
+        } else if (encrypted) {
+            return R.drawable.ic_folder_overlay_key;
+        } else if (WebdavEntry.MountType.EXTERNAL == mountType) {
+            return R.drawable.ic_folder_overlay_external;
+        } else if (locked) {
+            return R.drawable.ic_folder_overlay_lock;
+        } else if (isAutoUploadFolder) {
+            return R.drawable.ic_folder_overlay_upload;
+        } else {
+            return null;
+        }
+    }
+
     public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
 
         @Override
@@ -995,4 +1021,5 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
     public void setTags(List<String> tags) {
         this.tags = tags;
     }
+
 }

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

@@ -34,6 +34,7 @@ import com.nextcloud.client.preferences.AppPreferencesImpl;
 import com.nextcloud.client.preferences.SubFolderRule;
 import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.files.model.ServerFileInterface;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -89,6 +90,10 @@ public class SyncedFolderProvider extends Observable {
         }
     }
 
+    public static boolean isAutoUploadFolder(SyncedFolderProvider syncedFolderProvider, ServerFileInterface file, User user) {
+        return syncedFolderProvider != null && syncedFolderProvider.findByRemotePathAndAccount(file.getRemotePath(), user);
+    }
+
     public int countEnabledSyncedFolders() {
         int count = 0;
         Cursor cursor = mContentResolver.query(
@@ -307,6 +312,10 @@ public class SyncedFolderProvider extends Observable {
         );
     }
 
+    public AppPreferences getPreferences() {
+        return preferences;
+    }
+
     /**
      * update given synced folder.
      *

+ 2 - 2
app/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -83,6 +83,7 @@ import java.util.List;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.content.ContextCompat;
 import androidx.core.content.res.ResourcesCompat;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import kotlin.text.Charsets;
@@ -899,8 +900,7 @@ public final class ThumbnailsCacheManager {
                 } else {
                     if (mFile != null) {
                         if (mFile.isDirectory()) {
-                            imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(mContext,
-                                                                                         viewThemeUtils));
+                            imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(mContext, viewThemeUtils));
                         } else {
                             if (MimeTypeUtil.isVideo(mFile)) {
                                 imageView.setImageBitmap(ThumbnailsCacheManager.mDefaultVideo);

+ 7 - 9
app/src/main/java/com/owncloud/android/ui/activity/EditorWebView.java

@@ -28,6 +28,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
 import android.os.Handler;
 import android.view.View;
@@ -39,6 +40,7 @@ import android.widget.Toast;
 
 import com.google.android.material.snackbar.Snackbar;
 import com.nextcloud.client.account.User;
+import com.nextcloud.client.preferences.DarkMode;
 import com.nextcloud.java.util.Optional;
 import com.owncloud.android.R;
 import com.owncloud.android.databinding.RichdocumentsWebviewBinding;
@@ -220,15 +222,11 @@ public abstract class EditorWebView extends ExternalSiteWebView {
         // Todo minimize: only icon by mimetype
         OCFile file = getFile();
         if (file.isFolder()) {
-            binding.thumbnail.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
-                                                                                  file.isSharedWithSharee(),
-                                                                              file.isSharedViaLink(),
-                                                                              file.isEncrypted(),
-                                                                              syncedFolderProvider.findByRemotePathAndAccount(file.getRemotePath(), user),
-                                                                              file.isGroupFolder(),
-                                                                              file.getMountType(),
-                                                                              this,
-                                                                              viewThemeUtils));
+            boolean isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user);
+
+            Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder);
+            LayerDrawable drawable = MimeTypeUtil.getFileIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils);
+            binding.thumbnail.setImageDrawable(drawable);
         } else {
             if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
                 // Thumbnail in cache?

+ 7 - 9
app/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java

@@ -23,9 +23,11 @@ package com.owncloud.android.ui.activity;
 
 import android.app.Activity;
 import android.graphics.Bitmap;
+import android.graphics.drawable.LayerDrawable;
 import android.os.Bundle;
 
 import com.nextcloud.client.account.User;
+import com.nextcloud.client.preferences.DarkMode;
 import com.nextcloud.java.util.Optional;
 import com.owncloud.android.R;
 import com.owncloud.android.databinding.ShareActivityBinding;
@@ -77,15 +79,11 @@ public class ShareActivity extends FileActivity {
 
         // Icon
         if (file.isFolder()) {
-            binding.shareFileIcon.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
-                                                                                      file.isSharedWithSharee(),
-                                                                                  file.isSharedViaLink(),
-                                                                                  file.isEncrypted(),
-                                                                                  syncedFolderProvider.findByRemotePathAndAccount(file.getRemotePath(), optionalUser.get()),
-                                                                                  file.isGroupFolder(),
-                                                                                  file.getMountType(),
-                                                                                  this,
-                                                                                  viewThemeUtils));
+            boolean isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, optionalUser.get());
+
+            Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder);
+            LayerDrawable drawable = MimeTypeUtil.getFileIcon(preferences.isDarkModeEnabled(), overlayIconId, this, viewThemeUtils);
+            binding.shareFileIcon.setImageDrawable(drawable);
         } else {
             binding.shareFileIcon.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimeType(),
                                                                                 file.getFileName(),

+ 2 - 2
app/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java

@@ -80,6 +80,7 @@ import java.util.List;
 import java.util.Locale;
 
 import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
 /**
@@ -271,8 +272,7 @@ public class ActivityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
                 .into(imageView);
         } else {
             if (MimeTypeUtil.isFolder(previewObject.getMimeType())) {
-                imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(context,
-                                                                             viewThemeUtils));
+                imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(context, viewThemeUtils));
             } else {
                 imageView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(previewObject.getMimeType(),
                                                                         "",

+ 8 - 10
app/src/main/java/com/owncloud/android/ui/adapter/GroupfolderListAdapter.kt

@@ -23,15 +23,16 @@
 package com.owncloud.android.ui.adapter
 
 import android.content.Context
+import android.graphics.drawable.LayerDrawable
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import androidx.appcompat.content.res.AppCompatResources
 import androidx.recyclerview.widget.RecyclerView
 import com.nextcloud.android.lib.resources.groupfolders.Groupfolder
 import com.owncloud.android.R
 import com.owncloud.android.databinding.ListItemBinding
 import com.owncloud.android.ui.interfaces.GroupfolderListInterface
+import com.owncloud.android.utils.MimeTypeUtil
 import com.owncloud.android.utils.theme.ViewThemeUtils
 import java.io.File
 
@@ -43,18 +44,15 @@ class GroupfolderListAdapter(
     RecyclerView.Adapter<RecyclerView.ViewHolder>() {
     lateinit var list: List<Groupfolder>
 
-    private val folderIcon = viewThemeUtils.platform.tintPrimaryDrawable(
-        context,
-        AppCompatResources.getDrawable(
-            context,
-            R.drawable.folder_group
-        )
-    )
-
     fun setData(result: Map<String, Groupfolder>) {
         list = result.values.sortedBy { it.mountPoint }
     }
 
+    private fun getFolderIcon(): LayerDrawable? {
+        val overlayDrawableId = R.drawable.ic_folder_overlay_account_group
+        return MimeTypeUtil.getFileIcon(false, overlayDrawableId, context, viewThemeUtils)
+    }
+
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
         return OCFileListItemViewHolder(
             ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
@@ -82,7 +80,7 @@ class GroupfolderListAdapter(
             localFileIndicator.visibility = View.GONE
             favorite.visibility = View.GONE
 
-            thumbnail.setImageDrawable(folderIcon)
+            thumbnail.setImageDrawable(getFolderIcon())
 
             itemLayout.setOnClickListener { groupfolderListInterface.onFolderClick(groupfolder.mountPoint) }
         }

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

@@ -54,6 +54,7 @@ import java.util.concurrent.Executors;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.core.content.ContextCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
 /**

+ 2 - 2
app/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java

@@ -48,6 +48,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
 import androidx.recyclerview.widget.RecyclerView;
 
 import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
@@ -219,8 +220,7 @@ public class TrashbinListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
 
     private void setThumbnail(TrashbinFile file, ImageView thumbnailView) {
         if (file.isFolder()) {
-            thumbnailView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(context,
-                                                                             viewThemeUtils));
+            thumbnailView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(context, viewThemeUtils));
         } else {
             if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
                 // Thumbnail in cache?

+ 7 - 9
app/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java

@@ -23,6 +23,7 @@ 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;
@@ -31,6 +32,7 @@ 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;
@@ -104,15 +106,11 @@ public class UploaderAdapter extends SimpleAdapter {
         }
 
         if (file.isFolder()) {
-            final boolean isShared = file.isSharedWithMe() || file.isSharedWithSharee();
-            final Drawable icon = MimeTypeUtil.getFolderTypeIcon(isShared,
-                                                                 file.isSharedViaLink(),
-                                                                 file.isEncrypted(),
-                                                                 syncedFolderProvider.findByRemotePathAndAccount(file.getRemotePath(), user),
-                                                                 file.isGroupFolder(),
-                                                                 file.getMountType(),
-                                                                 mContext,
-                                                                 viewThemeUtils);
+            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

+ 9 - 9
app/src/main/java/com/owncloud/android/utils/DisplayUtils.java

@@ -38,6 +38,7 @@ import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.text.Spannable;
@@ -66,6 +67,7 @@ import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
 import com.nextcloud.client.network.ClientFactory;
 import com.nextcloud.client.preferences.AppPreferences;
+import com.nextcloud.client.preferences.DarkMode;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
@@ -852,15 +854,13 @@ public final class DisplayUtils {
                                     SyncedFolderProvider syncedFolderProvider) {
         if (file.isFolder()) {
             stopShimmer(shimmerThumbnail, thumbnailView);
-            thumbnailView.setImageDrawable(MimeTypeUtil
-                                               .getFolderTypeIcon(file.isSharedWithMe() || file.isSharedWithSharee(),
-                                                                  file.isSharedViaLink(),
-                                                                  file.isEncrypted(),
-                                                                  syncedFolderProvider != null && syncedFolderProvider.findByRemotePathAndAccount(file.getRemotePath(), user),
-                                                                  file.isGroupFolder(),
-                                                                  file.getMountType(),
-                                                                  context,
-                                                                  viewThemeUtils));
+
+            boolean isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user);
+            boolean isDarkModeActive = preferences.isDarkModeEnabled();
+
+            Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder);
+            LayerDrawable fileIcon = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, context, viewThemeUtils);
+            thumbnailView.setImageDrawable(fileIcon);
         } else {
             if (file.getRemoteId() != null && file.isPreviewAvailable()) {
                 // Thumbnail in cache?

+ 47 - 0
app/src/main/java/com/owncloud/android/utils/DrawableUtil.kt

@@ -0,0 +1,47 @@
+/*
+ * 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.utils
+
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
+import androidx.core.graphics.drawable.DrawableCompat
+
+class DrawableUtil {
+
+    fun changeColor(source: Drawable, color: Int): Drawable {
+        val drawable = DrawableCompat.wrap(source)
+        DrawableCompat.setTint(drawable, color)
+        return drawable
+    }
+
+    fun addDrawableAsOverlay(backgroundDrawable: Drawable, overlayDrawable: Drawable): LayerDrawable {
+        val overlayBounds = Rect()
+        val overlayIconSize = backgroundDrawable.intrinsicWidth / 2
+        val topMargin = overlayIconSize.div(2)
+        overlayBounds.set(overlayIconSize, overlayIconSize + topMargin, overlayIconSize, overlayIconSize)
+
+        val layerDrawable = LayerDrawable(arrayOf(backgroundDrawable, overlayDrawable))
+        layerDrawable.setLayerInset(1, overlayBounds.left, overlayBounds.top, overlayBounds.right, overlayBounds.bottom)
+        return layerDrawable
+    }
+}

+ 29 - 45
app/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java

@@ -22,9 +22,13 @@ package com.owncloud.android.utils;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
+import android.util.DisplayMetrics;
+import android.util.Log;
 import android.webkit.MimeTypeMap;
 
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.network.WebdavEntry;
@@ -41,6 +45,7 @@ import java.util.Locale;
 import java.util.Map;
 
 import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
 
 /**
  * <p>Helper class for detecting the right icon for a file or folder,
@@ -133,55 +138,34 @@ public final class MimeTypeUtil {
         return determineIconIdByMimeTypeList(possibleMimeTypes);
     }
 
-    /**
-     * Returns the resource identifier of an image to use as icon associated to a type of folder.
-     *
-     * @param isSharedViaUsers flag if the folder is shared via the users system
-     * @param isSharedViaLink  flag if the folder is publicly shared via link
-     * @param isEncrypted      flag if the folder is encrypted
-     * @return Identifier of an image resource.
-     */
-    public static Drawable getFolderTypeIcon(boolean isSharedViaUsers,
-                                             boolean isSharedViaLink,
-                                             boolean isEncrypted,
-                                             boolean isAutoUploadFolder,
-                                             boolean isGroupFolder,
-                                             WebdavEntry.MountType mountType,
-                                             Context context,
-                                             ViewThemeUtils viewThemeUtils) {
-        int drawableId;
-
-        if (WebdavEntry.MountType.GROUP == mountType || isGroupFolder) {
-            drawableId = R.drawable.folder_group;
-        } else if (isSharedViaLink && !isEncrypted) {
-            drawableId = R.drawable.folder_shared_link;
-        } else if (isSharedViaUsers) {
-            drawableId = R.drawable.folder_shared_users;
-        } else if (isEncrypted) {
-            drawableId = R.drawable.folder_encrypted;
-        } else if (isAutoUploadFolder) {
-            drawableId = R.drawable.folder_auto_upload;
-        } else if (WebdavEntry.MountType.EXTERNAL == mountType) {
-            drawableId = R.drawable.folder_external;
-        } else {
-            drawableId = R.drawable.folder;
-        }
+    public static Drawable getDefaultFolderIcon(Context context, ViewThemeUtils viewThemeUtils) {
+        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.folder);
+        assert(drawable != null);
 
-        Drawable drawable = ContextCompat.getDrawable(context, drawableId);
-        viewThemeUtils.platform.tintPrimaryDrawable(context, drawable);
+        viewThemeUtils.platform.tintDrawable(context, drawable, ColorRole.PRIMARY);
         return drawable;
     }
 
-    public static Drawable getDefaultFolderIcon(Context context,
-                                                ViewThemeUtils viewThemeUtils) {
-        return getFolderTypeIcon(false,
-                                 false,
-                                 false,
-                                 false,
-                                 false,
-                                 WebdavEntry.MountType.INTERNAL,
-                                 context,
-                                 viewThemeUtils);
+    public static LayerDrawable getFileIcon(Boolean isDarkModeActive, Integer overlayIconId, Context context, ViewThemeUtils viewThemeUtils) {
+        Drawable folderDrawable = getDefaultFolderIcon(context, viewThemeUtils);
+        assert(folderDrawable != null);
+
+        LayerDrawable folderLayerDrawable = new LayerDrawable(new Drawable[] { folderDrawable } );
+
+        if (overlayIconId == null) {
+            return folderLayerDrawable;
+        }
+
+        DrawableUtil drawableUtil = new DrawableUtil();
+
+        Drawable overlayDrawable = ContextCompat.getDrawable(context, overlayIconId);
+        assert(overlayDrawable != null);
+
+        if (isDarkModeActive) {
+            overlayDrawable = drawableUtil.changeColor(overlayDrawable, R.color.dark);
+        }
+
+        return drawableUtil.addDrawableAsOverlay(folderDrawable, overlayDrawable);
     }
 
     /**

+ 0 - 29
app/src/main/res/drawable/folder_auto_upload.xml

@@ -1,29 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2023 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:fillColor="#FF000000"
-        android:fillType="nonZero"
-        android:pathData="M10,4L12,6L20,6C21.1,6 22,6.89 22,8L22,18C22,19.097 21.097,20 20,20L4,20C2.903,20 2,19.097 2,18L2,6C2,4.89 2.89,4 4,4L10,4ZM8.412,17.286L15.576,17.286L15.576,16.262L8.412,16.262L8.412,17.286ZM10.459,15.239L13.529,15.239L13.529,12.168L15.576,12.168L11.994,8.586L8.412,12.168L10.459,12.168L10.459,15.239Z" />
-</vector>

+ 0 - 28
app/src/main/res/drawable/folder_encrypted.xml

@@ -1,28 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2020 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-  <path
-      android:fillColor="#FF000000"
-      android:pathData="M4,4C2.89,4 2,4.89 2,6L2,18C2,19.1046 2.8954,20 4,20L20,20C21.1046,20 22,19.1046 22,18L22,8C22,6.89 21.1,6 20,6L12,6L10,4L4,4zM12.0254,8.6133A2.0714,2.0714 0,0 1,14.0977 10.6855L14.0977,11.5137L14.5117,11.5137A0.8286,0.8286 0,0 1,15.3398 12.3418L15.3398,16.4844A0.8286,0.8286 0,0 1,14.5117 17.3145L9.5391,17.3145A0.8286,0.8286 0,0 1,8.7109 16.4844L8.7109,12.3418C8.7109,11.8819 9.0833,11.5137 9.5391,11.5137L9.9531,11.5137L9.9531,10.6855A2.0714,2.0714 0,0 1,12.0254 8.6133zM12.0254,9.4414A1.2429,1.2429 0,0 0,10.7832 10.6855L10.7832,11.5137L13.2676,11.5137L13.2676,10.6855A1.2429,1.2429 0,0 0,12.0254 9.4414zM12.0254,13.5859A0.8286,0.8286 0,0 0,11.1973 14.4141A0.8286,0.8286 0,0 0,12.0254 15.2422A0.8286,0.8286 0,0 0,12.8535 14.4141C12.8535,13.9542 12.4811,13.5859 12.0254,13.5859z"/>
-</vector>

+ 0 - 28
app/src/main/res/drawable/folder_external.xml

@@ -1,28 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2020 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M10,4L4,4C2.89,4 2,4.89 2,6L2,18C2,19.097 2.903,20 4,20L20,20C21.097,20 22,19.097 22,18L22,8C22,6.89 21.1,6 20,6L12,6L10,4ZM8.453,9.652L10.823,9.652L11.616,10.403L8.453,10.403L8.453,16.403L14.776,16.403L14.776,13.402L15.569,14.151L15.569,16.403C15.569,16.817 15.216,17.152 14.778,17.152L8.451,17.152C8.013,17.152 7.661,16.817 7.661,16.403L7.661,10.403C7.661,9.987 8.014,9.652 8.453,9.652ZM11.616,8.903L16.361,8.903L16.361,13.402L14.776,11.902L12.404,14.152L10.823,12.651L13.196,10.405L11.616,8.903Z" />
-</vector>

+ 0 - 28
app/src/main/res/drawable/folder_group.xml

@@ -1,28 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2020 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M4,4C2.89,4 2,4.89 2,6L2,18C2,19.1046 2.8954,20 4,20L20,20C21.1046,20 22,19.1046 22,18L22,8C22,6.89 21.1,6 20,6L12,6L10,4L4,4zM10.2246,8.6348A2.03,2.03 0,0 1,12.3125 10.6641A2.03,2.03 0,0 1,10.2832 12.6934A2.03,2.03 0,0 1,10.2246 8.6348zM13.7637,8.6348A2.03,2.03 0,0 1,13.7637 12.6934A1.9662,1.9662 0,0 1,12.6445 12.3516A2.9,2.9 0,0 0,12.6445 8.9766A1.9662,1.9662 0,0 1,13.7637 8.6348zM10.2832,13.8535C14.3432,13.8535 14.3438,16.1738 14.3438,16.1738L14.3438,17.334L6.2227,17.334L6.2227,16.1738C6.2227,16.1738 6.2232,13.8535 10.2832,13.8535zM14.3086,13.8535C17.8234,14.0681 17.8223,16.1738 17.8223,16.1738L17.8223,17.334L15.5039,17.334L15.5039,16.1738A3.0856,3.0856 0,0 0,14.3086 13.8535z" />
-</vector>

+ 0 - 28
app/src/main/res/drawable/folder_shared_link.xml

@@ -1,28 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2020 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M4,4C2.89,4 2,4.89 2,6L2,18C2,19.1046 2.8954,20 4,20L20,20C21.1046,20 22,19.1046 22,18L22,8C22,6.89 21.1,6 20,6L12,6L10,4L4,4zM14.3125,8.7168C14.834,8.7168 15.3554,8.914 15.75,9.3086C16.5391,10.0977 16.5391,11.3933 15.75,12.1836L14.4668,13.4668C14.5201,12.9852 14.4446,12.4989 14.2363,12.0547L14.9297,11.3613C15.2789,11.0133 15.2777,10.4801 14.9297,10.1309C14.5817,9.7816 14.0453,9.7816 13.6973,10.1309L11.6445,12.1836A0.8577,0.8577 0,0 0,11.8867 13.582L11.041,14.4297C10.962,14.3715 10.8933,14.3086 10.8223,14.2363A2.0414,2.0414 0,0 1,10.8223 11.3613L12.875,9.3086C13.2696,8.914 13.791,8.7168 14.3125,8.7168zM13.0684,11.5801A1.9152,1.9152 0,0 1,13.2852 11.7715A2.0414,2.0414 0,0 1,13.2852 14.6465L13.2852,14.6484L11.2324,16.7012C10.4433,17.4915 9.1465,17.4903 8.3574,16.7012C7.5683,15.9121 7.5683,14.6165 8.3574,13.8262L9.6406,12.543A2.6271,2.6271 0,0 0,9.873 13.9551L9.1797,14.6484C8.8317,14.9964 8.8311,15.5309 9.1797,15.8789C9.5283,16.2269 10.0629,16.2281 10.4121,15.8789L12.4648,13.8262A0.8577,0.8577 0,0 0,12.2207 12.4277L13.0684,11.5801z" />
-</vector>

+ 0 - 28
app/src/main/res/drawable/folder_shared_users.xml

@@ -1,28 +0,0 @@
-<!--
-    @author Google LLC
-    @author Andy Scherzinger
-    Copyright (C) 2018 Google LLC
-    Copyright (C) 2020 Andy Scherzinger
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:tint="#0082c9"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M4,4C2.89,4 2,4.89 2,6L2,18A2,2 0,0 0,4 20L20,20A2,2 0,0 0,22 18L22,8C22,6.89 21.1,6 20,6L12,6L10,4L4,4zM14.9336,8.168A1.45,1.45 0,0 1,16.3828 9.6191A1.45,1.45 0,0 1,14.9336 11.0684C14.5518,11.0684 14.2083,10.9194 13.9473,10.6777L10.5391,12.6641C10.5632,12.7752 10.584,12.886 10.584,13.002C10.584,13.118 10.5632,13.2287 10.5391,13.3398L13.9863,15.3457C14.2377,15.1185 14.5663,14.9746 14.9336,14.9746A1.4113,1.4113 0,0 1,16.3457 16.3848C16.3457,17.1629 15.7118,17.791 14.9336,17.791C14.1554,17.791 13.5215,17.1629 13.5215,16.3848C13.5215,16.2736 13.5364,16.1679 13.5605,16.0664L10.1191,14.0605C9.8581,14.3022 9.5146,14.4512 9.1328,14.4512A1.45,1.45 0,0 1,7.6836 13.002A1.45,1.45 0,0 1,9.1328 11.5527C9.5146,11.5527 9.8581,11.7017 10.1191,11.9434L13.5273,9.957C13.5032,9.8459 13.4844,9.7351 13.4844,9.6191A1.45,1.45 0,0 1,14.9336 8.168z" />
-</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_account_group.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M12,5.5A3.5,3.5 0,0 1,15.5 9A3.5,3.5 0,0 1,12 12.5A3.5,3.5 0,0 1,8.5 9A3.5,3.5 0,0 1,12 5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0,0 1,2 11A3,3 0,0 1,5 8M19,8A3,3 0,0 1,22 11A3,3 0,0 1,19 14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_external.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0,0 0,5 21H19A2,2 0,0 0,21 19V12H19V19Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_key.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M7,14C5.9,14 5,13.1 5,12S5.9,10 7,10 9,10.9 9,12 8.1,14 7,14M12.6,10C11.8,7.7 9.6,6 7,6C3.7,6 1,8.7 1,12S3.7,18 7,18C9.6,18 11.8,16.3 12.6,14H16V18H20V14H23V10H12.6Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_link.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_lock.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M12,17A2,2 0,0 0,14 15C14,13.89 13.1,13 12,13A2,2 0,0 0,10 15A2,2 0,0 0,12 17M18,8A2,2 0,0 1,20 10V20A2,2 0,0 1,18 22H6A2,2 0,0 1,4 20V10C4,8.89 4.9,8 6,8H7V6A5,5 0,0 1,12 1A5,5 0,0 1,17 6V8H18M12,3A3,3 0,0 0,9 6V8H15V6A3,3 0,0 0,12 3Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_share.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0,0 0,21 5A3,3 0,0 0,18 2A3,3 0,0 0,15 5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0,0 0,3 12A3,3 0,0 0,6 15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19A2.92,2.92 0,0 0,18 16.08Z"/>
+</vector>

+ 30 - 0
app/src/main/res/drawable/ic_folder_overlay_upload.xml

@@ -0,0 +1,30 @@
+<!--
+ Nextcloud Android client application
+
+ @author Alper Öztürk
+ Copyright (C) 2023 Alper Öztürk
+ 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/>.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FFFFFF"
+      android:pathData="M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z"/>
+</vector>

+ 2 - 2
app/src/test/java/com/nextcloud/android/utils/ExtensionsTest.kt

@@ -1,7 +1,7 @@
 package com.nextcloud.android.utils
 
-import com.nextcloud.utils.getFormattedStringDate
-import com.nextcloud.utils.isCurrentYear
+import com.nextcloud.utils.extensions.getFormattedStringDate
+import com.nextcloud.utils.extensions.isCurrentYear
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Test

+ 0 - 5
drawable_resources/folder_auto_upload.svg

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg width="100%" height="100%" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
-    <path d="M10,4L12,6L20,6C21.1,6 22,6.89 22,8L22,18C22,19.097 21.097,20 20,20L4,20C2.903,20 2,19.097 2,18L2,6C2,4.89 2.89,4 4,4L10,4ZM8.412,17.286L15.576,17.286L15.576,16.262L8.412,16.262L8.412,17.286ZM10.459,15.239L13.529,15.239L13.529,12.168L15.576,12.168L11.994,8.586L8.412,12.168L10.459,12.168L10.459,15.239Z" style="fill-rule:nonzero;"/>
-</svg>

+ 0 - 67
drawable_resources/folder_encrypted.svg

@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="24"
-   height="24"
-   viewBox="0 0 24 24"
-   id="svg3738"
-   sodipodi:docname="folder-group.svg"
-   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
-  <metadata
-     id="metadata3744">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3742" />
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="2520"
-     inkscape:window-height="1481"
-     id="namedview3740"
-     showgrid="false"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:zoom="27.812867"
-     inkscape:cx="20.589505"
-     inkscape:cy="10.4013"
-     inkscape:window-x="2869"
-     inkscape:window-y="-11"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg3738">
-    <sodipodi:guide
-       position="12.025424,12.737288"
-       orientation="1,0"
-       id="guide3746"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="1.0606602,11.020079"
-       orientation="0,1"
-       id="guide3748"
-       inkscape:locked="false" />
-  </sodipodi:namedview>
-  <path
-     d="M 4 4 C 2.89 4 2 4.89 2 6 L 2 18 C 2 19.104569 2.8954305 20 4 20 L 20 20 C 21.104569 20 22 19.104569 22 18 L 22 8 C 22 6.89 21.1 6 20 6 L 12 6 L 10 4 L 4 4 z M 12.025391 8.6132812 A 2.0714286 2.0714286 0 0 1 14.097656 10.685547 L 14.097656 11.513672 L 14.511719 11.513672 A 0.82857142 0.82857142 0 0 1 15.339844 12.341797 L 15.339844 16.484375 A 0.82857142 0.82857142 0 0 1 14.511719 17.314453 L 9.5390625 17.314453 A 0.82857142 0.82857142 0 0 1 8.7109375 16.484375 L 8.7109375 12.341797 C 8.7109375 11.88194 9.0833475 11.513672 9.5390625 11.513672 L 9.953125 11.513672 L 9.953125 10.685547 A 2.0714286 2.0714286 0 0 1 12.025391 8.6132812 z M 12.025391 9.4414062 A 1.2428571 1.2428571 0 0 0 10.783203 10.685547 L 10.783203 11.513672 L 13.267578 11.513672 L 13.267578 10.685547 A 1.2428571 1.2428571 0 0 0 12.025391 9.4414062 z M 12.025391 13.585938 A 0.82857142 0.82857142 0 0 0 11.197266 14.414062 A 0.82857142 0.82857142 0 0 0 12.025391 15.242188 A 0.82857142 0.82857142 0 0 0 12.853516 14.414062 C 12.853516 13.954206 12.481105 13.585937 12.025391 13.585938 z "
-     id="path3736" />
-</svg>

+ 0 - 5
drawable_resources/folder_external.svg

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg width="100%" height="100%" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
-    <path d="M10,4L4,4C2.89,4 2,4.89 2,6L2,18C2,19.097 2.903,20 4,20L20,20C21.097,20 22,19.097 22,18L22,8C22,6.89 21.1,6 20,6L12,6L10,4ZM8.453,9.652L10.823,9.652L11.616,10.403L8.453,10.403L8.453,16.403L14.776,16.403L14.776,13.402L15.569,14.151L15.569,16.403C15.569,16.817 15.216,17.152 14.778,17.152L8.451,17.152C8.013,17.152 7.661,16.817 7.661,16.403L7.661,10.403C7.661,9.987 8.014,9.652 8.453,9.652ZM11.616,8.903L16.361,8.903L16.361,13.402L14.776,11.902L12.404,14.152L10.823,12.651L13.196,10.405L11.616,8.903Z" style="fill-rule:nonzero;"/>
-</svg>

+ 0 - 67
drawable_resources/folder_group.svg

@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="24"
-   height="24"
-   viewBox="0 0 24 24"
-   id="svg3738"
-   sodipodi:docname="folder-group.svg"
-   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
-  <metadata
-     id="metadata3744">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3742" />
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="2520"
-     inkscape:window-height="1481"
-     id="namedview3740"
-     showgrid="false"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:zoom="39.333333"
-     inkscape:cx="5.613764"
-     inkscape:cy="12.065596"
-     inkscape:window-x="2869"
-     inkscape:window-y="-11"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg3738">
-    <sodipodi:guide
-       position="12.025424,12.737288"
-       orientation="1,0"
-       id="guide3746"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="1.0606602,11.020079"
-       orientation="0,1"
-       id="guide3748"
-       inkscape:locked="false" />
-  </sodipodi:namedview>
-  <path
-     d="M 4 4 C 2.89 4 2 4.89 2 6 L 2 18 C 2 19.104569 2.8954305 20 4 20 L 20 20 C 21.104569 20 22 19.104569 22 18 L 22 8 C 22 6.89 21.1 6 20 6 L 12 6 L 10 4 L 4 4 z M 10.224609 8.6347656 A 2.0299929 2.0299929 0 0 1 12.3125 10.664062 A 2.0299929 2.0299929 0 0 1 10.283203 12.693359 A 2.0299929 2.0299929 0 0 1 10.224609 8.6347656 z M 13.763672 8.6347656 A 2.0299932 2.0299932 0 0 1 13.763672 12.693359 A 1.9661931 1.9661931 0 0 1 12.644531 12.351562 A 2.8999899 2.8999899 0 0 0 12.644531 8.9765625 A 1.9661931 1.9661931 0 0 1 13.763672 8.6347656 z M 10.283203 13.853516 C 14.343189 13.853516 14.34375 16.173828 14.34375 16.173828 L 14.34375 17.333984 L 6.2226562 17.333984 L 6.2226562 16.173828 C 6.2226562 16.173828 6.2232172 13.853516 10.283203 13.853516 z M 14.308594 13.853516 C 17.823381 14.068115 17.822266 16.173828 17.822266 16.173828 L 17.822266 17.333984 L 15.503906 17.333984 L 15.503906 16.173828 A 3.0855892 3.0855892 0 0 0 14.308594 13.853516 z "
-     id="path3736" />
-</svg>

+ 0 - 67
drawable_resources/folder_shared_link.svg

@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="24"
-   height="24"
-   viewBox="0 0 24 24"
-   id="svg3738"
-   sodipodi:docname="folder_public.svg"
-   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
-  <metadata
-     id="metadata3744">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3742" />
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="2520"
-     inkscape:window-height="1481"
-     id="namedview3740"
-     showgrid="false"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:zoom="27.812867"
-     inkscape:cx="19.008573"
-     inkscape:cy="7.4638855"
-     inkscape:window-x="2869"
-     inkscape:window-y="-11"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg3738">
-    <sodipodi:guide
-       position="12.025424,12.737288"
-       orientation="1,0"
-       id="guide3746"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="1.0606602,11.020079"
-       orientation="0,1"
-       id="guide3748"
-       inkscape:locked="false" />
-  </sodipodi:namedview>
-  <path
-     d="M 4 4 C 2.89 4 2 4.89 2 6 L 2 18 C 2 19.104569 2.8954305 20 4 20 L 20 20 C 21.104569 20 22 19.104569 22 18 L 22 8 C 22 6.89 21.1 6 20 6 L 12 6 L 10 4 L 4 4 z M 14.3125 8.7167969 C 14.834031 8.7167969 15.355444 8.9140378 15.75 9.3085938 C 16.539112 10.097706 16.539112 11.393256 15.75 12.183594 L 14.466797 13.466797 C 14.520098 12.985243 14.444634 12.498869 14.236328 12.054688 L 14.929688 11.361328 C 15.278905 11.013335 15.27768 10.480077 14.929688 10.130859 C 14.581694 9.7816405 14.04526 9.7816405 13.697266 10.130859 L 11.644531 12.183594 A 0.8577305 0.8577305 0 0 0 11.886719 13.582031 L 11.041016 14.429688 C 10.961982 14.371484 10.893336 14.308618 10.822266 14.236328 A 2.0413986 2.0413986 0 0 1 10.822266 11.361328 L 12.875 9.3085938 C 13.269556 8.9140377 13.790969 8.7167969 14.3125 8.7167969 z M 13.068359 11.580078 A 1.9151897 1.9151897 0 0 1 13.285156 11.771484 A 2.0413986 2.0413986 0 0 1 13.285156 14.646484 L 13.285156 14.648438 L 11.232422 16.701172 C 10.44331 17.491509 9.146534 17.490284 8.3574219 16.701172 C 7.5683099 15.91206 7.5683099 14.616509 8.3574219 13.826172 L 9.640625 12.542969 A 2.627106 2.627106 0 0 0 9.8730469 13.955078 L 9.1796875 14.648438 C 8.8316939 14.996431 8.8310813 15.530912 9.1796875 15.878906 C 9.5282936 16.226925 10.062891 16.228125 10.412109 15.878906 L 12.464844 13.826172 A 0.8577305 0.8577305 0 0 0 12.220703 12.427734 L 13.068359 11.580078 z "
-     id="path3736" />
-</svg>

+ 0 - 66
drawable_resources/folder_shared_users.svg

@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.1"
-   width="24"
-   height="24"
-   viewBox="0 0 24 24"
-   id="svg3738"
-   sodipodi:docname="folder-shared.svg"
-   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
-  <metadata
-     id="metadata3744">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3742" />
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="2520"
-     inkscape:window-height="1481"
-     id="namedview3740"
-     showgrid="false"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:zoom="27.812867"
-     inkscape:cx="-0.64166953"
-     inkscape:cy="11.271299"
-     inkscape:window-x="2869"
-     inkscape:window-y="-11"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg3738">
-    <sodipodi:guide
-       position="12.025424,12.737288"
-       orientation="1,0"
-       id="guide3746"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="1.0606602,11.020079"
-       orientation="0,1"
-       id="guide3748"
-       inkscape:locked="false" />
-  </sodipodi:namedview>
-  <path
-     d="M 4 4 C 2.89 4 2 4.89 2 6 L 2 18 A 2 2 0 0 0 4 20 L 20 20 A 2 2 0 0 0 22 18 L 22 8 C 22 6.89 21.1 6 20 6 L 12 6 L 10 4 L 4 4 z M 14.933594 8.1679688 A 1.449999 1.449999 0 0 1 16.382812 9.6191406 A 1.449999 1.449999 0 0 1 14.933594 11.068359 C 14.55176 11.068359 14.208265 10.9194 13.947266 10.677734 L 10.539062 12.664062 C 10.563222 12.77523 10.583984 12.885951 10.583984 13.001953 C 10.583984 13.117952 10.563223 13.228676 10.539062 13.339844 L 13.986328 15.345703 C 14.237662 15.118536 14.566259 14.974609 14.933594 14.974609 A 1.4113325 1.4113325 0 0 1 16.345703 16.384766 C 16.345703 17.162932 15.711761 17.791016 14.933594 17.791016 C 14.155428 17.791016 13.521484 17.162932 13.521484 16.384766 C 13.521484 16.273599 13.536387 16.167908 13.560547 16.066406 L 10.119141 14.060547 C 9.8581421 14.302213 9.5146455 14.451172 9.1328125 14.451172 A 1.449999 1.449999 0 0 1 7.6835938 13.001953 A 1.449999 1.449999 0 0 1 9.1328125 11.552734 C 9.5146455 11.552734 9.8581421 11.701692 10.119141 11.943359 L 13.527344 9.9570312 C 13.503184 9.8458632 13.484375 9.7351412 13.484375 9.6191406 A 1.449999 1.449999 0 0 1 14.933594 8.1679688 z "
-     id="path3736" />
-</svg>