bug fixes

pull/1242/head
deniscerri 4 weeks ago
parent bf90b2aca3
commit 5cffd60e81
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -12,7 +12,7 @@ def properties = new Properties()
def versionMajor = 1
def versionMinor = 8
def versionPatch = 9
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
def versionBuild = 1 // bump for dogfood builds, public betas, etc.
//WHEN RELEASING BETA KEEP THE SAME VERSION AS LATEST STABLE, SO USERS CAN DOWNGRADE
def isBeta = false
@ -237,7 +237,7 @@ dependencies {
implementation 'com.google.accompanist:accompanist-webview:0.36.0'
implementation 'androidx.compose.material3:material3-android:1.4.0'
implementation "io.noties.markwon:core:4.6.2"
implementation("com.github.teamnewpipe:newpipeextractor:v0.26.3")
implementation("com.github.teamnewpipe:newpipeextractor:-SNAPSHOT")
implementation("commons-io:commons-io:2.5")
implementation("org.apache.commons:commons-compress:1.12")

@ -34,7 +34,6 @@
</queries>
<application
android:usesCleartextTraffic="true"
android:name=".App"
android:allowBackup="false"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|locale"

@ -65,13 +65,14 @@ class DownloadMultipleCardViewModel(application: Application) : AndroidViewModel
}
.flowOn(Dispatchers.Default)
private var currentPagingSource: PagingSource<Int, DownloadItemConfigureMultiple>? = null
val processingDownloads: Flow<PagingData<DownloadItemConfigureMultiple>> = Pager(
config = PagingConfig(
pageSize = 40,
enablePlaceholders = false,
initialLoadSize = 80
),
pagingSourceFactory = { dao.getProcessingDownloads() }
pagingSourceFactory = { dao.getProcessingDownloads().also { currentPagingSource = it } }
).flow.cachedIn(viewModelScope)
val processingIds: Flow<List<Long>> = dao.getProcessingDownloadsIds()
@ -90,4 +91,8 @@ class DownloadMultipleCardViewModel(application: Application) : AndroidViewModel
}
}.flowOn(Dispatchers.IO)
fun refreshProcessingDownloads() {
currentPagingSource?.invalidate()
}
}

