diff --git a/app/build.gradle b/app/build.gradle index 5397aa1b..3a17bbe5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,13 +4,14 @@ plugins { id 'org.jetbrains.kotlin.android' id 'com.google.devtools.ksp' id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10" + id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10" } def properties = new Properties() def versionMajor = 1 def versionMinor = 6 def versionPatch = 8 -def versionBuild = 0 // bump for dogfood builds, public betas, etc. +def versionBuild = 1 // bump for dogfood builds, public betas, etc. def versionExt = "" if (versionBuild > 0){ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 51a85cf4..a3ab7031 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,6 +45,7 @@ android:name=".MainActivity" android:configChanges="locale" android:exported="true" + android:launchMode="singleTask" android:windowSoftInputMode="adjustPan"> @@ -53,6 +54,7 @@ android:configChanges="smallestScreenSize|layoutDirection|locale|orientation|screenSize" android:excludeFromRecents="true" android:exported="true" + android:launchMode="singleInstance" android:theme="@style/Theme.BottomSheet"> @@ -125,6 +127,7 @@ android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:configChanges="locale" + android:launchMode="singleTask" android:targetActivity=".MainActivity" android:windowSoftInputMode="adjustPan" android:exported="true"> @@ -147,6 +150,7 @@ android:icon="@mipmap/ic_launcher_dark" android:roundIcon="@mipmap/ic_launcher_round_dark" android:configChanges="locale" + android:launchMode="singleTask" android:targetActivity=".MainActivity" android:windowSoftInputMode="adjustPan"> @@ -167,6 +171,7 @@ android:icon="@mipmap/ic_launcher_light" android:roundIcon="@mipmap/ic_launcher_round_light" android:configChanges="locale" + android:launchMode="singleTask" android:targetActivity=".MainActivity" android:windowSoftInputMode="adjustPan"> @@ -184,6 +189,7 @@ android:name=".ui.more.WebViewActivity" android:configChanges="locale" android:exported="true" + android:launchMode="singleTask" android:parentActivityName=".MainActivity" android:windowSoftInputMode="adjustResize"> diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt index 6b9b3627..fd918e02 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt @@ -30,6 +30,7 @@ import androidx.fragment.app.FragmentContainerView import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController +import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.findNavController import androidx.navigation.ui.setupWithNavController @@ -48,6 +49,7 @@ import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdlnis.util.UpdateUtil import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.android.material.elevation.SurfaceColors import com.google.android.material.navigation.NavigationBarView import com.google.android.material.navigation.NavigationView import com.google.android.material.navigationrail.NavigationRailView @@ -82,6 +84,7 @@ class MainActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ThemeUtil.updateTheme(this) + window.navigationBarColor = SurfaceColors.SURFACE_2.getColor(this) setContentView(R.layout.activity_main) context = baseContext resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] @@ -362,8 +365,10 @@ class MainActivity : BaseActivity() { Toast.makeText(context, "Couldn't read file", Toast.LENGTH_LONG).show() return } - val bottomSheet = DownloadBottomSheetDialog(type = DownloadViewModel.Type.command, result = downloadViewModel.createEmptyResultItem(f.absolutePath)) - bottomSheet.show(supportFragmentManager, "downloadSingleSheet") + val bundle = Bundle() + bundle.putParcelable("result", downloadViewModel.createEmptyResultItem(f.absolutePath)) + bundle.putSerializable("type", DownloadViewModel.Type.command) + navController.navigate(R.id.downloadBottomSheetDialog, bundle) }else{ val `is` = contentResolver.openInputStream(uri!!) val textBuilder = StringBuilder() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt index 55539251..f39b0e81 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt @@ -13,10 +13,10 @@ interface DownloadDao { @Query("SELECT * FROM downloads ORDER BY status") fun getAllDownloads() : PagingSource - @Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'") + @Query("SELECT * FROM downloads WHERE status in ('Active', 'ActivePaused', 'PausedReQueued')") fun getActiveDownloads() : Flow> - @Query("SELECT COUNT(*) FROM downloads WHERE status='Active' or status='Paused'") + @Query("SELECT COUNT(*) FROM downloads WHERE status in ('Active', 'ActivePaused', 'PausedReQueued')") fun getActiveDownloadsCountFlow() : Flow @Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)") @@ -25,34 +25,34 @@ interface DownloadDao { @Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)") fun getDownloadsCountByStatus(status : List) : Int - @Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'") + @Query("SELECT * FROM downloads WHERE status in('Active','ActivePaused','PausedReQueued')") fun getActiveAndPausedDownloadsList() : List @Query("SELECT * FROM downloads WHERE status='Active'") fun getActiveDownloadsList() : List - @Query("SELECT * FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'") + @Query("SELECT * FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')") fun getActiveAndQueuedDownloadsList() : List - @Query("SELECT id FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'") + @Query("SELECT id FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')") fun getActiveAndQueuedDownloadIDs() : List - @Query("SELECT * FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'") + @Query("SELECT * FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')") fun getActiveAndQueuedDownloads() : Flow> - @Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id") + @Query("SELECT * FROM downloads WHERE status in('Queued','QueuedPaused') ORDER BY downloadStartTime, id") fun getQueuedDownloads() : PagingSource - @Query("SELECT format FROM downloads WHERE status='Queued' or status='QueuedPaused'") + @Query("SELECT format FROM downloads WHERE status in('Queued','QueuedPaused')") fun getSelectedFormatFromQueued() : List - @Query("SELECT * FROM downloads WHERE downloadStartTime <= :currentTime and status='Queued' ORDER BY downloadStartTime, id LIMIT 20") + @Query("SELECT * FROM downloads WHERE downloadStartTime <= :currentTime and status in ('Queued', 'PausedReQueued') ORDER BY downloadStartTime, id LIMIT 20") fun getQueuedDownloadsThatAreNotScheduledChunked(currentTime: Long) : Flow> - @Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' or status='Paused' ORDER BY downloadStartTime, id") + @Query("SELECT * FROM downloads WHERE status in ('Queued','QueuedPaused','ActivePaused','PausedReQueued') ORDER BY downloadStartTime, id") fun getQueuedAndPausedDownloads() : Flow> - @Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id") + @Query("SELECT * FROM downloads WHERE status in('Queued','QueuedPaused') ORDER BY downloadStartTime, id") fun getQueuedDownloadsList() : List @Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC") @@ -87,7 +87,7 @@ interface DownloadDao { @Query("UPDATE downloads " + "SET status = CASE " + - " WHEN status = 'Active' THEN 'Paused' " + + " WHEN status = 'Active' THEN 'ActivePaused' " + " WHEN status = 'Queued' THEN 'QueuedPaused' " + " ELSE status " + " END;") @@ -95,7 +95,7 @@ interface DownloadDao { @Query("UPDATE downloads " + "SET status = CASE " + - " WHEN status = 'Paused' THEN 'Active' " + + " WHEN status = 'ActivePaused' THEN 'Active' " + " WHEN status = 'QueuedPaused' THEN 'Queued' " + " ELSE status " + " END;") @@ -125,7 +125,7 @@ interface DownloadDao { @Query("DELETE FROM downloads WHERE id in (:list)") suspend fun deleteAllWithIDs(list: List) - @Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued' or status='QueuedPaused' or status='Active' or status='Paused'") + @Query("UPDATE downloads SET status='Cancelled' WHERE status in('Queued','QueuedPaused','Active','ActivePaused','PausedReQueued')") suspend fun cancelActiveQueued() @Query("DELETE FROM downloads WHERE status='Processing' AND id=:id") diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/AudioPreferences.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/AudioPreferences.kt index db6f1697..2a562f9a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/AudioPreferences.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/AudioPreferences.kt @@ -1,7 +1,11 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class AudioPreferences( var embedThumb: Boolean = true, var splitByChapters: Boolean = false, var sponsorBlockFilters: ArrayList = arrayListOf() -) +) : Parcelable diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ChapterItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ChapterItem.kt index 50560666..2cfa0904 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ChapterItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ChapterItem.kt @@ -1,7 +1,10 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable import com.google.gson.annotations.SerializedName +import kotlinx.parcelize.Parcelize +@Parcelize data class ChapterItem( @SerializedName(value = "start_time") var start_time: Long, @@ -9,4 +12,4 @@ data class ChapterItem( var end_time: Long, @SerializedName(value = "title") var title: String, -) \ No newline at end of file +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt index 4b29f743..6fde4cbc 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt @@ -1,11 +1,14 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel +import kotlinx.parcelize.Parcelize @Entity(tableName = "downloads") +@Parcelize data class DownloadItem( @PrimaryKey(autoGenerate = true) var id: Long, @@ -24,7 +27,7 @@ data class DownloadItem( var downloadPath: String, var website: String, val downloadSize: String, - val playlistTitle: String, + var playlistTitle: String, val audioPreferences : AudioPreferences, val videoPreferences: VideoPreferences, @ColumnInfo(defaultValue = "") @@ -36,4 +39,4 @@ data class DownloadItem( @ColumnInfo(defaultValue = "0") var downloadStartTime: Long, var logID: Long? -) \ No newline at end of file +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt index 12bec0ad..5620f738 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/Format.kt @@ -1,7 +1,10 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable import com.google.gson.annotations.SerializedName +import kotlinx.parcelize.Parcelize +@Parcelize data class Format( @SerializedName(value = "format_id", alternate = ["itag"]) var format_id: String = "", @@ -23,4 +26,4 @@ data class Format( var asr: String? = "", @SerializedName(value = "url") var url: String? = "" -) \ No newline at end of file +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt index 4da30423..35d0ed95 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt @@ -1,10 +1,13 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import kotlinx.parcelize.Parcelize @Entity(tableName = "results") +@Parcelize data class ResultItem( @PrimaryKey(autoGenerate = true) var id: Long, @@ -20,4 +23,4 @@ data class ResultItem( var urls: String, var chapters: MutableList?, var creationTime: Long = System.currentTimeMillis() / 1000, -) \ No newline at end of file +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/VideoPreferences.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/VideoPreferences.kt index 3661993a..3b2217fe 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/VideoPreferences.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/VideoPreferences.kt @@ -1,5 +1,9 @@ package com.deniscerri.ytdlnis.database.models +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class VideoPreferences ( var embedSubs: Boolean = true, var addChapters: Boolean = true, @@ -9,4 +13,4 @@ data class VideoPreferences ( var subsLanguages: String = "en.*,.*-orig", var audioFormatIDs : ArrayList = arrayListOf(), var removeAudio: Boolean = false -) +) : Parcelable diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt index f8dd8f15..3cee20a1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt @@ -37,7 +37,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) { val activeDownloadsCount : Flow = downloadDao.getActiveDownloadsCountFlow() enum class Status { - Active, Paused, Queued, QueuedPaused, Error, Cancelled, Saved + Active, ActivePaused, PausedReQueued, Queued, QueuedPaused, Error, Cancelled, Saved } suspend fun insert(item: DownloadItem) : Long { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt index df91c15e..7e8f4b6b 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt @@ -612,7 +612,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application } items.forEach { - if (it.status != DownloadRepository.Status.Paused.toString()) it.status = DownloadRepository.Status.Queued.toString() + if (it.status != DownloadRepository.Status.ActivePaused.toString()) it.status = DownloadRepository.Status.Queued.toString() val currentCommand = infoUtil.buildYoutubeDLRequest(it) val parsedCurrentCommand = infoUtil.parseYTDLRequestString(currentCommand) val existingDownload = activeAndQueuedDownloads.firstOrNull{d -> @@ -640,7 +640,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application existing.add(it) }else{ if (it.id == 0L){ - val id = withContext(Dispatchers.IO){ + val id = runBlocking { repository.insert(it) } it.id = id @@ -665,6 +665,13 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application } } + if (items.any { it.playlistTitle.isEmpty() }){ + items.forEachIndexed { index, it -> it.playlistTitle = "Various[${index+1}]" } + withContext(Dispatchers.IO){ + dao.updateMultiple(items) + } + } + if (!useScheduler || alarmScheduler.isDuringTheScheduledTime() || items.any { it.downloadStartTime > 0L } ){ startDownloadWorker(queuedItems) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/PauseDownloadNotificationReceiver.kt b/app/src/main/java/com/deniscerri/ytdlnis/receiver/PauseDownloadNotificationReceiver.kt index 756de36e..4d2a778a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/PauseDownloadNotificationReceiver.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/PauseDownloadNotificationReceiver.kt @@ -25,7 +25,7 @@ class PauseDownloadNotificationReceiver : BroadcastReceiver() { CoroutineScope(Dispatchers.IO).launch{ runCatching { val item = dbManager.downloadDao.getDownloadById(id.toLong()) - item.status = DownloadRepository.Status.Paused.toString() + item.status = DownloadRepository.Status.ActivePaused.toString() dbManager.downloadDao.update(item) } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt index 217d87d3..2ec6fc5c 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt @@ -1,6 +1,7 @@ package com.deniscerri.ytdlnis.receiver import android.Manifest +import android.content.ComponentName import android.content.Context import android.content.DialogInterface import android.content.Intent @@ -16,10 +17,16 @@ import android.util.Log import android.util.Patterns import android.view.WindowManager import androidx.core.app.ActivityCompat +import androidx.core.content.IntentSanitizer import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavController +import androidx.navigation.NavDestination +import androidx.navigation.findNavController +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.R @@ -34,6 +41,7 @@ import com.deniscerri.ytdlnis.ui.downloadcard.SelectPlaylistItemsDialog import com.deniscerri.ytdlnis.util.ThemeUtil import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlin.properties.Delegates @@ -46,6 +54,7 @@ class ShareActivity : BaseActivity() { private lateinit var downloadViewModel: DownloadViewModel private lateinit var cookieViewModel: CookieViewModel private lateinit var sharedPreferences: SharedPreferences + private lateinit var navController: NavController private var quickDownload by Delegates.notNull() @@ -83,6 +92,28 @@ class ShareActivity : BaseActivity() { handleIntents(intent) } + override fun onResume() { + super.onResume() + navController.addOnDestinationChangedListener(object: NavController.OnDestinationChangedListener{ + override fun onDestinationChanged( + controller: NavController, + destination: NavDestination, + arguments: Bundle? + ) { + if (navController.currentBackStack.value.isEmpty()) return + navController.removeOnDestinationChangedListener(this) + lifecycleScope.launch { + navController.currentBackStack.collectLatest { + if (it.isEmpty()){ + this@ShareActivity.finish() + } + } + } + + } + }) + } + override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleIntents(intent) @@ -91,6 +122,9 @@ class ShareActivity : BaseActivity() { private fun handleIntents(intent: Intent) { askPermissions() + val navHostFragment = supportFragmentManager.findFragmentById(R.id.frame_layout) as NavHostFragment + navController = navHostFragment.findNavController() + val action = intent.action Log.e("aa", intent.toString()) if (Intent.ACTION_SEND == action || Intent.ACTION_VIEW == action) { @@ -129,10 +163,10 @@ class ShareActivity : BaseActivity() { } val downloadType = DownloadViewModel.Type.valueOf(type ?: downloadViewModel.getDownloadType(url = result.url).toString()) if (sharedPreferences.getBoolean("download_card", true) && !background){ - val bottomSheet = DownloadBottomSheetDialog( - result = result, - type = downloadType) - bottomSheet.show(supportFragmentManager, "downloadSingleSheet") + val bundle = Bundle() + bundle.putParcelable("result", result) + bundle.putSerializable("type", downloadType) + navController.setGraph(R.navigation.share_nav_graph, bundle) }else{ lifecycleScope.launch(Dispatchers.IO){ val downloadItem = downloadViewModel.createDownloadItemFromResult( @@ -152,32 +186,6 @@ class ShareActivity : BaseActivity() { } } - private fun showDownloadSheet(it: ResultItem){ - - } - - private fun showSelectPlaylistItems(it: List){ - if (sharedPreferences.getBoolean("download_card", true)){ - val bottomSheet = SelectPlaylistItemsDialog(it, DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)) - bottomSheet.show(supportFragmentManager, "downloadPlaylistSheet") - }else{ - lifecycleScope.launch(Dispatchers.IO){ - val downloadItems = mutableListOf() - lifecycleScope.launch(Dispatchers.IO){ - it.forEach { res -> - val i = downloadViewModel.createDownloadItemFromResult( - result = res!!, - givenType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)) - i.format = downloadViewModel.getLatestCommandTemplateAsFormat() - downloadItems.add(i) - } - downloadViewModel.queueDownloads(downloadItems) - } - } - this.finish() - } - } - private fun askPermissions() { val permissions = arrayListOf() if (!checkFilePermission()) { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt index 654a185b..6882f1a5 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -20,12 +20,14 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode import androidx.constraintlayout.widget.ConstraintLayout import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.os.bundleOf import androidx.core.view.children import androidx.core.view.forEach import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -158,28 +160,30 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene recyclerView?.enableFastScroll() resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] - resultViewModel.items.observe(viewLifecycleOwner) { - homeAdapter!!.submitList(it) - resultsList = it - if(resultViewModel.repository.itemCount.value > 1 || resultViewModel.repository.itemCount.value == -1){ - if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && !loadingItems){ - downloadAllFabCoordinator!!.visibility = VISIBLE + resultViewModel.items.observe(requireActivity()) { + kotlin.runCatching { + homeAdapter!!.submitList(it) + resultsList = it + if(resultViewModel.repository.itemCount.value > 1 || resultViewModel.repository.itemCount.value == -1){ + if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && !loadingItems){ + downloadAllFabCoordinator!!.visibility = VISIBLE + }else{ + downloadAllFabCoordinator!!.visibility = GONE + } + }else if (resultViewModel.repository.itemCount.value == 1){ + if (sharedPreferences!!.getBoolean("download_card", true)){ + if(it.size == 1 && quickLaunchSheet && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){ + showSingleDownloadSheet( + it[0], + DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) + ) + } + } }else{ downloadAllFabCoordinator!!.visibility = GONE } - }else if (resultViewModel.repository.itemCount.value == 1){ - if (sharedPreferences!!.getBoolean("download_card", true)){ - if(it.size == 1 && quickLaunchSheet && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){ - showSingleDownloadSheet( - it[0], - DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) - ) - } - } - }else{ - downloadAllFabCoordinator!!.visibility = GONE + quickLaunchSheet = true } - quickLaunchSheet = true } initMenu() @@ -271,8 +275,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene ids?.forEach { items.add(downloadViewModel.getItemByID(it)) } - val bottomSheet = DownloadMultipleBottomSheetDialog(items.toMutableList()) - bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") + findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf( + Pair("downloads", items) + )) } } @@ -560,20 +565,18 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene if(sharedPreferences!!.getBoolean("quick_download", false) || sharedPreferences!!.getString("preferred_download_type", "video") == "command"){ if (queryList.size == 1 && Patterns.WEB_URL.matcher(queryList.first()).matches()){ if (sharedPreferences!!.getBoolean("download_card", true)) { - showSingleDownloadSheet( - resultItem = downloadViewModel.createEmptyResultItem(queryList.first()), - type = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) - ) - } else { - lifecycleScope.launch{ - val downloadItem = withContext(Dispatchers.IO){ - downloadViewModel.createDownloadItemFromResult( - result = downloadViewModel.createEmptyResultItem(queryList.first()), - givenType = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) - ) - } - downloadViewModel.queueDownloads(listOf(downloadItem)) + withContext(Dispatchers.Main){ + showSingleDownloadSheet( + resultItem = downloadViewModel.createEmptyResultItem(queryList.first()), + type = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) + ) } + } else { + val downloadItem = downloadViewModel.createDownloadItemFromResult( + result = downloadViewModel.createEmptyResultItem(queryList.first()), + givenType = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!) + ) + downloadViewModel.queueDownloads(listOf(downloadItem)) } }else{ @@ -620,8 +623,13 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene resultItem: ResultItem, type: DownloadViewModel.Type ){ - val bottomSheet = DownloadBottomSheetDialog(resultItem, downloadViewModel.getDownloadType(type, resultItem.url)) - bottomSheet.show(parentFragmentManager, "downloadSingleSheet") + if(findNavController().currentBackStack.value.firstOrNull {it.destination.id == R.id.downloadBottomSheetDialog} == null){ + //show the fragment if its not in the backstack + val bundle = Bundle() + bundle.putParcelable("result", resultItem) + bundle.putSerializable("type", downloadViewModel.getDownloadType(type, resultItem.url)) + findNavController().navigate(R.id.downloadBottomSheetDialog, bundle) + } } override fun onCardClick(videoURL: String, add: Boolean) { @@ -646,8 +654,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene override fun onCardDetailsClick(videoURL: String) { if (parentFragmentManager.findFragmentByTag("resultDetails") == null && resultsList != null && resultsList!!.isNotEmpty()){ - val bottomSheet = ResultCardDetailsDialog(resultsList!!.first{it!!.url == videoURL}!!) - bottomSheet.show(parentFragmentManager, "cutVideoSheet") + val bundle = Bundle() + bundle.putParcelable("result", resultsList!!.first{it!!.url == videoURL}!!) + findNavController().navigate(R.id.resultCardDetailsDialog, bundle) } } @@ -662,8 +671,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene downloadViewModel.turnResultItemsToDownloadItems(resultsList!!) } if (sharedPreferences!!.getBoolean("download_card", true)) { - val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList()) - bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") + findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf( + Pair("downloads", downloadList) + )) } else { downloadViewModel.queueDownloads(downloadList) } @@ -723,8 +733,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene } if (sharedPreferences!!.getBoolean("download_card", true)) { - val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList()) - bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") + findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf( + Pair("downloads", downloadList) + )) } else { downloadViewModel.queueDownloads(downloadList) } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadAdapter.kt index f528c307..8deaa5a6 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadAdapter.kt @@ -133,25 +133,37 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null) cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)} - if (item.status == DownloadRepository.Status.Paused.toString()){ - progressBar.isIndeterminate = false - pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white) - pauseButton.tag = ActiveDownloadAction.Resume - cancelButton.visibility = View.VISIBLE - }else{ - progressBar.isIndeterminate = true - pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white) - cancelButton.visibility = View.GONE - pauseButton.tag = ActiveDownloadAction.Pause + + when(DownloadRepository.Status.valueOf(item.status)){ + DownloadRepository.Status.Active -> { + progressBar.isIndeterminate = true + pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white) + cancelButton.visibility = View.GONE + pauseButton.isEnabled = true + pauseButton.tag = ActiveDownloadAction.Pause + } + DownloadRepository.Status.ActivePaused -> { + progressBar.isIndeterminate = false + pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white) + pauseButton.tag = ActiveDownloadAction.Resume + pauseButton.isEnabled = true + cancelButton.visibility = View.VISIBLE + } + DownloadRepository.Status.PausedReQueued -> { + progressBar.isIndeterminate = true + pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.ic_refresh) + pauseButton.tag = null + pauseButton.isEnabled = false + cancelButton.visibility = View.GONE + } + else -> {} } pauseButton.setOnClickListener { if (pauseButton.tag == ActiveDownloadAction.Pause){ onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Pause, position) - }else{ onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Resume, position) - } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadMinifiedAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadMinifiedAdapter.kt index c3c22e37..95756b2b 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadMinifiedAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/adapter/ActiveDownloadMinifiedAdapter.kt @@ -116,7 +116,7 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null) cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)} - if (item.status == DownloadRepository.Status.Paused.toString()){ + if (item.status == DownloadRepository.Status.ActivePaused.toString()){ progressBar.isIndeterminate = false pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white) pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt index 3eeb6e73..28bc98da 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt @@ -5,8 +5,8 @@ import android.app.Dialog import android.content.DialogInterface import android.content.SharedPreferences import android.content.res.Configuration +import android.os.Build import android.os.Bundle -import android.os.Looper import android.text.format.DateFormat import android.util.DisplayMetrics import android.util.Patterns @@ -17,13 +17,16 @@ import android.widget.Button import android.widget.LinearLayout import android.widget.Toast import androidx.core.content.edit +import androidx.core.os.bundleOf import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavController +import androidx.navigation.NavDestination +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.afollestad.materialdialogs.utils.MDUtil.getStringArray -import com.deniscerri.ytdlnis.MainActivity import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao @@ -44,14 +47,20 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.tabs.TabLayout -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.text.SimpleDateFormat -import java.util.* +import java.util.Locale -class DownloadBottomSheetDialog(private var result: ResultItem, private val type: Type, private var currentDownloadItem: DownloadItem? = null) : BottomSheetDialogFragment() { +class DownloadBottomSheetDialog : BottomSheetDialogFragment() { private lateinit var tabLayout: TabLayout private lateinit var viewPager2: ViewPager2 private lateinit var fragmentAdapter : DownloadFragmentAdapter @@ -64,6 +73,18 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type private lateinit var sharedPreferences : SharedPreferences private lateinit var updateItem : Button private lateinit var view: View + private lateinit var shimmerLoading :ShimmerFrameLayout + private lateinit var title : View + private lateinit var shimmerLoadingSubtitle : ShimmerFrameLayout + private lateinit var subtitle : View + + private var updateJob : Job? = null + private var updateFormatsJob : Job? = null + + + private lateinit var result: ResultItem + private lateinit var type: Type + private var currentDownloadItem: DownloadItem? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -81,6 +102,26 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type view = LayoutInflater.from(context).inflate(R.layout.download_bottom_sheet, null) dialog.setContentView(view) + if (Build.VERSION.SDK_INT >= 33){ + arguments?.getParcelable("result", ResultItem::class.java) + }else{ + arguments?.getParcelable("result") + }.apply { + if (this == null){ + dismiss() + return + }else{ + result = this + } + } + + type = arguments?.getSerializable("type") as Type + currentDownloadItem = if (Build.VERSION.SDK_INT >= 33){ + arguments?.getParcelable("downloadItem", DownloadItem::class.java) + }else{ + arguments?.getParcelable("downloadItem") + } + dialog.setOnShowListener { behavior = BottomSheetBehavior.from(view.parent as View) val displayMetrics = DisplayMetrics() @@ -95,6 +136,13 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type viewPager2 = view.findViewById(R.id.download_viewpager) updateItem = view.findViewById(R.id.update_item) + + //loading shimmers + shimmerLoading = view.findViewById(R.id.shimmer_loading_title) + title = view.findViewById(R.id.bottom_sheet_title) + shimmerLoadingSubtitle = view.findViewById(R.id.shimmer_loading_subtitle) + subtitle = view.findViewById(R.id.bottom_sheet_subtitle) + (viewPager2.getChildAt(0) as? RecyclerView)?.apply { isNestedScrollingEnabled = false overScrollMode = View.OVER_SCROLL_NEVER @@ -224,6 +272,8 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type scheduleBtn.setOnClickListener{ UiUtil.showDatePicker(fragmentManager) { + updateJob?.cancel() + updateFormatsJob?.cancel() scheduleBtn.isEnabled = false download.isEnabled = false val item: DownloadItem = getDownloadItem() @@ -237,6 +287,8 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type } } download!!.setOnClickListener { + updateJob?.cancel() + updateFormatsJob?.cancel() scheduleBtn.isEnabled = false download.isEnabled = false val item: DownloadItem = getDownloadItem() @@ -285,7 +337,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type (updateItem.parent as LinearLayout).visibility = View.VISIBLE updateItem.setOnClickListener { (updateItem.parent as LinearLayout).visibility = View.GONE - initUpdateData(view) + initUpdateData() } } }else{ @@ -300,7 +352,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type //update in the background if there is no data if(result.title.isEmpty() && currentDownloadItem == null && !sharedPreferences.getBoolean("quick_download", false) && type != Type.command){ - initUpdateData(view) + initUpdateData() }else { val usingGenericFormatsOrEmpty = result.formats.isEmpty() || result.formats.any { it.format_note.contains("ytdlnisgeneric") } if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false) && !sharedPreferences.getBoolean("quick_download", false)){ @@ -377,97 +429,97 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type } } - private fun initUpdateData(v: View){ - val shimmerLoading = v.findViewById(R.id.shimmer_loading_title) - val title = v.findViewById(R.id.bottom_sheet_title) - val shimmerLoadingSubtitle = v.findViewById(R.id.shimmer_loading_subtitle) - val subtitle = v.findViewById(R.id.bottom_sheet_subtitle) - - val updateJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){ - withContext(Dispatchers.Main){ - title.visibility = View.GONE - subtitle.visibility = View.GONE - shimmerLoading.visibility = View.VISIBLE - shimmerLoadingSubtitle.visibility = View.VISIBLE - shimmerLoading.startShimmer() - shimmerLoadingSubtitle.startShimmer() - } + private fun initUpdateData() { + updateJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){ + findNavController().saveState() + kotlin.runCatching { + withContext(Dispatchers.Main){ + title.visibility = View.GONE + subtitle.visibility = View.GONE + shimmerLoading.visibility = View.VISIBLE + shimmerLoadingSubtitle.visibility = View.VISIBLE + shimmerLoading.startShimmer() + shimmerLoadingSubtitle.startShimmer() + } + if (result.url.isBlank()){ + withContext(Dispatchers.Main){dismiss()} + return@launch + } - if (result.url.isBlank()){ - withContext(Dispatchers.Main){dismiss()} - return@launch - } + val result = resultViewModel.parseQueries(listOf(result.url)) + if (result.isEmpty()){ + return@launch + } - val result = resultViewModel.parseQueries(listOf(result.url)) - if (result.isEmpty()){ - return@launch - } + if (result.size == 1 && result[0] != null){ + fragmentAdapter.setResultItem(result[0]!!) + withContext(Dispatchers.Main){ + runCatching { + val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment + f.updateUI(result[0]) + } - if (result.size == 1 && result[0] != null){ - fragmentAdapter.setResultItem(result[0]!!) - withContext(Dispatchers.Main){ - runCatching { - val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment - f.updateUI(result[0]) + runCatching { + val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment + f1.updateUI(result[0]) + } } - runCatching { - val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment - f1.updateUI(result[0]) + withContext(Dispatchers.Main){ + title.visibility = View.VISIBLE + subtitle.visibility = View.VISIBLE + shimmerLoading.visibility = View.GONE + shimmerLoadingSubtitle.visibility = View.GONE + shimmerLoading.stopShimmer() + shimmerLoadingSubtitle.stopShimmer() } - } - withContext(Dispatchers.Main){ - title.visibility = View.VISIBLE - subtitle.visibility = View.VISIBLE - shimmerLoading.visibility = View.GONE - shimmerLoadingSubtitle.visibility = View.GONE - shimmerLoading.stopShimmer() - shimmerLoadingSubtitle.stopShimmer() - } + val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") } - val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") } + if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){ + initUpdateFormats(result[0]!!.url) + } else { - if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){ - initUpdateFormats(result[0]!!.url) - } + } - }else{ - //open multi download card instead - if (activity is ShareActivity){ - val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!) - withContext(Dispatchers.Main){ - val playlistSelect = SelectPlaylistItemsDialog(items = result, type = preferredType) - parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment -> - dismiss() + }else{ + //open multi download card instead + if (activity is ShareActivity){ + val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!) + withContext(Dispatchers.Main){ + findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf( + Pair("results", result), + Pair("type", preferredType), + )) } - playlistSelect.show(parentFragmentManager, "downloadPlaylistSheet") + }else{ + dismiss() } - }else{ - dismiss() } } } shimmerLoading.setOnClickListener { - updateJob.cancel() + updateJob?.cancel() (updateItem.parent as LinearLayout).visibility = View.VISIBLE } - updateJob.invokeOnCompletion { - requireActivity().runOnUiThread { - title.visibility = View.VISIBLE - subtitle.visibility = View.VISIBLE - shimmerLoading.visibility = View.GONE - shimmerLoadingSubtitle.visibility = View.GONE - shimmerLoading.stopShimmer() - shimmerLoadingSubtitle.stopShimmer() + updateJob?.invokeOnCompletion { + kotlin.runCatching { + requireActivity().runOnUiThread { + title.visibility = View.VISIBLE + subtitle.visibility = View.VISIBLE + shimmerLoading.visibility = View.GONE + shimmerLoadingSubtitle.visibility = View.GONE + shimmerLoading.stopShimmer() + shimmerLoadingSubtitle.stopShimmer() + } } } - updateJob.start() + updateJob?.start() } private fun initUpdateFormats(url: String){ - CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { + updateFormatsJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { withContext(Dispatchers.Main){ runCatching { val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment @@ -510,25 +562,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type } } - } - - override fun onCancel(dialog: DialogInterface) { - super.onCancel(dialog) - cleanUp() - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - cleanUp() - } - - - private fun cleanUp(){ - kotlin.runCatching { - if (activity is ShareActivity && !parentFragmentManager.fragments.map { it.tag }.contains("downloadPlaylistSheet")){ - (activity as ShareActivity).finish() - } - } + updateFormatsJob?.start() } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt index 9b7db523..37dc6da7 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt @@ -9,6 +9,7 @@ import android.content.SharedPreferences import android.content.res.Configuration import android.graphics.Canvas import android.graphics.Color +import android.os.Build import android.os.Bundle import android.text.format.DateFormat import android.util.DisplayMetrics @@ -37,6 +38,7 @@ import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.ui.adapter.ConfigureMultipleDownloadsAdapter import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.Format +import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel @@ -66,7 +68,7 @@ import kotlinx.coroutines.withContext import java.text.SimpleDateFormat import java.util.Locale -class DownloadMultipleBottomSheetDialog(private var items: MutableList) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener, +class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener, ConfigureDownloadBottomSheetDialog.OnDownloadItemUpdateListener { private lateinit var downloadViewModel: DownloadViewModel private lateinit var historyViewModel: HistoryViewModel @@ -80,6 +82,8 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -97,6 +101,19 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList= 33){ + arguments?.getParcelableArrayList("downloads", DownloadItem::class.java) + }else{ + arguments?.getParcelableArrayList("downloads") + }.apply { + if (this == null){ + dismiss() + return + }else{ + items = this + } + } + if (items.isEmpty()) dismiss() dialog.setOnShowListener { @@ -138,10 +155,7 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList= 33){ + arguments?.getParcelable("result", ResultItem::class.java) + }else{ + arguments?.getParcelable("result") + } + + if (i == null) { + dismiss() + return + } + + item = i + //remove outdated player url of 1hr so it can refetch it in the player if (item.creationTime > System.currentTimeMillis() - 3600000) item.urls = "" @@ -293,10 +308,12 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF } private fun onButtonClick(type: DownloadViewModel.Type){ - this.dismiss() if (sharedPreferences.getBoolean("download_card", true)) { - val bottomSheet = DownloadBottomSheetDialog(item, type) - bottomSheet.show(parentFragmentManager, "downloadSingleSheet") + val bundle = Bundle() + bundle.putParcelable("result", item) + bundle.putSerializable("type", type) + findNavController().navigateUp() + findNavController().navigate(R.id.downloadBottomSheetDialog, bundle) } else { lifecycleScope.launch{ val downloadItem = withContext(Dispatchers.IO){ @@ -305,6 +322,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF givenType = type) } downloadViewModel.queueDownloads(listOf(downloadItem)) + findNavController().navigateUp() } } } @@ -324,7 +342,6 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF kotlin.runCatching { videoView.player?.stop() videoView.player?.release() - parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("resultDetails")!!).commit() } } @@ -582,7 +599,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF ActiveDownloadAdapter.ActiveDownloadAction.Pause -> { lifecycleScope.launch { cancelItem(itemID.toInt()) - item.status = DownloadRepository.Status.Paused.toString() + item.status = DownloadRepository.Status.ActivePaused.toString() withContext(Dispatchers.IO){ downloadViewModel.updateDownload(item) } @@ -591,7 +608,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF } ActiveDownloadAdapter.ActiveDownloadAction.Resume -> { lifecycleScope.launch { - item.status = DownloadRepository.Status.Active.toString() + item.status = DownloadRepository.Status.PausedReQueued.toString() withContext(Dispatchers.IO){ downloadViewModel.updateDownload(item) } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/SelectPlaylistItemsDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/SelectPlaylistItemsDialog.kt index 872867e1..2e4d8908 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/SelectPlaylistItemsDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/SelectPlaylistItemsDialog.kt @@ -3,16 +3,19 @@ package com.deniscerri.ytdlnis.ui.downloadcard import android.app.ActionBar.LayoutParams import android.app.Dialog import android.content.DialogInterface +import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.view.Window +import androidx.core.os.bundleOf import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.DialogFragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.deniscerri.ytdlnis.R @@ -30,8 +33,9 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu import com.google.android.material.textfield.TextInputLayout import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext -class SelectPlaylistItemsDialog(private val items: List, private val type: DownloadViewModel.Type) : DialogFragment(), PlaylistAdapter.OnItemClickListener { +class SelectPlaylistItemsDialog : DialogFragment(), PlaylistAdapter.OnItemClickListener { private lateinit var downloadViewModel: DownloadViewModel private lateinit var resultViewModel: ResultViewModel private lateinit var listAdapter : PlaylistAdapter @@ -41,6 +45,10 @@ class SelectPlaylistItemsDialog(private val items: List, private va private lateinit var fromTextInput: TextInputLayout private lateinit var toTextInput: TextInputLayout + + private lateinit var items: List + private lateinit var type: DownloadViewModel.Type + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NORMAL, R.style.FullScreenDialogTheme) @@ -65,6 +73,21 @@ class SelectPlaylistItemsDialog(private val items: List, private va override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + if (Build.VERSION.SDK_INT >= 33){ + arguments?.getParcelableArrayList("results", ResultItem::class.java) + }else{ + arguments?.getParcelableArrayList("results") + }.apply { + if (this == null){ + dismiss() + return + }else{ + items = this + } + } + type = arguments?.getSerializable("type") as DownloadViewModel.Type + + dialog?.window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) toolbar = view.findViewById(R.id.toolbar) @@ -156,11 +179,12 @@ class SelectPlaylistItemsDialog(private val items: List, private va val checkedResultItems = items.filter { item -> checkedItems.contains(item!!.url) } if (checkedResultItems.size == 1){ val resultItem = resultViewModel.getItemByURL(checkedResultItems[0]!!.url) - val bottomSheet = DownloadBottomSheetDialog(resultItem, type) - parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment -> - dismiss() + withContext(Dispatchers.Main){ + findNavController().navigate(R.id.action_selectPlaylistItemsDialog_to_downloadBottomSheetDialog, bundleOf( + Pair("result", resultItem), + Pair("type", downloadViewModel.getDownloadType(type, resultItem.url)), + )) } - bottomSheet.show(parentFragmentManager, "downloadSingleSheet") }else{ val downloadItems = mutableListOf() checkedResultItems.forEach { c -> @@ -173,11 +197,11 @@ class SelectPlaylistItemsDialog(private val items: List, private va downloadItems.add(i) } - val bottomSheet = DownloadMultipleBottomSheetDialog(downloadItems) - parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment -> - dismiss() + withContext(Dispatchers.Main){ + findNavController().navigate(R.id.action_selectPlaylistItemsDialog_to_downloadMultipleBottomSheetDialog, bundleOf( + Pair("downloads", downloadItems) + )) } - bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") } dismiss() @@ -210,25 +234,6 @@ class SelectPlaylistItemsDialog(private val items: List, private va } } - override fun onCancel(dialog: DialogInterface) { - super.onCancel(dialog) - cleanup() - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - cleanup() - } - - private fun cleanup(){ - kotlin.runCatching { - val movedToMultipleOrSingleSheet = parentFragmentManager.fragments.map { it.tag }.contains("downloadMultipleSheet") || parentFragmentManager.fragments.map { it.tag }.contains("downloadSingleSheet") - if (activity is ShareActivity && !movedToMultipleOrSingleSheet){ - (activity as ShareActivity).finish() - } - } - } - private fun checkRanges(start: String, end: String) : Boolean { return start.isNotBlank() && end.isNotBlank() } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt index 7340b713..285c41ac 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt @@ -94,7 +94,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis downloadViewModel.getActiveDownloads() }.forEach { cancelItem(it.id.toInt()) - it.status = DownloadRepository.Status.Paused.toString() + it.status = DownloadRepository.Status.ActivePaused.toString() downloadViewModel.updateDownload(it) } @@ -111,7 +111,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis downloadViewModel.getActiveDownloads() } - val toQueue = active.filter { it.status == DownloadRepository.Status.Paused.toString() }.toMutableList() + val toQueue = active.filter { it.status == DownloadRepository.Status.ActivePaused.toString() }.toMutableList() toQueue.forEach { it.status = DownloadRepository.Status.Queued.toString() downloadViewModel.updateDownload(it) @@ -162,7 +162,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis if (it.size > 1){ pauseResume.visibility = View.VISIBLE - if (it.all { l -> l.status == DownloadRepository.Status.Paused.toString() }){ + if (it.all { l -> l.status == DownloadRepository.Status.ActivePaused.toString() }){ pauseResume.text = requireContext().getString(R.string.resume) }else{ pauseResume.text = requireContext().getString(R.string.pause) @@ -208,7 +208,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis ActiveDownloadAdapter.ActiveDownloadAction.Pause -> { lifecycleScope.launch { cancelItem(itemID.toInt()) - item.status = DownloadRepository.Status.Paused.toString() + item.status = DownloadRepository.Status.ActivePaused.toString() withContext(Dispatchers.IO){ downloadViewModel.updateDownload(item) } @@ -217,7 +217,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis } ActiveDownloadAdapter.ActiveDownloadAction.Resume -> { lifecycleScope.launch { - item.status = DownloadRepository.Status.Active.toString() + item.status = DownloadRepository.Status.PausedReQueued.toString() withContext(Dispatchers.IO){ downloadViewModel.updateDownload(item) } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt index e019ac97..f09a7001 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt @@ -14,9 +14,11 @@ import android.widget.RelativeLayout import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper @@ -131,12 +133,12 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic } }, longClickDownloadButton = { - val sheet = DownloadBottomSheetDialog( - currentDownloadItem = it, - result = downloadViewModel.createResultItemFromDownload(it), - type = it.type + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("downloadItem", it), + Pair("result", downloadViewModel.createResultItemFromDownload(it)), + Pair("type", it.type) + ) ) - sheet.show(parentFragmentManager, "downloadSingleSheet") }, scheduleButtonClick = {} ) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/DownloadQueueMainFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/DownloadQueueMainFragment.kt index a192bc05..184ec1ae 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/DownloadQueueMainFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/DownloadQueueMainFragment.kt @@ -10,6 +10,8 @@ import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import androidx.navigation.ui.setupWithNavController import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import androidx.work.WorkManager diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt index ff7fc0a9..c284af96 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt @@ -15,6 +15,7 @@ import android.widget.AdapterView.OnItemClickListener import android.widget.RelativeLayout import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope @@ -134,12 +135,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL } }, longClickDownloadButton = { - val sheet = DownloadBottomSheetDialog( - currentDownloadItem = it, - result = downloadViewModel.createResultItemFromDownload(it), - type = it.type - ) - sheet.show(parentFragmentManager, "downloadSingleSheet") + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("downloadItem", it), + Pair("result", downloadViewModel.createResultItemFromDownload(it)), + Pair("type", it.type) + )) }, scheduleButtonClick = {} ) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt index 213fa7f1..a97a5f76 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt @@ -27,6 +27,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView import androidx.core.content.ContextCompat +import androidx.core.os.bundleOf import androidx.core.view.forEach import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider @@ -411,11 +412,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ historyViewModel.delete(it, false) }, redownloadShowDownloadCard = { - val sheet = DownloadBottomSheetDialog( - result = downloadViewModel.createResultItemFromHistory(it), - type = it.type - ) - sheet.show(parentFragmentManager, "downloadSingleSheet") + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("result", downloadViewModel.createResultItemFromHistory(it)), + Pair("type", it.type), + )) } ) } @@ -547,10 +547,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ ItemTouchHelper.RIGHT -> { val item = historyList!![position]!! historyAdapter!!.notifyItemChanged(position) - val sheet = DownloadBottomSheetDialog(type = item.type, - result = downloadViewModel.createResultItemFromHistory(item) - ) - sheet.show(parentFragmentManager, "downloadSingleSheet") + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("result", downloadViewModel.createResultItemFromHistory(item)), + Pair("type", item.type) + )) } } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt index 59bcff9c..7d9c4498 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt @@ -16,9 +16,11 @@ import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper @@ -154,12 +156,11 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi } }, longClickDownloadButton = { - val sheet = DownloadBottomSheetDialog( - currentDownloadItem = it, - result = downloadViewModel.createResultItemFromDownload(it), - type = it.type - ) - sheet.show(parentFragmentManager, "downloadSingleSheet") + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("downloadItem", it), + Pair("result", downloadViewModel.createResultItemFromDownload(it)), + Pair("type", it.type) + )) }, scheduleButtonClick = {downloadItem -> UiUtil.showDatePicker(parentFragmentManager) { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt index a669acf0..152abbaa 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt @@ -14,9 +14,11 @@ import android.widget.RelativeLayout import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper @@ -131,12 +133,11 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis } }, longClickDownloadButton = { it: DownloadItem -> - val sheet = DownloadBottomSheetDialog( - currentDownloadItem = it, - result = downloadViewModel.createResultItemFromDownload(it), - type = it.type - ) - sheet.show(parentFragmentManager, "downloadSingleSheet") + findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf( + Pair("downloadItem", it), + Pair("result", downloadViewModel.createResultItemFromDownload(it)), + Pair("type", it.type), + )) }, scheduleButtonClick = {} ) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/downloadLogs/DownloadLogFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/downloadLogs/DownloadLogFragment.kt index 71cafa43..5b311336 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/downloadLogs/DownloadLogFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/downloadLogs/DownloadLogFragment.kt @@ -69,7 +69,6 @@ class DownloadLogFragment : Fragment() { } content = view.findViewById(R.id.content) - content.movementMethod = ScrollingMovementMethod() content.setTextIsSelectable(true) contentScrollView = view.findViewById(R.id.content_scrollview) val bottomAppBar = view.findViewById(R.id.bottomAppBar) @@ -89,7 +88,7 @@ class DownloadLogFragment : Fragment() { } val id = arguments?.getLong("logID") - if (id == null) { + if (id == null || id == 0L) { mainActivity.onBackPressedDispatcher.onBackPressed() } @@ -155,19 +154,11 @@ class DownloadLogFragment : Fragment() { true } -// contentScrollView.setOnScrollChangeListener { view, sx, sy, osx, osy -> -// if (sy < osy){ -// if (contentScrollView.canScrollVertically(1)){ -// shouldScroll = false -// content.movementMethod = LinkMovementMethod.getInstance() -// bottomAppBar?.menu?.get(1)?.isVisible = true -// }else{ -// shouldScroll = true -// content.movementMethod = ScrollingMovementMethod() -// bottomAppBar?.menu?.get(1)?.isVisible = false -// } -// } -// } + contentScrollView.setOnScrollChangeListener { view, sx, sy, osx, osy -> + if (sy < osy){ + bottomAppBar?.menu?.get(1)?.isVisible = contentScrollView.canScrollVertically(1) + } + } logViewModel.getLogFlowByID(id!!).observe(viewLifecycleOwner){logItem -> diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt index 315d2826..ebe59089 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt @@ -57,6 +57,7 @@ class NotificationUtil(var context: Context) { val importance = NotificationManager.IMPORTANCE_LOW var channel = NotificationChannel(DOWNLOAD_WORKER_CHANNEL_ID, name, importance) channel.description = description + channel.setSound(null, null) notificationManager.createNotificationChannel(channel) //gui downloads diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt index 3b232be3..de221bdc 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt @@ -611,7 +611,7 @@ object UiUtil { if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility = View.GONE - else formatNote!!.text = item.format.format_note.uppercase() + else formatNote!!.text = item.format.format_note if (item.format.container != "") { container!!.text = if (file.exists()) file.extension.uppercase() else item.format.container.uppercase() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt index ddfb2269..c695a936 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt @@ -30,8 +30,6 @@ import com.yausername.youtubedl_android.YoutubeDL.UpdateStatus import io.noties.markwon.AbstractMarkwonPlugin import io.noties.markwon.Markwon import io.noties.markwon.MarkwonConfiguration -import io.noties.markwon.MarkwonSpansFactory -import io.noties.markwon.core.MarkwonTheme import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.File @@ -94,7 +92,7 @@ class UpdateUtil(var context: Context) { .setTitle(v.tag_name) .setMessage(v.body) .setIcon(R.drawable.ic_update_app) - .setNeutralButton(R.string.skip){ d: DialogInterface?, _:Int -> + .setNeutralButton(R.string.ignore){ d: DialogInterface?, _:Int -> skippedVersions.add(v.tag_name) sharedPreferences.edit().putString("skip_updates", skippedVersions.joinToString(",")).apply() d?.dismiss() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt index 97e64ff0..7b15aa54 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -259,7 +259,10 @@ class DownloadWorker( }else{ logString.append("${it.message}\n") logItem.content = logString.toString() - logRepo.insert(logItem) + val logID = withContext(Dispatchers.IO){ + logRepo.insert(logItem) + } + downloadItem.logID = logID } } @@ -277,8 +280,8 @@ class DownloadWorker( } notificationUtil.createDownloadErrored( - downloadItem.title, it.message, - if (logDownloads) logItem.id else null, + downloadItem.title.ifEmpty { downloadItem.url }, it.message, + downloadItem.logID, NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID ) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt index 3246c938..edc68ede 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt @@ -77,7 +77,15 @@ class TerminalDownloadWorker( } } - request.addOption("-P", FileUtil.getDefaultCommandPath() + "/" + itemId) + val commandPath = sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())!! + val noCache = !sharedPreferences.getBoolean("cache_downloads", true) && File(FileUtil.formatPath(commandPath)).canWrite() + + if (!noCache){ + request.addOption("-P", FileUtil.getCachePath(context) + "/TERMINAL/" + itemId) + }else if (!request.hasOption("-P")){ + request.addOption("-P", FileUtil.formatPath(commandPath)) + } + val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false) @@ -120,16 +128,18 @@ class TerminalDownloadWorker( } }.onSuccess { CoroutineScope(Dispatchers.IO).launch { - //move file from internal to set download directory - try { - FileUtil.moveFile(File(FileUtil.getDefaultCommandPath() + "/" + itemId),context, downloadLocation!!, false){ p -> - setProgressAsync(workDataOf("progress" to p)) + if(!noCache){ + //move file from internal to set download directory + try { + FileUtil.moveFile(File(FileUtil.getCachePath(context) + "/TERMINAL/" + itemId),context, downloadLocation!!, false){ p -> + setProgressAsync(workDataOf("progress" to p)) + } + }catch (e: Exception){ + e.printStackTrace() + handler.postDelayed({ + Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() + }, 1000) } - }catch (e: Exception){ - e.printStackTrace() - handler.postDelayed({ - Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() - }, 1000) } } diff --git a/app/src/main/res/layout/activity_share.xml b/app/src/main/res/layout/activity_share.xml index e2d336fa..e9ee9ec8 100644 --- a/app/src/main/res/layout/activity_share.xml +++ b/app/src/main/res/layout/activity_share.xml @@ -1,8 +1,21 @@ - + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 246be80d..428bc6bb 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -27,6 +27,12 @@ + + - @@ -142,4 +148,12 @@ android:name="com.deniscerri.ytdlnis.ui.more.settings.GeneralSettingsFragment" android:label="AppearanceSettingsFragment" /> + + \ No newline at end of file diff --git a/app/src/main/res/navigation/share_nav_graph.xml b/app/src/main/res/navigation/share_nav_graph.xml index d498625f..b32ae933 100644 --- a/app/src/main/res/navigation/share_nav_graph.xml +++ b/app/src/main/res/navigation/share_nav_graph.xml @@ -8,14 +8,27 @@ android:label="DownloadBottomSheetDialog" > + app:destination="@id/selectPlaylistItemsDialog" + app:launchSingleTop="true" + app:popUpTo="@id/downloadBottomSheetDialog" + app:popUpToInclusive="true" /> + app:destination="@id/downloadMultipleBottomSheetDialog" + app:launchSingleTop="true" + app:popUpTo="@id/selectPlaylistItemsDialog" + app:popUpToInclusive="true" /> + تعيين نوع التحميل اللاحق بناءً على آخر نوع تحميل تم الوصول اليه توقيت بحث في قوالب الأوامر - تخطي + تخطي الترخيص المضي بالتحميل على أي حال؟ تحرير بطاقة التحميل diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 5d553f94..c4ac6ab3 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -309,7 +309,7 @@ Selecciona el último tipo de la descarga abierto para el elemento actual Horario Búsqueda a partir de comandos - Omitir + Omitir Licencia ¿Todavía quieres descargar\? Modificar la tarjeta de descarga diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index c6ac0a21..23b620b7 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -309,7 +309,7 @@ वर्तमान आइटम के लिए अंतिम बार खोला गया डाउनलोड टाईप चुनें शडिऊल कमांड में से खोजें - छोड़ें + छोड़ें लाइसेंस क्या आप अब भी डाउनलोड करना चाहते हैं\? डाउनलोड कार्ड संशोधित करें diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 4b212248..b97d58a3 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -309,7 +309,7 @@ לא ניתן לנתח את הקובץ תזמון חפש מתוך פקודות - דילוג + דילוג רישיון האם תרצה להמשיך להוריד\? התאמת כרטיס הורדה diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 0f70a4c0..559a8268 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -309,7 +309,7 @@ ਮੌਜੂਦਾ ਆਈਟਮ ਲਈ ਆਖਰੀ ਵਾਰ ਖੋਲ੍ਹੀ ਗਈ ਡਾਊਨਲੋਡ ਕਿਸਮ ਚੁਣੋ ਸ਼ਡਿਊਲ ਕਮਾਂਡਾਂ ਤੋਂ ਖੋਜ ਕਰੋ - ਸਕਿੱਪ ਕਰੋ + ਸਕਿੱਪ ਕਰੋ ਲਾਈਸੈਂਸ ਕੀ ਤੁਸੀਂ ਅਜੇ ਵੀ ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\? ਡਾਊਨਲੋਡ ਕਾਰਡ ਨੂੰ ਸੋਧੋ diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 261f5a9e..e89a2420 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -309,7 +309,7 @@ Selecione o último tipo de download aberto para o item atual Agendar Pesquisar a partir dos comandos - Pular + Pular Licença Você ainda quer fazer o download\? Modificar cartão de download diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 3027ebfb..778aec83 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -309,7 +309,7 @@ Selecionar o último tipo de download aberto para o item atual Agendar Pesquisar a partir de comandos - Saltar + Saltar Licença Ainda queres descarregar\? Modificar o cartão de descarregamento diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index f4986d08..76587884 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -307,7 +307,7 @@ Расписание Заголовок User-Agent Поиск по командам - Пропустить + Пропустить Лицензия Вы все еще хотите скачать\? Изменить карту загрузки diff --git a/app/src/main/res/values-sq-rAL/strings.xml b/app/src/main/res/values-sq-rAL/strings.xml index 095ebe9c..83a1d9a6 100644 --- a/app/src/main/res/values-sq-rAL/strings.xml +++ b/app/src/main/res/values-sq-rAL/strings.xml @@ -310,7 +310,7 @@ Zgjidh llojin e fundit të shkarkimit për shkarkimin aktual Gjatësia Orar - Injoro + Injoro Liçensa Do sërisht ta shkarkosh\? Modifiko Kartën e Shkarkimit diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 1c309814..c6081a31 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -307,7 +307,7 @@ Розклад Заголовок User-Agent Пошук з команд - Пропустити + Пропустити Ліцензія Ви все ще хочете завантажити\? Змінити картку завантаження diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 211d517e..b3d7361c 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -307,7 +307,7 @@ Lịch trình Tiêu đề tác nhân người dùng Tìm kiếm từ lệnh - Bỏ qua + Bỏ qua Giấy phép Bạn vẫn muốn tải xuống\? Sửa đổi thẻ tải xuống diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e801f351..b438da63 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -309,7 +309,7 @@ 为当前项目选择上次打开的下载类型 安排时间 搜索命令行模板 - 跳过 + 跳过 许可证 你仍要下载吗? 修改下载卡片 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e372fcd5..20a42945 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -309,7 +309,7 @@ 使用上次的下載類型 排程設定 指令搜尋 - 略過此項 + 略過此項 使用授權 是否繼續進行下載? 編輯下載資訊卡片 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2e1d507..9cb3da8b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -293,7 +293,7 @@ Extra Command Use Cookies Embed Metadata - Embed and parse metadata to the audio file + Parse and embed metadata to the audio file Update Formats in Background Auto-Update yt-dlp Use SponsorBlock @@ -316,7 +316,7 @@ License Do you still want to download? Schedule - Skip + Ignore Modify Download Card Export File \ No newline at end of file diff --git a/build.gradle b/build.gradle index b98d1bc2..fd2e7300 100644 --- a/build.gradle +++ b/build.gradle @@ -39,6 +39,7 @@ plugins { id 'com.android.library' version '8.1.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.10' apply false id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10" apply false + id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10" apply false id 'com.android.test' version '8.1.1' apply false id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false }