add no free space warning

pull/906/head
deniscerri 11 months ago
parent 98930837af
commit 84f13b1c86
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -22,6 +22,7 @@ import com.deniscerri.ytdl.ui.downloadcard.FormatSelectionBottomSheetDialog.Form
import com.deniscerri.ytdl.ui.downloadcard.FormatTuple
import com.deniscerri.ytdl.ui.downloadcard.MultipleItemFormatTuple
import com.deniscerri.ytdl.util.Extensions.isYoutubeURL
import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdl.util.FormatUtil
import com.deniscerri.ytdl.util.UiUtil
import com.google.android.material.snackbar.Snackbar
@ -30,11 +31,14 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.text.Normalizer.Form
import kotlin.text.compareTo
class FormatViewModel(private val application: Application) : AndroidViewModel(application) {
private val downloadRepository: DownloadRepository
@ -56,6 +60,9 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a
var sortBy = FormatSorting.valueOf(sharedPreferences.getString("format_order", "filesize")!!)
var filterBy = MutableStateFlow(FormatCategory.valueOf(sharedPreferences.getString("format_filter", "ALL")!!))
private val _noFreeSpace = MutableSharedFlow<String?>()
val noFreeSpace = _noFreeSpace.asSharedFlow()
init {
downloadRepository = DownloadRepository(DBManager.getInstance(application).downloadDao)
formats = combine(listOf(selectedItemsSharedFlow, filterBy)) { f ->
@ -245,4 +252,19 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a
return formatsToReturn
}
fun checkFreeSpace(size: Long, path: String) = viewModelScope.launch {
_noFreeSpace.emit(null)
if (size > 10L) {
File(FileUtil.formatPath(path)).apply {
if (size > this.freeSpace) {
val warningTxt = application.getString(R.string.no_free_space_warning) +
"\n" + "${application.getString(R.string.file_size)}:\t${FileUtil.convertFileSize(size)}" +
"\n" + "${application.getString(R.string.freespace)}:\t${FileUtil.convertFileSize(this.freeSpace)}"
_noFreeSpace.emit(warningTxt)
}
}
}
}
}

@ -45,6 +45,8 @@ import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
@ -227,12 +229,14 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
val chosenFormat = downloadItem.format
UiUtil.populateFormatCard(requireContext(), formatCard, chosenFormat, null, showSize = downloadItem.downloadSections.isEmpty())
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, chosenFormat, null, showSize = downloadItem.downloadSections.isEmpty())
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
val listener = object : OnFormatClickListener {
override fun onFormatClick(formatTuple: FormatTuple) {
formatTuple.format?.apply {
downloadItem.format = this
UiUtil.populateFormatCard(requireContext(), formatCard, this, null, showSize = downloadItem.downloadSections.isEmpty())
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, this, null, showSize = downloadItem.downloadSections.isEmpty())
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
}
@ -253,7 +257,8 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
val preferredFormat = downloadViewModel.getFormat(formats, Type.audio)
downloadItem.format = preferredFormat
downloadItem.allFormats = formats
UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, null, showSize = downloadItem.downloadSections.isEmpty())
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, null, showSize = downloadItem.downloadSections.isEmpty())
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
}
formatCard.setOnClickListener{
@ -359,7 +364,8 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
},
cutValueChanged = {
downloadItem.downloadSections = it
UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format, showSize = downloadItem.downloadSections.isEmpty())
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format, showSize = downloadItem.downloadSections.isEmpty())
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
if (it.isNotBlank()){
downloadItem.customFileNameTemplate = downloadItem.customFileNameTemplate.applyFilenameTemplateForCuts()
@ -392,6 +398,16 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
}
}
}
lifecycleScope.launch {
formatViewModel.noFreeSpace.collectLatest {
if (it != null) {
val snack = Snackbar.make(view, it, Snackbar.LENGTH_INDEFINITE)
snack.setTextMaxLines(10)
snack.show()
}
}
}
}
@SuppressLint("RestrictedApi")
@ -400,7 +416,8 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
formats.find { it.format_id == formatID }?.apply {
downloadItem.format = this
val formatCard = requireView().findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format, listOf(), showSize = downloadItem.downloadSections.isEmpty())
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format, listOf(), showSize = downloadItem.downloadSections.isEmpty())
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
}