@ -149,7 +149,7 @@ class HomeAdapter(onItemClickListener: OnItemClickListener, activity: Activity)
true
}
card.setOnClickListener {
if (checkedItems.isNotEmpty()) {
if (card.isChecked || checkedItems.isNotEmpty()) {
checkCard(card, video.id, video)
}else{
onItemClickListener.onCardDetailsClick(video)

@ -31,11 +31,15 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.children
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.media3.exoplayer.offline.Download
import androidx.navigation.fragment.findNavController
import androidx.paging.CombinedLoadStates
import androidx.paging.LoadState
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
@ -233,6 +237,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
processingItemsCount = ids.size
processingDownloadIDs = ids
count.text = "$processingItemsCount ${getString(R.string.selected)}"
downloadMultipleCardViewModel.refreshProcessingDownloads()
}
}

@ -74,6 +74,7 @@ class CropVideoBottomSheetDialog(
private lateinit var forwardBtn: MaterialButton
private lateinit var muteBtn: MaterialButton
private lateinit var resetBtn: Button
private lateinit var clearZoom: Button
private lateinit var okBtn: Button
private lateinit var xEditText: EditText
@ -157,6 +158,7 @@ class CropVideoBottomSheetDialog(
forwardBtn = view.findViewById(R.id.forward)
muteBtn = view.findViewById(R.id.mute)
resetBtn = view.findViewById(R.id.resetButton)
clearZoom = view.findViewById(R.id.clearZoom)
okBtn = view.findViewById(R.id.okButton)
xEditText = view.findViewById(R.id.crop_x_edittext)
@ -218,9 +220,23 @@ class CropVideoBottomSheetDialog(
}
resetBtn.isEnabled = item.videoPreferences.cropValues.isNotBlank()
val formatReference = item.allFormats.sortedByDescending { it.height }.firstOrNull {
(it.height ?: 0) > 0 && (it.width ?: 0) > 0
}
videoWidth = formatReference?.width ?: 0
videoHeight = formatReference?.height ?: 0
clearZoom.setOnClickListener {
listener?.onClearCrop()
ratioChipGroup.findViewById<Chip>(R.id.chip_free).performClick()
refreshTextInputs(0, 0, videoWidth, videoHeight)
applyVideoCoordsToOverlay(0, 0, videoWidth, videoHeight)
}
okBtn.setOnClickListener {
readTextFieldsToVideoCoords()?.let { (x, y, w, h) ->
listener?.onChangeCrop(x, y, w, h, videoWidth, videoHeight)
resetBtn.isEnabled = true
}
player.stop()
dismiss()
@ -245,11 +261,6 @@ class CropVideoBottomSheetDialog(
}
})
val formatReference = item.allFormats.sortedByDescending { it.height }.firstOrNull {
(it.height ?: 0) > 0 && (it.width ?: 0) > 0
}
videoWidth = formatReference?.width ?: 0
videoHeight = formatReference?.height ?: 0
showOverlayAndLoad()
videoView.setOnClickListener {

@ -153,13 +153,13 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
override fun onActionButtonClick(itemID: Long) {
lifecycleScope.launch {
runCatching {
actionMode?.finish()
val item = withContext(Dispatchers.IO){
downloadViewModel.getItemByID(itemID)
}
withContext(Dispatchers.IO){
downloadViewModel.queueDownloads(listOf(item), true)
}
actionMode?.finish()
}.onFailure {
Toast.makeText(requireContext(), getString(R.string.error_restarting_download), Toast.LENGTH_LONG).show()
}

@ -153,7 +153,6 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
override fun onActionButtonClick(itemID: Long) {
lifecycleScope.launch {
actionMode?.finish()
val item = withContext(Dispatchers.IO){
downloadViewModel.getItemByID(itemID)
}
@ -166,6 +165,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
bundle
)
}
actionMode?.finish()
}
}

@ -590,11 +590,10 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
lifecycleScope.launch {
actionMode?.finish()
val selectedObjects = getSelectedIDs()
historyAdapter.clearCheckedItems()
historyViewModel.deleteAllWithIDs(selectedObjects, deleteFile[0])
actionMode?.finish()
}
}
deleteDialog.show()
@ -602,22 +601,20 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
}
R.id.share -> {
lifecycleScope.launch {
actionMode?.finish()
val selectedObjects = getSelectedIDs()
val paths = withContext(Dispatchers.IO){
historyViewModel.getDownloadPathsFromIDs(selectedObjects)
}
FileUtil.shareFileIntent(requireContext(), paths.flatten())
historyAdapter.clearCheckedItems()
actionMode?.finish()
}
true
}
R.id.redownload -> {
lifecycleScope.launch {
val selectedObjects = getSelectedIDs()
actionMode?.finish()
historyAdapter.clearCheckedItems()
if (selectedObjects.size == 1) {
val tmp = withContext(Dispatchers.IO) {
@ -633,6 +630,7 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
Pair("ignore_duplicates", true)
))
}
actionMode?.finish()
}else {
val showDownloadCard = sharedPreferences.getBoolean("download_card", true)
downloadViewModel.turnHistoryItemsToProcessingDownloads(selectedObjects, downloadNow = !showDownloadCard)
@ -642,6 +640,7 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
bundle.putBoolean("ignore_duplicates", true)
findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundle)
}
actionMode?.finish()
}
}
true

@ -162,7 +162,6 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
override fun onActionButtonClick(itemID: Long) {
lifecycleScope.launch {
actionMode?.finish()
val item = withContext(Dispatchers.IO){
downloadViewModel.getItemByID(itemID)
@ -175,6 +174,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
}else{
Toast.makeText(requireContext(), getString(R.string.error_restarting_download), Toast.LENGTH_LONG).show()
}
actionMode?.finish()
}
}

