浏览代码

File actions bottom sheet: show file thumbnail

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey 2 年之前
父节点
当前提交
4523537587

+ 34 - 0
app/src/main/java/com/nextcloud/ui/fileactions/FileActionsBottomSheet.kt

@@ -41,13 +41,16 @@ import androidx.fragment.app.setFragmentResult
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.ViewModelProvider
 import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.nextcloud.android.common.ui.theme.utils.ColorRole
 import com.nextcloud.client.account.CurrentAccountProvider
 import com.nextcloud.client.di.Injectable
 import com.nextcloud.client.di.ViewModelFactory
 import com.owncloud.android.R
 import com.owncloud.android.databinding.FileActionsBottomSheetBinding
 import com.owncloud.android.databinding.FileActionsBottomSheetItemBinding
+import com.owncloud.android.datamodel.FileDataStorageManager
 import com.owncloud.android.datamodel.OCFile
+import com.owncloud.android.datamodel.ThumbnailsCacheManager
 import com.owncloud.android.lib.resources.files.model.FileLockType
 import com.owncloud.android.ui.activity.ComponentsGetter
 import com.owncloud.android.utils.DisplayUtils
@@ -66,6 +69,9 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
     @Inject
     lateinit var currentUserProvider: CurrentAccountProvider
 
+    @Inject
+    lateinit var storageManager: FileDataStorageManager
+
     lateinit var viewModel: FileActionsViewModel
 
     private var _binding: FileActionsBottomSheetBinding? = null
@@ -74,6 +80,8 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
 
     lateinit var componentsGetter: ComponentsGetter
 
+    private val thumbnailAsyncTasks = mutableListOf<ThumbnailsCacheManager.ThumbnailGenerationTask>()
+
     interface ResultListener {
         fun onResult(@IdRes actionId: Int)
     }
@@ -99,6 +107,7 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         toggleLoadingOrContent(state)
         when (state) {
             is FileActionsViewModel.UiState.LoadedForSingleFile -> {
+                loadFileThumbnail(state.titleFile)
                 if (state.lockInfo != null) {
                     displayLockInfo(state.lockInfo)
                 }
@@ -106,6 +115,7 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
                 displayTitle(state.titleFile)
             }
             is FileActionsViewModel.UiState.LoadedForMultipleFiles -> {
+                setMultipleFilesThumbnail()
                 displayActions(state.actions)
                 displayTitle(state.fileCount)
             }
@@ -119,6 +129,30 @@ class FileActionsBottomSheet private constructor() : BottomSheetDialogFragment()
         }
     }
 
