Update storage usage indicator

This commit is contained in:
Koitharu
2022-08-01 11:18:34 +03:00
parent 8b0f221eef
commit 523ee1e2a9
5 changed files with 92 additions and 21 deletions

View File

@@ -10,9 +10,11 @@ import android.view.ViewOutlineProvider
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import androidx.core.graphics.ColorUtils
import org.koitharu.kotatsu.parsers.util.replaceWith
import org.koitharu.kotatsu.utils.ext.resolveDp
import com.google.android.material.R as materialR
import kotlin.random.Random
import org.koitharu.kotatsu.parsers.util.replaceWith
import org.koitharu.kotatsu.utils.ext.getThemeColor
import org.koitharu.kotatsu.utils.ext.resolveDp
class SegmentedBarView @JvmOverloads constructor(
context: Context,
@@ -22,17 +24,20 @@ class SegmentedBarView @JvmOverloads constructor(
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val segmentsData = ArrayList<Segment>()
private val minSegmentSize = context.resources.resolveDp(3f)
private val segmentsSizes = ArrayList<Float>()
private val outlineColor = context.getThemeColor(materialR.attr.colorOutline)
private var cornerSize = 0f
var segments: List<Segment>
get() = segmentsData
set(value) {
segmentsData.replaceWith(value)
updateSizes()
invalidate()
}
init {
paint.style = Paint.Style.FILL
paint.strokeWidth = context.resources.resolveDp(1f)
outlineProvider = OutlineProvider()
clipToOutline = true
@@ -46,15 +51,44 @@ class SegmentedBarView @JvmOverloads constructor(
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
cornerSize = h / 2f
updateSizes()
}
override fun onDraw(canvas: Canvas) {
var x = 0f
val w = width.toFloat()
for (segment in segmentsData) {
paint.color = segment.color
val segmentWidth = (w * segment.percent).coerceAtLeast(minSegmentSize)
canvas.drawRect(x, 0f, x + segmentWidth, height.toFloat(), paint)
x += segmentWidth
if (segmentsSizes.isEmpty()) {
return
}
val w = width.toFloat()
var x = w - segmentsSizes.last()
for (i in (0 until segmentsData.size).reversed()) {
val segment = segmentsData[i]
paint.color = segment.color
paint.style = Paint.Style.FILL
val segmentWidth = segmentsSizes[i]
canvas.drawRoundRect(0f, 0f, x + cornerSize, height.toFloat(), cornerSize, cornerSize, paint)
paint.color = outlineColor
paint.style = Paint.Style.STROKE
canvas.drawRoundRect(0f, 0f, x + cornerSize, height.toFloat(), cornerSize, cornerSize, paint)
x -= segmentWidth
}
paint.color = outlineColor
paint.style = Paint.Style.STROKE
canvas.drawRoundRect(0f, 0f, w, height.toFloat(), cornerSize, cornerSize, paint)
}
private fun updateSizes() {
segmentsSizes.clear()
segmentsSizes.ensureCapacity(segmentsData.size + 1)
var w = width.toFloat()
for (segment in segmentsData) {
val segmentWidth = (w * segment.percent).coerceAtLeast(cornerSize)
segmentsSizes.add(segmentWidth)
w -= segmentWidth
}
segmentsSizes.add(w)
}
class Segment(
@@ -86,4 +120,4 @@ class SegmentedBarView @JvmOverloads constructor(
outline.setRoundRect(0, 0, view.width, view.height, view.height / 2f)
}
}
}
}

View File

@@ -4,9 +4,11 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat.startActivity
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.RecyclerView
import coil.ImageLoader
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
@@ -15,6 +17,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.reverseAsync
import org.koitharu.kotatsu.base.ui.BaseFragment
import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.databinding.FragmentLibraryBinding
@@ -34,6 +37,7 @@ import org.koitharu.kotatsu.utils.ext.getDisplayMessage
@AndroidEntryPoint
class LibraryFragment :
BaseFragment<FragmentLibraryBinding>(),
RecyclerViewOwner,
LibraryListEventListener {
@Inject
@@ -46,6 +50,9 @@ class LibraryFragment :
private var adapter: LibraryAdapter? = null
private var selectionController: SectionedSelectionController<LibrarySectionModel>? = null
override val recyclerView: RecyclerView
get() = binding.recyclerView
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): FragmentLibraryBinding {
return FragmentLibraryBinding.inflate(inflater, container, false)
}

View File

@@ -126,6 +126,7 @@ class SettingsActivity :
ACTION_READER -> ReaderSettingsFragment()
ACTION_SUGGESTIONS -> SuggestionsSettingsFragment()
ACTION_SHIKIMORI -> ShikimoriSettingsFragment()
ACTION_HISTORY -> HistorySettingsFragment()
ACTION_TRACKER -> TrackerSettingsFragment()
ACTION_SOURCE -> SourceSettingsFragment.newInstance(
intent.getSerializableExtra(EXTRA_SOURCE) as? MangaSource ?: MangaSource.LOCAL,
@@ -153,6 +154,7 @@ class SettingsActivity :
private const val ACTION_READER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_READER_SETTINGS"
private const val ACTION_SUGGESTIONS = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SUGGESTIONS"
private const val ACTION_TRACKER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_TRACKER"
private const val ACTION_HISTORY = "${BuildConfig.APPLICATION_ID}.action.MANAGE_HISTORY"
private const val ACTION_SOURCE = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCE_SETTINGS"
private const val ACTION_SHIKIMORI = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SHIKIMORI_SETTINGS"
private const val ACTION_MANAGE_SOURCES = "${BuildConfig.APPLICATION_ID}.action.MANAGE_SOURCES_LIST"
@@ -178,6 +180,10 @@ class SettingsActivity :
Intent(context, SettingsActivity::class.java)
.setAction(ACTION_TRACKER)
fun newHistorySettingsIntent(context: Context) =
Intent(context, SettingsActivity::class.java)
.setAction(ACTION_HISTORY)
fun newManageSourcesIntent(context: Context) =
Intent(context, SettingsActivity::class.java)
.setAction(ACTION_MANAGE_SOURCES)

View File

@@ -60,6 +60,7 @@ class ToolsFragment :
override fun onClick(v: View) {
when (v.id) {
R.id.button_settings -> startActivity(SettingsActivity.newIntent(v.context))
R.id.button_manage -> startActivity(SettingsActivity.newHistorySettingsIntent(v.context))
R.id.button_downloads -> startActivity(DownloadsActivity.newIntent(v.context))
R.id.button_download -> {
val url = viewModel.appUpdate.value?.apkUrl ?: return
@@ -98,6 +99,7 @@ class ToolsFragment :
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(
@@ -131,7 +133,7 @@ class ToolsFragment :
@ColorInt
private fun segmentColor(i: Int): Int {
val hue = (93.6f * i) % 360
val color = ColorUtils.HSLToColor(floatArrayOf(hue, 0.5f, 0.5f))
val color = ColorUtils.HSLToColor(floatArrayOf(hue, 0.4f, 0.6f))
val backgroundColor = requireContext().getThemeColor(materialR.attr.colorSecondaryContainer)
return MaterialColors.harmonize(color, backgroundColor)
}

View File

@@ -6,19 +6,36 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/screen_padding">
android:paddingStart="@dimen/screen_padding"
android:paddingTop="@dimen/margin_small"
android:paddingBottom="@dimen/screen_padding"
tools:ignore="RtlSymmetry">
<TextView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/storage_usage"
android:textAppearance="?textAppearanceTitleMedium" />
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/storage_usage"
android:textAppearance="?textAppearanceTitleMedium" />
<Button
android:id="@+id/button_manage"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/manage" />
</LinearLayout>
<org.koitharu.kotatsu.base.ui.widgets.SegmentedBarView
android:id="@+id/bar"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_marginVertical="@dimen/margin_normal"
android:layout_height="16dp"
android:layout_marginEnd="@dimen/screen_padding"
android:background="?colorSecondaryContainer" />
<TextView
@@ -26,6 +43,8 @@
style="@style/Widget.Kotatsu.TextView.Indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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"
@@ -38,6 +57,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_small"
android:layout_marginEnd="@dimen/screen_padding"
android:text="@string/pages_cache"
android:visibility="gone"
app:drawableStartCompat="@drawable/bg_circle"
@@ -50,6 +70,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_small"
android:layout_marginEnd="@dimen/screen_padding"
android:text="@string/other_cache"
android:visibility="gone"
app:drawableStartCompat="@drawable/bg_circle"
@@ -62,8 +83,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_small"
android:layout_marginEnd="@dimen/screen_padding"
android:text="@string/computing_"
app:drawableStartCompat="@drawable/bg_circle"
app:drawableTint="?colorSecondaryContainer" />
</LinearLayout>
</LinearLayout>