@ -159,7 +159,6 @@ class ScheduledDownloadsFragment : Fragment(), ScheduledDownloadAdapter.OnItemCl
override fun onActionButtonClick(itemID: Long) {
lifecycleScope.launch {
actionMode?.finish()
runCatching {
withContext(Dispatchers.IO){
downloadViewModel.resetScheduleTimeForItemsAndStartDownload(listOf(itemID))
@ -167,6 +166,7 @@ class ScheduledDownloadsFragment : Fragment(), ScheduledDownloadAdapter.OnItemCl
}.onFailure {
Toast.makeText(requireContext(), it.message, Toast.LENGTH_LONG).show()
}
actionMode?.finish()
}
}

@ -1,5 +1,6 @@
package com.deniscerri.ytdl.util
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.media.MediaScannerConnection
@ -55,30 +56,29 @@ object FileUtil {
val file = File(path)
val uri = MediaStore.Files.getContentUri("external")
val selection: String
val selectionArgs: Array<String>
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val parentPath = file.parentFile?.absolutePath.orEmpty()
val primaryRoot = Environment.getExternalStorageDirectory().absolutePath
if (parentPath.startsWith(primaryRoot)) {
val trimmed = parentPath
.removePrefix(primaryRoot)
.removePrefix(File.separator)
val relativePath = if (trimmed.isEmpty()) "" else "$trimmed${File.separator}"
selection = MediaStore.MediaColumns.RELATIVE_PATH + " =? AND " +
MediaStore.MediaColumns.DISPLAY_NAME + " =?"
selectionArgs = arrayOf(relativePath, file.name)
} else {
// Non-primary storage: fall back to DATA query
selection = MediaStore.MediaColumns.DATA + " =?"
selectionArgs = arrayOf(file.absolutePath)
// Query by DATA first to find the exact MediaStore row ID, then delete by ID
val projection = arrayOf(MediaStore.MediaColumns._ID)
val selection = MediaStore.MediaColumns.DATA + " =?"
val selectionArgs = arrayOf(file.absolutePath)
val rowUri = contentResolver.query(uri, projection, selection, selectionArgs, null)
?.use { cursor ->
if (cursor.moveToFirst()) {
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
ContentUris.withAppendedId(uri, id)
} else null
}
if (rowUri != null) {
contentResolver.delete(rowUri, null, null)
}
} else {
selection = MediaStore.MediaColumns.DATA + " =?"
selectionArgs = arrayOf(file.absolutePath)
// Pre-Q: DATA column is reliable
val selection = MediaStore.MediaColumns.DATA + " =?"
val selectionArgs = arrayOf(file.absolutePath)
contentResolver.delete(uri, selection, selectionArgs)
}
contentResolver.delete(uri, selection, selectionArgs)
}
fun exists(path: String) : Boolean {

@ -96,16 +96,36 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/clearZoom"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:contentDescription="@string/reset"
android:layout_height="wrap_content"
app:icon="@drawable/baseline_delete_24"
app:iconSize="30dp"
app:iconTint="?android:colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton
android:id="@+id/rewind"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="40dp"
app:icon="@drawable/exomedia_ic_rewind_white"
app:iconSize="40dp"
android:layout_marginHorizontal="15dp"
app:iconTint="?android:colorAccent" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton
android:id="@+id/playpause"
style="@style/Widget.Material3.Button.IconButton"
@ -117,16 +137,24 @@
app:iconSize="40dp"
app:iconTint="?android:colorAccent" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton
android:id="@+id/forward"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
app:icon="@drawable/exomedia_ic_fast_forward_white"
app:iconSize="40dp"
android:layout_marginHorizontal="15dp"
app:iconTint="?android:colorAccent" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton
android:id="@+id/mute"
style="@style/Widget.Material3.Button.IconButton"

@ -23,6 +23,7 @@ buildscript {
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://central.sonatype.com/repository/maven-snapshots/' }
google()
}

Loading…
Cancel
Save