+    private fun loadFileThumbnail(titleFile: OCFile?) {
+        titleFile?.let {
+            DisplayUtils.setThumbnail(
+                it,
+                binding.thumbnailLayout.thumbnail,
+                currentUserProvider.user,
+                storageManager,
+                thumbnailAsyncTasks,
+                false,
+                context,
+                binding.thumbnailLayout.thumbnailShimmer,
+                null,
+                viewThemeUtils
+            )
+        }
+    }
+
+    private fun setMultipleFilesThumbnail() {
+        context?.let {
+            val drawable = viewThemeUtils.platform.tintDrawable(it, R.drawable.file_multiple, ColorRole.PRIMARY)
+            binding.thumbnailLayout.thumbnail.setImageDrawable(drawable)
+        }
+    }
+
     override fun onDestroyView() {
         super.onDestroyView()
         _binding = null

+ 3 - 3
app/src/main/java/com/owncloud/android/ui/adapter/OCFileListItemViewHolder.kt

@@ -47,14 +47,14 @@ internal class OCFileListItemViewHolder(private var binding: ListItemBinding) :
     override val fileName: TextView
         get() = binding.Filename
     override val thumbnail: ImageView
-        get() = binding.thumbnail
+        get() = binding.thumbnailLayout.thumbnail
 
     override fun showVideoOverlay() {
-        binding.videoOverlay.visibility = View.VISIBLE
+        binding.thumbnailLayout.videoOverlay.visibility = View.VISIBLE
     }
 
     override val shimmerThumbnail: LoaderImageView
-        get() = binding.thumbnailShimmer
+        get() = binding.thumbnailLayout.thumbnailShimmer
     override val favorite: ImageView
         get() = binding.favoriteAction
     override val localFileIndicator: ImageView

+ 8 - 0
app/src/main/res/drawable/file_multiple.xml

@@ -0,0 +1,8 @@
+<!-- drawable/file_multiple.xml -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M15,7H20.5L15,1.5V7M8,0H16L22,6V18A2,2 0 0,1 20,20H8C6.89,20 6,19.1 6,18V2A2,2 0 0,1 8,0M4,4V22H20V24H4A2,2 0 0,1 2,22V4H4Z" />
+</vector>

+ 30 - 7
app/src/main/res/layout/file_actions_bottom_sheet.xml

@@ -38,42 +38,65 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 
+        <!--  TODO theme this! -->
         <com.google.android.material.progressindicator.CircularProgressIndicator
             android:indeterminate="true"
             android:id="@+id/bottom_sheet_loading"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="center" />
+            android:layout_gravity="center"
+            tools:visibility="gone" />
 
-        <LinearLayout
+        <androidx.constraintlayout.widget.ConstraintLayout
             android:id="@+id/bottom_sheet_content"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="vertical"
             android:visibility="gone"
-            tools:visibility="gone">
+            tools:visibility="visible">
+
+            <FrameLayout
+                android:id="@+id/thumbnail_container"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="@dimen/standard_padding"
+                app:layout_constraintBottom_toBottomOf="@+id/title"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="@+id/title">
+
+                <include
+                    android:id="@+id/thumbnail_layout"
+                    layout="@layout/file_thumbnail" />
+            </FrameLayout>
 
             <TextView
                 android:id="@+id/title"
-                android:layout_width="match_parent"
+                android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:ellipsize="middle"
                 android:lines="1"
                 android:padding="@dimen/standard_padding"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toEndOf="@id/thumbnail_container"
+                app:layout_constraintTop_toTopOf="parent"
                 android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
                 tools:text="Test file name which is very very very very very long.pdf" />
 
-
+            <!--  TODO test scroll -->
             <androidx.core.widget.NestedScrollView
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content">
+                android:layout_height="wrap_content"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/title">
+
                 <LinearLayout
                     android:id="@+id/file_actions_list"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:orientation="vertical" />
             </androidx.core.widget.NestedScrollView>
-        </LinearLayout>
+        </androidx.constraintlayout.widget.ConstraintLayout>
     </LinearLayout>
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 63 - 0
app/src/main/res/layout/file_thumbnail.xml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+
+<!--
+  ~ Nextcloud Android client application
+  ~
+  ~  @author Álvaro Brey
+  ~  Copyright (C) 2022 Álvaro Brey
+  ~  Copyright (C) 2022 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
+  ~ License as published by the Free Software Foundation; either
+  ~ version 3 of the License, or any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+  ~
+  ~ You should have received a copy of the GNU Affero General Public
+  ~ License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  ~
+  -->
+
+<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    tools:showIn="@layout/list_item">
+
+    <FrameLayout
+        android:layout_width="@dimen/file_icon_size"
+        android:layout_height="@dimen/file_icon_size"
+        android:layout_gravity="center">
+
+        <ImageView
+            android:id="@+id/thumbnail"
+            android:layout_width="@dimen/file_icon_size"
+            android:layout_height="@dimen/file_icon_size"
+            android:contentDescription="@null"
+            android:src="@drawable/folder" />
+
+        <ImageView
+            android:id="@+id/videoOverlay"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2dp"
+            android:layout_marginStart="2dp"
+            android:src="@drawable/video_white"
+            android:visibility="gone"
+            android:contentDescription="@string/video_overlay_icon" />
+    </FrameLayout>
+
+    <com.elyeproj.loaderviewlibrary.LoaderImageView
+        android:id="@+id/thumbnail_shimmer"
+        android:layout_width="@dimen/file_icon_size"
+        android:layout_height="@dimen/file_icon_size"
+        android:visibility="gone"
+        app:corners="8" />
+</FrameLayout>
+

+ 12 - 40
app/src/main/res/layout/list_item.xml

@@ -18,7 +18,6 @@
  -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/ListItemLayout"
     android:layout_width="match_parent"
     android:layout_height="@dimen/standard_list_item_size"
@@ -34,7 +33,7 @@
         android:layout_marginBottom="@dimen/standard_padding">
 
         <FrameLayout
-            android:id="@+id/thumbnail_layout"
+            android:id="@+id/thumbnail_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -42,36 +41,9 @@
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent">
 
-            <FrameLayout
-                android:layout_width="@dimen/file_icon_size"
-                android:layout_height="@dimen/file_icon_size"
-                android:layout_gravity="center">
-
-                <ImageView
-                    android:id="@+id/thumbnail"
-                    android:layout_width="@dimen/file_icon_size"
-                    android:layout_height="@dimen/file_icon_size"
-                    android:contentDescription="@null"
-                    android:src="@drawable/folder" />
-
-                <ImageView
-                    android:id="@+id/videoOverlay"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="2dp"
-                    android:layout_marginStart="2dp"
-                    android:src="@drawable/video_white"
-                    android:visibility="gone"
-                    tools:visibility="visible"
-                    android:contentDescription="@string/video_overlay_icon" />
-            </FrameLayout>
-
-            <com.elyeproj.loaderviewlibrary.LoaderImageView
-                android:id="@+id/thumbnail_shimmer"
-                android:layout_width="@dimen/file_icon_size"
-                android:layout_height="@dimen/file_icon_size"
-                android:visibility="gone"
-                app:corners="8" />
+            <include
+                android:id="@+id/thumbnail_layout"
+                layout="@layout/file_thumbnail" />
         </FrameLayout>
 
         <ImageView
@@ -81,10 +53,10 @@
             android:contentDescription="@string/downloader_download_succeeded_ticker"
             android:scaleType="fitCenter"
             android:src="@drawable/ic_synced"
-            app:layout_constraintBottom_toBottomOf="@+id/thumbnail_layout"
-            app:layout_constraintEnd_toEndOf="@+id/thumbnail_layout"
-            app:layout_constraintStart_toEndOf="@+id/thumbnail_layout"
-            app:layout_constraintTop_toBottomOf="@+id/thumbnail_layout" />
+            app:layout_constraintBottom_toBottomOf="@+id/thumbnail_container"
+            app:layout_constraintEnd_toEndOf="@+id/thumbnail_container"
+            app:layout_constraintStart_toEndOf="@+id/thumbnail_container"
+            app:layout_constraintTop_toBottomOf="@+id/thumbnail_container" />
 
         <ImageView
             android:id="@+id/favorite_action"
@@ -92,10 +64,10 @@
             android:layout_height="@dimen/list_item_favorite_action_layout_height"
             android:contentDescription="@string/favorite"
             android:src="@drawable/favorite"
-            app:layout_constraintBottom_toTopOf="@+id/thumbnail_layout"
-            app:layout_constraintEnd_toEndOf="@+id/thumbnail_layout"
-            app:layout_constraintStart_toEndOf="@+id/thumbnail_layout"
-            app:layout_constraintTop_toTopOf="@+id/thumbnail_layout" />
+            app:layout_constraintBottom_toTopOf="@+id/thumbnail_container"
+            app:layout_constraintEnd_toEndOf="@+id/thumbnail_container"
+            app:layout_constraintStart_toEndOf="@+id/thumbnail_container"
+            app:layout_constraintTop_toTopOf="@+id/thumbnail_container" />
 
     </androidx.constraintlayout.widget.ConstraintLayout>