From 529c9858a946419fd45cc58ec7ef69c368e3f7b3 Mon Sep 17 00:00:00 2001
From: Taras Smakula <tarassmakula@gmail.com>
Date: Mon, 18 Dec 2023 16:37:49 +0200
Subject: [PATCH] Add media usage progress on settings page

---
 .../feature/settings/SettingsFragment.kt      | 24 +++++++++++
 .../feature/settings/SettingsViewModel.kt     | 12 ++++++
 app/src/main/res/layout/fragment_settings.xml | 41 ++++++++++++++++++-
 app/src/main/res/values/strings.xml           |  2 +
 .../backup/list/MediaFolderViewHolder.kt      | 17 ++------
 5 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/app/src/main/java/org/futo/circles/feature/settings/SettingsFragment.kt b/app/src/main/java/org/futo/circles/feature/settings/SettingsFragment.kt
index 6ef1753b7..ebf29d87c 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/SettingsFragment.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/SettingsFragment.kt
@@ -1,6 +1,7 @@
 package org.futo.circles.feature.settings
 
 import android.os.Bundle
+import android.text.format.Formatter
 import android.view.View
 import android.widget.Toast
 import androidx.fragment.app.Fragment
@@ -28,6 +29,7 @@ import org.futo.circles.core.provider.PreferencesProvider
 import org.futo.circles.core.view.LoadingDialog
 import org.futo.circles.databinding.FragmentSettingsBinding
 import org.matrix.android.sdk.api.session.user.model.User
+import org.matrix.android.sdk.internal.session.media.MediaUsageInfo
 
 @AndroidEntryPoint
 class SettingsFragment : Fragment(R.layout.fragment_settings) {
@@ -44,6 +46,11 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
         setupObservers()
     }
 
