Storage usage preference
parent
513aa1a285
commit
bc273bfb8f
@ -1,106 +0,0 @@
|
||||
package org.koitharu.kotatsu.settings.tools
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CompoundButton
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.viewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.github.AppVersion
|
||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.setChecked
|
||||
import org.koitharu.kotatsu.databinding.FragmentToolsBinding
|
||||
import org.koitharu.kotatsu.download.ui.list.DownloadsActivity
|
||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.settings.about.AppUpdateDialog
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ToolsFragment :
|
||||
BaseFragment<FragmentToolsBinding>(),
|
||||
CompoundButton.OnCheckedChangeListener,
|
||||
View.OnClickListener {
|
||||
|
||||
private val viewModel by viewModels<ToolsViewModel>()
|
||||
|
||||
override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentToolsBinding {
|
||||
return FragmentToolsBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewBindingCreated(binding: FragmentToolsBinding, savedInstanceState: Bundle?) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
binding.buttonSettings.setOnClickListener(this)
|
||||
binding.buttonDownloads.setOnClickListener(this)
|
||||
binding.cardUpdate.buttonChangelog.setOnClickListener(this)
|
||||
binding.cardUpdate.buttonDownload.setOnClickListener(this)
|
||||
binding.switchIncognito.setOnCheckedChangeListener(this)
|
||||
binding.memoryUsageView.setManageButtonOnClickListener(this)
|
||||
|
||||
binding.chart?.setDataChart(
|
||||
listOf(
|
||||
Pair(5, "Категория 1"),
|
||||
Pair(3, "Категория 2"),
|
||||
Pair(7, "Категория 3"),
|
||||
)
|
||||
)
|
||||
binding.chart?.startAnimation()
|
||||
|
||||
viewModel.isIncognitoModeEnabled.observe(viewLifecycleOwner) {
|
||||
binding.switchIncognito.setChecked(it, false)
|
||||
}
|
||||
viewModel.storageUsage.observe(viewLifecycleOwner) {
|
||||
binding.memoryUsageView.bind(it)
|
||||
}
|
||||
viewModel.appUpdate.observe(viewLifecycleOwner, ::onAppUpdateAvailable)
|
||||
}
|
||||
|
||||
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
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.data = url.toUri()
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.open_in_browser)))
|
||||
}
|
||||
|
||||
R.id.button_changelog -> {
|
||||
val version = viewModel.appUpdate.value ?: return
|
||||
AppUpdateDialog(v.context).show(version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCheckedChanged(button: CompoundButton?, isChecked: Boolean) {
|
||||
viewModel.toggleIncognitoMode(isChecked)
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) {
|
||||
requireViewBinding().root.updatePadding(
|
||||
bottom = insets.bottom,
|
||||
)
|
||||
}
|
||||
|
||||
private fun onAppUpdateAvailable(version: AppVersion?) {
|
||||
if (version == null) {
|
||||
requireViewBinding().cardUpdate.root.isVisible = false
|
||||
return
|
||||
}
|
||||
requireViewBinding().cardUpdate.textSecondary.text = getString(R.string.new_version_s, version.name)
|
||||
requireViewBinding().cardUpdate.root.isVisible = true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = ToolsFragment()
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package org.koitharu.kotatsu.settings.tools
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.github.AppUpdateRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
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(
|
||||
private val storageManager: LocalStorageManager,
|
||||
private val settings: AppSettings,
|
||||
appUpdateRepository: AppUpdateRepository,
|
||||
) : BaseViewModel() {
|
||||
|
||||
val appUpdate = appUpdateRepository.observeAvailableUpdate()
|
||||
|
||||
val storageUsage: StateFlow<StorageUsage?> = flow {
|
||||
emit(collectStorageUsage())
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null)
|
||||
|
||||
val isIncognitoModeEnabled = settings.observeAsStateFlow(
|
||||
scope = viewModelScope + Dispatchers.Default,
|
||||
key = AppSettings.KEY_INCOGNITO_MODE,
|
||||
valueProducer = { isIncognitoModeEnabled },
|
||||
)
|
||||
|
||||
fun toggleIncognitoMode(isEnabled: Boolean) {
|
||||
settings.isIncognitoModeEnabled = isEnabled
|
||||
}
|
||||
|
||||
private suspend fun collectStorageUsage(): StorageUsage {
|
||||
val pagesCacheSize = storageManager.computeCacheSize(CacheDir.PAGES)
|
||||
val otherCacheSize = storageManager.computeCacheSize() - pagesCacheSize
|
||||
val storageSize = storageManager.computeStorageSize()
|
||||
val availableSpace = storageManager.computeAvailableSize()
|
||||
val totalBytes = pagesCacheSize + otherCacheSize + storageSize + availableSpace
|
||||
return StorageUsage(
|
||||
savedManga = StorageUsage.Item(
|
||||
bytes = storageSize,
|
||||
percent = (storageSize.toDouble() / totalBytes).toFloat(),
|
||||
),
|
||||
pagesCache = StorageUsage.Item(
|
||||
bytes = pagesCacheSize,
|
||||
percent = (pagesCacheSize.toDouble() / totalBytes).toFloat(),
|
||||
),
|
||||
otherCache = StorageUsage.Item(
|
||||
bytes = otherCacheSize,
|
||||
percent = (otherCacheSize.toDouble() / totalBytes).toFloat(),
|
||||
),
|
||||
available = StorageUsage.Item(
|
||||
bytes = availableSpace,
|
||||
percent = (availableSpace.toDouble() / totalBytes).toFloat(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package org.koitharu.kotatsu.settings.tools.model
|
||||
|
||||
class StorageUsage(
|
||||
val savedManga: Item,
|
||||
val pagesCache: Item,
|
||||
val otherCache: Item,
|
||||
val available: Item,
|
||||
) {
|
||||
|
||||
class Item(
|
||||
val bytes: Long,
|
||||
val percent: Float,
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package org.koitharu.kotatsu.settings.userdata
|
||||
|
||||
class StorageUsage(
|
||||
val savedManga: Item,
|
||||
val pagesCache: Item,
|
||||
val otherCache: Item,
|
||||
val available: Item,
|
||||
) {
|
||||
|
||||
class Item(
|
||||
val bytes: Long,
|
||||
val percent: Float,
|
||||
) {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Item
|
||||
|
||||
if (bytes != other.bytes) return false
|
||||
return percent == other.percent
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = bytes.hashCode()
|
||||
result = 31 * result + percent.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as StorageUsage
|
||||
|
||||
if (savedManga != other.savedManga) return false
|
||||
if (pagesCache != other.pagesCache) return false
|
||||
if (otherCache != other.otherCache) return false
|
||||
return available == other.available
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = savedManga.hashCode()
|
||||
result = 31 * result + pagesCache.hashCode()
|
||||
result = 31 * result + otherCache.hashCode()
|
||||
result = 31 * result + available.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<include
|
||||
android:id="@+id/card_update"
|
||||
layout="@layout/layout_app_update"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_normal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<org.koitharu.kotatsu.settings.tools.views.MemoryUsageView
|
||||
android:id="@+id/memory_usage_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_incognito"
|
||||
style="?listItemTextViewStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?android:listPreferredItemHeightSmall"
|
||||
android:layout_marginTop="2dp"
|
||||
android:drawableStart="@drawable/ic_incognito"
|
||||
android:drawablePadding="?android:listPreferredItemPaddingStart"
|
||||
android:paddingStart="?android:listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
||||
android:text="@string/incognito_mode"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
android:textColor="?attr/colorControlNormal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@id/card_update"
|
||||
app:layout_goneMarginTop="8dp" />
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.ListItemTextView
|
||||
android:id="@+id/button_downloads"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?android:listPreferredItemHeightSmall"
|
||||
android:drawableStart="@drawable/ic_download"
|
||||
android:drawablePadding="?android:listPreferredItemPaddingStart"
|
||||
android:paddingStart="?android:listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
||||
android:text="@string/downloads"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@id/switch_incognito" />
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.ListItemTextView
|
||||
android:id="@+id/button_settings"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="?android:listPreferredItemHeightSmall"
|
||||
android:drawableStart="@drawable/ic_settings"
|
||||
android:drawablePadding="?android:listPreferredItemPaddingStart"
|
||||
android:paddingStart="?android:listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
||||
android:text="@string/settings"
|
||||
android:textAppearance="?attr/textAppearanceButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_downloads" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
Loading…
Reference in New Issue