Skip to content

Commit

Permalink
[feature] Support for deleting cached torrent files
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Feb 22, 2024
1 parent d49ac67 commit b6bae13
Show file tree
Hide file tree
Showing 26 changed files with 676 additions and 25 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ android {
minSdk = 24
targetSdk = 34
versionCode = 4
versionName = "1.0-beta07"
versionName = "1.0-beta08"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
7 changes: 6 additions & 1 deletion app/src/main/java/com/skyd/anivu/ext/FileExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ import java.io.File

fun File.toUri(context: Context): Uri = FileProvider.getUriForFile(
context, "${context.packageName}.fileprovider", this
)
)

fun File.deleteRecursivelyExclude(hook: (File) -> Boolean = { true }): Boolean =
walkBottomUp().fold(true) { res, it ->
(it != this && hook(it) && (it.delete() || !it.exists())) && res
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.skyd.anivu.model.bean.settings

import android.graphics.drawable.Drawable
import com.skyd.anivu.base.BaseBean

data class SettingsBaseBean(
val title: String,
val description: String,
val icon: Drawable,
val action: ((SettingsBaseBean) -> Unit)? = null,
) : BaseBean
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.skyd.anivu.model.repository

import com.skyd.anivu.base.BaseRepository
import com.skyd.anivu.config.Const
import com.skyd.anivu.ext.deleteRecursivelyExclude
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject

class DataRepository @Inject constructor() : BaseRepository() {
fun requestClearCache(): Flow<Long> {
return flow {
var size: Long = 0
Const.TEMP_TORRENT_DIR.deleteRecursivelyExclude(hook = {
if (!it.canWrite()) return@deleteRecursivelyExclude false
if (it.isFile) size += it.length()
true
})
emit(size)
}.flowOn(Dispatchers.IO)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.navigation.NavDeepLinkBuilder
import androidx.work.CoroutineWorker
import androidx.work.ExistingWorkPolicy
Expand Down Expand Up @@ -289,7 +290,7 @@ class DownloadTorrentWorker(context: Context, parameters: WorkerParameters) :
.setContentTitle(title)
.setTicker(title)
.setContentText(progress.toPercentage())
.setSmallIcon(R.drawable.ic_icon_24)
.setSmallIcon(R.drawable.ic_icon_2_24)
.setOngoing(true)
.setProgress(100, (progress * 100).toInt(), false)
// Add the cancel action to the notification which can be used to cancel the worker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.skyd.anivu.databinding.ItemMedia1Binding
import com.skyd.anivu.databinding.ItemMore1Binding
import com.skyd.anivu.databinding.ItemOtherWorks1Binding
import com.skyd.anivu.databinding.ItemParentDir1Binding
import com.skyd.anivu.databinding.ItemSettingsBaseBinding

abstract class BaseViewHolder<V : ViewBinding>(val binding: V) :
RecyclerView.ViewHolder(binding.root)
Expand Down Expand Up @@ -43,3 +44,6 @@ class OtherWorks1ViewHolder(binding: ItemOtherWorks1Binding) :

class License1ViewHolder(binding: ItemLicense1Binding) :
BaseViewHolder<ItemLicense1Binding>(binding)

class SettingsBaseViewHolder(binding: ItemSettingsBaseBinding) :
BaseViewHolder<ItemSettingsBaseBinding>(binding)
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ class Media1Proxy(
cvMedia1Preview.visible()
ivMedia1Preview.setTag(R.id.image_view_tag_2, data.file.path)
coroutineScope.launch(Dispatchers.IO) {
retriever.setDataSource(data.file.path)
runCatching { retriever.setDataSource(data.file.path) }
.onFailure { return@launch }
val duration = retriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
?.toLongOrNull() ?: return@launch
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.skyd.anivu.ui.adapter.variety.proxy.settings


import android.view.LayoutInflater
import android.view.ViewGroup
import com.skyd.anivu.databinding.ItemSettingsBaseBinding
import com.skyd.anivu.model.bean.settings.SettingsBaseBean
import com.skyd.anivu.ui.adapter.variety.SettingsBaseViewHolder
import com.skyd.anivu.ui.adapter.variety.VarietyAdapter


class SettingsBaseProxy(
private val adapter: VarietyAdapter,
) :
VarietyAdapter.Proxy<SettingsBaseBean, ItemSettingsBaseBinding, SettingsBaseViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingsBaseViewHolder {
val holder = SettingsBaseViewHolder(
ItemSettingsBaseBinding
.inflate(LayoutInflater.from(parent.context), parent, false),
)
holder.itemView.setOnClickListener {
val data = adapter.dataList.getOrNull(holder.bindingAdapterPosition)
if (data !is SettingsBaseBean) return@setOnClickListener
data.action?.invoke(data)
}
return holder
}

override fun onBindViewHolder(
holder: SettingsBaseViewHolder,
data: SettingsBaseBean,
index: Int,
action: ((Any?) -> Unit)?
) {
holder.binding.apply {
tvSettingsBaseTitle.text = data.title
tvSettingsBaseDesc.text = data.description
ivSettingsBaseIcon.setImageDrawable(data.icon)
}
}
}
46 changes: 30 additions & 16 deletions app/src/main/java/com/skyd/anivu/ui/fragment/more/MoreFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,7 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>() {
super.onCreate(savedInstanceState)

adapter.apply {
dataList += mutableListOf(
MoreBean(
title = getString(R.string.about_fragment_name),
icon = AppCompatResources.getDrawable(
requireContext(),
R.drawable.ic_info_24
)!!,
iconTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorOnPrimary),
navigateId = R.id.action_to_about_fragment,
background = AppCompatResources.getDrawable(
requireContext(),
R.drawable.shape_clover
)!!,
backgroundTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorPrimary),
),
)
dataList += getMoreBeanList()
addProxy(More1Proxy(onClick = {
val data = dataList[it]
if (data is MoreBean) {
Expand All @@ -67,6 +52,35 @@ class MoreFragment : BaseFragment<FragmentMoreBinding>() {
rvMoreFragment.addInsetsByPadding(left = true, right = true)
}

private fun getMoreBeanList(): MutableList<MoreBean> {
return mutableListOf(
MoreBean(
title = getString(R.string.settings_fragment_name),
icon = AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_settings_24
)!!,
iconTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorOnPrimary),
navigateId = R.id.action_to_settings_fragment,
background = AppCompatResources.getDrawable(
requireContext(), R.drawable.shape_curly_corner
)!!,
backgroundTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorPrimary),
),
MoreBean(
title = getString(R.string.about_fragment_name),
icon = AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_info_24
)!!,
iconTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorOnSecondary),
navigateId = R.id.action_to_about_fragment,
background = AppCompatResources.getDrawable(
requireContext(), R.drawable.shape_clover
)!!,
backgroundTint = requireContext().getAttrColor(com.google.android.material.R.attr.colorSecondary),
),
)
}

override fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?) =
FragmentMoreBinding.inflate(inflater, container, false)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.skyd.anivu.ext.addInsetsByPadding
import com.skyd.anivu.ext.collectIn
import com.skyd.anivu.ext.gone
import com.skyd.anivu.ext.popBackStackWithLifecycle
import com.skyd.anivu.ext.showSoftKeyboard
import com.skyd.anivu.ext.startWith
import com.skyd.anivu.ext.visible
import com.skyd.anivu.ui.adapter.variety.AniSpanSize
Expand Down Expand Up @@ -91,11 +92,14 @@ class SearchFragment : BaseFragment<FragmentSearchBinding>() {

override fun FragmentSearchBinding.initView() {
tilSearchFragment.setStartIconOnClickListener { findNavController().popBackStackWithLifecycle() }
tilSearchFragment.editText?.setOnEditorActionListener { v, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
doSearch(v.text.toString())
true
} else false
tilSearchFragment.editText?.apply {
setOnEditorActionListener { v, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
doSearch(v.text.toString())
true
} else false
}
showSoftKeyboard(requireActivity().window)
}

rvSearchFragment.layoutManager = GridLayoutManager(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.skyd.anivu.ui.fragment.settings

import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.ViewCompat
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.skyd.anivu.R
import com.skyd.anivu.base.BaseFragment
import com.skyd.anivu.databinding.FragmentSettingsBinding
import com.skyd.anivu.ext.addInsetsByPadding
import com.skyd.anivu.ext.findMainNavController
import com.skyd.anivu.ext.popBackStackWithLifecycle
import com.skyd.anivu.model.bean.settings.SettingsBaseBean
import com.skyd.anivu.ui.adapter.variety.AniSpanSize
import com.skyd.anivu.ui.adapter.variety.VarietyAdapter
import com.skyd.anivu.ui.adapter.variety.proxy.settings.SettingsBaseProxy
import dagger.hilt.android.AndroidEntryPoint


@AndroidEntryPoint
class SettingsFragment : BaseFragment<FragmentSettingsBinding>() {
private val adapter = VarietyAdapter(mutableListOf()).apply {
addProxy(SettingsBaseProxy(adapter = this))
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

adapter.dataList = getSettingsList()
}

override fun FragmentSettingsBinding.initView() {
topAppBar.setNavigationOnClickListener { findNavController().popBackStackWithLifecycle() }

rvSettingsFragment.layoutManager = GridLayoutManager(
requireContext(),
AniSpanSize.MAX_SPAN_SIZE
).apply {
spanSizeLookup = AniSpanSize(adapter)
}
rvSettingsFragment.adapter = adapter
}

override fun FragmentSettingsBinding.setWindowInsets() {
ablSettingsFragment.addInsetsByPadding(top = true, left = true, right = true)
// Fix: https://github.com/material-components/material-components-android/issues/1310
ViewCompat.setOnApplyWindowInsetsListener(ctlSettingsFragment, null)
rvSettingsFragment.addInsetsByPadding(bottom = true, left = true, right = true)
}

private fun getSettingsList(): List<Any> = mutableListOf(
SettingsBaseBean(
title = getString(R.string.data_fragment_name),
description = getString(R.string.data_fragment_description),
icon = AppCompatResources.getDrawable(
requireContext(), R.drawable.ic_database_24
)!!,
action = { findMainNavController().navigate(R.id.action_to_data_fragment) }
),
)

override fun getViewBinding(inflater: LayoutInflater, container: ViewGroup?) =
FragmentSettingsBinding.inflate(inflater, container, false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.skyd.anivu.ui.fragment.settings.data

import com.skyd.anivu.base.mvi.MviSingleEvent

sealed interface DataEvent : MviSingleEvent {
sealed interface ClearCacheResultEvent : DataEvent {
data class Success(val msg: String) : ClearCacheResultEvent
data class Failed(val msg: String) : ClearCacheResultEvent
}
}
Loading

0 comments on commit b6bae13

Please sign in to comment.