+    override fun onResume() {
+        super.onResume()
+        viewModel.updateMediaUsageInfo()
+    }
+
     private fun setupViews() {
         with(binding) {
             tvManageSubscription.apply {
@@ -101,6 +108,23 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
         viewModel.passPhraseLoadingLiveData.observeData(this) {
             loadingDialog.handleLoading(it)
         }
+        viewModel.mediaUsageInfoLiveData.observeData(this) { mediaUsage ->
+            bindMediaUsageProgress(mediaUsage)
+        }
+    }
+
+    private fun bindMediaUsageProgress(mediaUsage: MediaUsageInfo?) {
+        binding.lMediaStorage.setIsVisible(mediaUsage != null)
+        mediaUsage ?: return
+        binding.mediaStorageProgress.apply {
+            max = mediaUsage.storageSize.toInt()
+            progress = mediaUsage.usedSize.toInt()
+        }
+        binding.tvMediaStorageInfo.text = getString(
+            R.string.media_usage_format,
+            Formatter.formatFileSize(requireContext(), mediaUsage.usedSize),
+            Formatter.formatFileSize(requireContext(), mediaUsage.storageSize),
+        )
     }
 
     private fun bindProfile(user: User) {
diff --git a/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt b/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
index 8b66e0e63..318be6f70 100644
--- a/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
+++ b/app/src/main/java/org/futo/circles/feature/settings/SettingsViewModel.kt
@@ -1,5 +1,6 @@
 package org.futo.circles.feature.settings
 
+import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
 import dagger.hilt.android.lifecycle.HiltViewModel
 import org.futo.circles.auth.feature.log_in.log_out.LogoutDataSource
@@ -9,6 +10,8 @@ import org.futo.circles.core.extensions.Response
 import org.futo.circles.core.extensions.launchBg
 import org.futo.circles.core.feature.workspace.SharedCircleDataSource
 import org.futo.circles.core.provider.MatrixSessionProvider
+import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.internal.session.media.MediaUsageInfo
 import javax.inject.Inject
 
 @HiltViewModel
@@ -26,6 +29,7 @@ class SettingsViewModel @Inject constructor(
     val deactivateLiveData = SingleEventLiveData<Response<Unit?>>()
     val navigateToMatrixChangePasswordEvent = SingleEventLiveData<Unit>()
     val changePasswordResponseLiveData = SingleEventLiveData<Response<Unit?>>()
+    val mediaUsageInfoLiveData = MutableLiveData<MediaUsageInfo?>()
 
     fun logOut() {
         launchBg {
@@ -58,4 +62,12 @@ class SettingsViewModel @Inject constructor(
     }
 
     fun getSharedCircleSpaceId(): String? = sharedCircleDataSource.getSharedCirclesSpaceId()
+    fun updateMediaUsageInfo() {
+        launchBg {
+            val mediaUsageInfo = tryOrNull {
+                MatrixSessionProvider.getSessionOrThrow().mediaService().getMediaUsage()
+            }
+            mediaUsageInfoLiveData.postValue(mediaUsageInfo)
+        }
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index f71f7909f..3c8465987 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -113,7 +113,7 @@
     <View
         android:layout_width="match_parent"
         android:layout_height="@dimen/divider_height"
-        android:layout_marginTop="8dp"
+        android:layout_marginTop="12dp"
         android:background="@color/divider_color" />
 
     <ScrollView
@@ -127,6 +127,45 @@
             android:clipToPadding="false"
             android:orientation="vertical">
 
+            <LinearLayout
+                android:id="@+id/lMediaStorage"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone"
+                tools:visibility="visible">
+
+                <TextView
+                    style="@style/settingMenuHeader"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/media_storage" />
+
+                <com.google.android.material.progressindicator.LinearProgressIndicator
+                    android:id="@+id/mediaStorageProgress"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginHorizontal="16dp"
+                    app:trackCornerRadius="6dp"
+                    tools:progress="15" />
+
+                <TextView
+                    android:id="@+id/tvMediaStorageInfo"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="16dp"
+                    android:layout_marginTop="4dp"
+                    android:gravity="center"
+                    android:paddingBottom="4dp"
+                    android:textSize="13sp"
+                    app:layout_constraintBottom_toBottomOf="@id/ivProfile"
+                    app:layout_constraintEnd_toEndOf="@id/ivEditProfile"
+                    app:layout_constraintStart_toStartOf="@id/ivEditProfile"
+                    app:layout_constraintTop_toBottomOf="@id/ivEditProfile"
+                    tools:text="7 GB of 15 GB used" />
+
+            </LinearLayout>
+
             <TextView
                 style="@style/settingMenuHeader"
                 android:layout_width="match_parent"
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f748de26c..5dfcf491c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -209,6 +209,8 @@
     <string name="session">Session</string>
     <string name="help">Help</string>
     <string name="optional_request_message">Optional: Request message</string>
+    <string name="media_storage">Media storage</string>
+    <string name="media_usage_format">%s of %s used</string>
 
     <!-- Rich text editor -->
     <string name="rich_text_editor_format_bold">Apply bold format</string>
diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/list/MediaFolderViewHolder.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/list/MediaFolderViewHolder.kt
index 69507097b..ffe092e44 100644
--- a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/list/MediaFolderViewHolder.kt
+++ b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/list/MediaFolderViewHolder.kt
@@ -1,13 +1,13 @@
 package org.futo.circles.gallery.feature.backup.list
 
+import android.text.format.Formatter.formatFileSize
 import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
-import org.futo.circles.core.extensions.onClick
 import org.futo.circles.core.base.list.ViewBindingHolder
+import org.futo.circles.core.base.list.context
+import org.futo.circles.core.extensions.onClick
 import org.futo.circles.gallery.databinding.ListItemMediaFolderBinding
 import org.futo.circles.gallery.model.MediaFolderListItem
-import kotlin.math.log10
-import kotlin.math.pow
 
 class MediaFolderViewHolder(
     parent: ViewGroup,
@@ -28,17 +28,8 @@ class MediaFolderViewHolder(
     fun bind(data: MediaFolderListItem) {
         with(binding) {
             tvFolderName.text = data.displayName
-            tvSize.text = formatFileSize(data.size)
+            tvSize.text = formatFileSize(context, data.size)
             svFolder.isChecked = data.isSelected
         }
     }
-
-    private fun formatFileSize(size: Long): String {
-        if (size <= 0) return "0 B"
-        val units = arrayOf("B", "KB", "MB", "GB", "TB")
-        val digitGroups = (log10(size.toDouble()) / log10(1024.0)).toInt()
-        return String.format(
-            "%.1f %s", size / 1024.0.pow(digitGroups.toDouble()), units[digitGroups]
-        )
-    }
 }
\ No newline at end of file
-- 
GitLab