@ -11,6 +11,7 @@ import android.graphics.Canvas
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.MenuItem
@ -71,6 +72,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.math.abs
@ -196,6 +198,16 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
}
}
lifecycleScope.launch {
formatViewModel.noFreeSpace.collectLatest {
if (it != null) {
val snack = Snackbar.make(view, it, Snackbar.LENGTH_INDEFINITE)
snack.setTextMaxLines(10)
snack.show()
}
}
}
lifecycleScope.launch {
downloadViewModel.processingDownloads.collectLatest { items ->
processingItemsCount = items.size
@ -1013,10 +1025,12 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
}
if (fileSizes.all { it > 5L }){
val size = FileUtil.convertFileSize(fileSizes.sum())
val filesizeRaw = fileSizes.sum()
val size = FileUtil.convertFileSize(filesizeRaw)
itemsFileSize = fileSizes.sum()
filesize.isVisible = size != "?" && !listAdapter.isCheckingItems()
filesize.text = "${getString(R.string.file_size)}: >~ $size"
formatViewModel.checkFreeSpace(filesizeRaw, Environment.getExternalStorageDirectory().path)
}else{
filesize.visibility = View.GONE
}

@ -46,6 +46,8 @@ import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
@ -244,14 +246,15 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
val chosenFormat = downloadItem.format
UiUtil.populateFormatCard(
val chosenAudioFormats = downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) }
val filesize = UiUtil.populateFormatCard(
requireContext(),
formatCard,
chosenFormat,
downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) },
chosenAudioFormats,
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
val listener = object : OnFormatClickListener {
override fun onFormatClick(formatTuple: FormatTuple) {
@ -262,10 +265,11 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
formatTuple.audioFormats?.map { it.format_id }?.let {
downloadItem.videoPreferences.audioFormatIDs.addAll(it)
}
UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format,
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format,
if(downloadItem.videoPreferences.removeAudio) listOf() else formatTuple.audioFormats,
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
override fun onFormatsUpdated(allFormats: List<Format>) {
@ -287,10 +291,11 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
val preferredAudioFormats = downloadViewModel.getPreferredAudioFormats(formats)
downloadItem.format = preferredFormat
downloadItem.allFormats = formats
UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat,
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat,
if(downloadItem.videoPreferences.removeAudio) listOf() else formats.filter { preferredAudioFormats.contains(it.format_id) },
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
}
@ -399,7 +404,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
},
cutValueChanged = {
downloadItem.downloadSections = it
UiUtil.populateFormatCard(
val filesize = UiUtil.populateFormatCard(
requireContext(),
formatCard,
downloadItem.format,
@ -407,6 +412,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
else downloadItem.allFormats.filter { f -> downloadItem.videoPreferences.audioFormatIDs.contains(f.format_id) },
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
if (it.isNotBlank()){
downloadItem.customFileNameTemplate = downloadItem.customFileNameTemplate.applyFilenameTemplateForCuts()
@ -428,13 +434,14 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
},
removeAudioClicked = {
downloadItem.videoPreferences.removeAudio = it
UiUtil.populateFormatCard(
val filesize = UiUtil.populateFormatCard(
requireContext(),
formatCard,
downloadItem.format,
if (it) listOf() else downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) },
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
},
recodeVideoClicked = {
downloadItem.videoPreferences.recodeVideo = it
@ -479,6 +486,16 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
}
}
}
lifecycleScope.launch {
formatViewModel.noFreeSpace.collectLatest {
if (it != null) {
val snack = Snackbar.make(view, it, Snackbar.LENGTH_INDEFINITE)
snack.setTextMaxLines(10)
snack.show()
}
}
}
}
override fun updateTitleAuthor(t: String, a: String){
@ -510,10 +527,11 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
downloadItem.videoPreferences.audioFormatIDs.clear()
downloadItem.videoPreferences.audioFormatIDs.addAll(arrayListOf(format.format_id))
val formatCard = requireView().findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format,
val filesize = UiUtil.populateFormatCard(requireContext(), formatCard, downloadItem.format,
if(downloadItem.videoPreferences.removeAudio) listOf() else listOf(format),
showSize = downloadItem.downloadSections.isEmpty()
)
formatViewModel.checkFreeSpace(filesize, downloadItem.downloadPath)
}
private var pathResultLauncher = registerForActivityResult(

@ -108,7 +108,8 @@ import java.util.Locale
object UiUtil {
@SuppressLint("SetTextI18n")
fun populateFormatCard(context: Context, formatCard : MaterialCardView, chosenFormat: Format, audioFormats: List<Format>? = null, showSize: Boolean = true){
//return filesize
fun populateFormatCard(context: Context, formatCard : MaterialCardView, chosenFormat: Format, audioFormats: List<Format>? = null, showSize: Boolean = true) : Long {
var formatNote = chosenFormat.format_note
if (formatNote.isEmpty()) formatNote = context.getString(R.string.defaultValue)
else if (formatNote == "best") formatNote = context.getString(R.string.best_quality)
@ -185,6 +186,12 @@ object UiUtil {
}
}
if (showSize) {
return filesize
}else {
return 0
}
}
fun populateCommandCard(card: MaterialCardView, item: CommandTemplate){

@ -485,4 +485,5 @@
<string name="no_keep_subs_summary">When using both Embed Subtitles and Write Subtitles, don\'t keep the subtitle files after embedding</string>
<string name="video_compatible">Compatible Video</string>
<string name="video_compatible_summary">Recodes the video making it compatible with other apps</string>
<string name="no_free_space_warning">There is no free space for this configuration.</string>
</resources>

Loading…
Cancel
Save