diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt index bd8b17e43..798fa7c33 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt @@ -1,35 +1,24 @@ package org.koitharu.kotatsu.settings.tools import android.content.Intent -import android.content.res.ColorStateList import android.os.Bundle -import android.transition.TransitionManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.CompoundButton -import androidx.annotation.ColorInt -import androidx.core.graphics.ColorUtils import androidx.core.graphics.Insets import androidx.core.net.toUri import androidx.core.view.isVisible import androidx.core.view.updatePadding -import androidx.core.widget.TextViewCompat import androidx.fragment.app.viewModels -import com.google.android.material.color.MaterialColors import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.widgets.SegmentedBarView import org.koitharu.kotatsu.core.github.AppVersion import org.koitharu.kotatsu.databinding.FragmentToolsBinding import org.koitharu.kotatsu.download.ui.DownloadsActivity import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.about.AppUpdateDialog -import org.koitharu.kotatsu.settings.tools.model.StorageUsage -import org.koitharu.kotatsu.utils.FileSize -import org.koitharu.kotatsu.utils.ext.getThemeColor -import com.google.android.material.R as materialR @AndroidEntryPoint class ToolsFragment : @@ -50,11 +39,14 @@ class ToolsFragment : binding.cardUpdate.buttonChangelog.setOnClickListener(this) binding.cardUpdate.buttonDownload.setOnClickListener(this) binding.switchIncognito.setOnCheckedChangeListener(this) + binding.memoryUsageView.setManageButtonOnClickListener(this) viewModel.isIncognitoModeEnabled.observe(viewLifecycleOwner) { binding.switchIncognito.isChecked = it } - viewModel.storageUsage.observe(viewLifecycleOwner, ::onStorageUsageChanged) + viewModel.storageUsage.observe(viewLifecycleOwner) { + binding.memoryUsageView.bind(it) + } viewModel.appUpdate.observe(viewLifecycleOwner, ::onAppUpdateAvailable) } @@ -96,51 +88,6 @@ class ToolsFragment : binding.cardUpdate.root.isVisible = true } - private fun onStorageUsageChanged(usage: StorageUsage) { - val storageSegment = SegmentedBarView.Segment(usage.savedManga.percent, segmentColor(1)) - val pagesSegment = SegmentedBarView.Segment(usage.pagesCache.percent, segmentColor(2)) - val otherSegment = SegmentedBarView.Segment(usage.otherCache.percent, segmentColor(3)) - - with(binding.layoutStorage) { - buttonManage.setOnClickListener(this@ToolsFragment) - bar.segments = listOf(storageSegment, pagesSegment, otherSegment) - val pattern = getString(R.string.memory_usage_pattern) - labelStorage.text = pattern.format( - FileSize.BYTES.format(root.context, usage.savedManga.bytes), - getString(R.string.saved_manga), - ) - labelPagesCache.text = pattern.format( - FileSize.BYTES.format(root.context, usage.pagesCache.bytes), - getString(R.string.pages_cache), - ) - labelOtherCache.text = pattern.format( - FileSize.BYTES.format(root.context, usage.otherCache.bytes), - getString(R.string.other_cache), - ) - labelAvailable.text = pattern.format( - FileSize.BYTES.format(root.context, usage.available.bytes), - getString(R.string.available), - ) - TextViewCompat.setCompoundDrawableTintList(labelStorage, ColorStateList.valueOf(storageSegment.color)) - TextViewCompat.setCompoundDrawableTintList(labelPagesCache, ColorStateList.valueOf(pagesSegment.color)) - TextViewCompat.setCompoundDrawableTintList(labelOtherCache, ColorStateList.valueOf(otherSegment.color)) - if (!labelStorage.isVisible) { - TransitionManager.beginDelayedTransition(root) - } - labelStorage.isVisible = true - labelPagesCache.isVisible = true - labelOtherCache.isVisible = true - } - } - - @ColorInt - private fun segmentColor(i: Int): Int { - val hue = (93.6f * i) % 360 - val color = ColorUtils.HSLToColor(floatArrayOf(hue, 0.4f, 0.6f)) - val backgroundColor = requireContext().getThemeColor(materialR.attr.colorSecondaryContainer) - return MaterialColors.harmonize(color, backgroundColor) - } - companion object { fun newInstance() = ToolsFragment() diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt index e2764ef5d..cbb17dd06 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt @@ -5,7 +5,6 @@ import androidx.lifecycle.asLiveData import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import kotlinx.coroutines.Dispatchers import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.github.AppUpdateRepository @@ -14,6 +13,7 @@ import org.koitharu.kotatsu.core.prefs.observeAsLiveData import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.settings.tools.model.StorageUsage +import javax.inject.Inject @HiltViewModel class ToolsViewModel @Inject constructor( @@ -25,7 +25,7 @@ class ToolsViewModel @Inject constructor( val appUpdate = appUpdateRepository.observeAvailableUpdate() .asLiveData(viewModelScope.coroutineContext) - val storageUsage: LiveData = liveData( + val storageUsage: LiveData = liveData( context = viewModelScope.coroutineContext + Dispatchers.Default, ) { emit(collectStorageUsage()) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt new file mode 100644 index 000000000..b144a8131 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt @@ -0,0 +1,77 @@ +package org.koitharu.kotatsu.settings.tools.views + +import android.content.Context +import android.content.res.ColorStateList +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import androidx.annotation.ColorInt +import androidx.annotation.StringRes +import androidx.core.graphics.ColorUtils +import androidx.core.widget.TextViewCompat +import com.google.android.material.color.MaterialColors +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.widgets.SegmentedBarView +import org.koitharu.kotatsu.databinding.LayoutMemoryUsageBinding +import org.koitharu.kotatsu.settings.tools.model.StorageUsage +import org.koitharu.kotatsu.utils.FileSize +import org.koitharu.kotatsu.utils.ext.getThemeColor + +class MemoryUsageView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : LinearLayout(context, attrs) { + + private val binding = LayoutMemoryUsageBinding.inflate(LayoutInflater.from(context), this) + private val labelPattern = context.getString(R.string.memory_usage_pattern) + + init { + orientation = VERTICAL + bind(null) + } + + fun setManageButtonOnClickListener(listener: OnClickListener?) { + binding.buttonManage.setOnClickListener(listener) + } + + fun bind(usage: StorageUsage?) { + val storageSegment = SegmentedBarView.Segment(usage?.savedManga?.percent ?: 0f, segmentColor(1)) + val pagesSegment = SegmentedBarView.Segment(usage?.pagesCache?.percent ?: 0f, segmentColor(2)) + val otherSegment = SegmentedBarView.Segment(usage?.otherCache?.percent ?: 0f, segmentColor(3)) + + with(binding) { + bar.segments = listOf(storageSegment, pagesSegment, otherSegment).filter { it.percent > 0f } + labelStorage.text = formatLabel(usage?.savedManga, R.string.saved_manga) + labelPagesCache.text = formatLabel(usage?.pagesCache, R.string.pages_cache) + labelOtherCache.text = formatLabel(usage?.otherCache, R.string.other_cache) + labelAvailable.text = formatLabel(usage?.available, R.string.available, R.string.available) + + TextViewCompat.setCompoundDrawableTintList(labelStorage, ColorStateList.valueOf(storageSegment.color)) + TextViewCompat.setCompoundDrawableTintList(labelPagesCache, ColorStateList.valueOf(pagesSegment.color)) + TextViewCompat.setCompoundDrawableTintList(labelOtherCache, ColorStateList.valueOf(otherSegment.color)) + } + } + + private fun formatLabel( + item: StorageUsage.Item?, + @StringRes labelResId: Int, + @StringRes emptyResId: Int = R.string.computing_, + ): String { + return if (item != null) { + labelPattern.format( + FileSize.BYTES.format(context, item.bytes), + context.getString(labelResId), + ) + } else { + context.getString(emptyResId) + } + } + + @ColorInt + private fun segmentColor(i: Int): Int { + val hue = (93.6f * i) % 360 + val color = ColorUtils.HSLToColor(floatArrayOf(hue, 0.4f, 0.6f)) + val backgroundColor = context.getThemeColor(com.google.android.material.R.attr.colorSecondaryContainer) + return MaterialColors.harmonize(color, backgroundColor) + } +} diff --git a/app/src/main/res/layout-w600dp/fragment_tools.xml b/app/src/main/res/layout-w600dp/fragment_tools.xml index 011d289af..6820ce01f 100644 --- a/app/src/main/res/layout-w600dp/fragment_tools.xml +++ b/app/src/main/res/layout-w600dp/fragment_tools.xml @@ -40,9 +40,8 @@ app:layout_constraintTop_toTopOf="parent" tools:visibility="visible" /> - - diff --git a/app/src/main/res/layout/layout_memory_usage.xml b/app/src/main/res/layout/layout_memory_usage.xml index 4a10caf3c..d03feaa4e 100644 --- a/app/src/main/res/layout/layout_memory_usage.xml +++ b/app/src/main/res/layout/layout_memory_usage.xml @@ -1,19 +1,19 @@ - + android:layout_height="wrap_content" + tools:ignore="RtlSymmetry" + tools:orientation="vertical" + tools:parentTag="android.widget.LinearLayout"> + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/screen_padding" + android:layout_marginTop="@dimen/margin_small"> @@ -44,49 +45,48 @@ style="@style/Widget.Kotatsu.TextView.Indicator" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginStart="@dimen/screen_padding" android:layout_marginTop="@dimen/margin_normal" android:layout_marginEnd="@dimen/screen_padding" android:text="@string/saved_manga" - android:visibility="gone" app:drawableStartCompat="@drawable/bg_circle" - tools:drawableTint="?colorPrimary" - tools:visibility="visible" /> + tools:drawableTint="?colorPrimary" /> + tools:drawableTint="?colorSecondary" /> + tools:drawableTint="?colorTertiary" /> - +