move to downloadable plugins as apks pt1

pull/1112/head
deniscerri 5 months ago
parent 6ab80ac940
commit 61b6a6f4ce
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -13,7 +13,8 @@ def versionMajor = 1
def versionMinor = 8
def versionPatch = 7
def versionBuild = 3 // bump for dogfood builds, public betas, etc.
def isBeta = true
//WHEN RELEASING BETA KEEP THE SAME VERSION AS LATEST STABLE, SO USERS CAN DOWNGRADE
def isBeta = false
def versionExt = ""
if (versionBuild > 0) {
@ -46,12 +47,7 @@ android {
defaultConfig {
applicationId "com.deniscerri.ytdl"
minSdk 24
/*
KEEP 28 TO ALLOW THE APP TO EXECUTE DOWNLOADABLE PACKAGES, IF PLAN TO UPGRADE PRE-BUNDLE packages in jniLibs
OR LOOK INTO PACKAGES as APK and put the files in their respective jniLibs
* */
//noinspection ExpiredTargetSdkVersion
targetSdk 28
targetSdk 36
versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild
versionName "${versionMajor}.${versionMinor}.${versionPatch}${versionExt}"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

@ -25,6 +25,12 @@
<!-- foreground service permission for android 14 and up-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<queries>
<package android:name="com.deniscerri.ytdl.nodejs" />
<package android:name="com.deniscerri.ytdl.python" />
<package android:name="com.deniscerri.ytdl.ffmpeg" />
<package android:name="com.deniscerri.ytdl.aria2c" />
</queries>
<application
android:usesCleartextTraffic="true"

@ -37,6 +37,7 @@ import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdl.database.enums.DownloadType
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.CookieViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdl.database.viewmodel.SettingsViewModel
@ -82,6 +83,7 @@ class MainActivity : BaseActivity() {
private lateinit var cookieViewModel: CookieViewModel
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var settingsViewModel: SettingsViewModel
private lateinit var downloadCardViewModel: DownloadCardViewModel
private var navigationView: NavigationView? = null
private var navigationBarView: NavigationBarView? = null
private lateinit var navHostFragment : NavHostFragment
@ -98,6 +100,7 @@ class MainActivity : BaseActivity() {
cookieViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java]
downloadCardViewModel = ViewModelProvider(this)[DownloadCardViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(context)
if (preferences.getBoolean("incognito", false)) {
@ -411,7 +414,8 @@ class MainActivity : BaseActivity() {
downloadType = downloadViewModel.getDownloadType(null, path)
}
bundle.putParcelable("result", downloadViewModel.createEmptyResultItem(path))
downloadCardViewModel.setResultItem(downloadViewModel.createEmptyResultItem(path))
downloadCardViewModel.setDownloadItem(null)
bundle.putSerializable("type", downloadType)
navController.navigate(R.id.downloadBottomSheetDialog, bundle)
return

@ -249,8 +249,7 @@ object RuntimeManager {
val err = errBuffer.toString()
val successCodes = listOf(
0, //Everything is successful,
100, //yt-dlp -U fails but the downloads is successful
0, //Everything is successful
)
if (!successCodes.contains(exitCode)) {

@ -8,4 +8,5 @@ object Aria2c : PackageBase() {
override val bundledVersion: String get() = "v1.37.0"
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubPackageName: String get() = "aria2c"
override val apkPackage: String get() = "com.deniscerri.ytdl.aria2c"
}

@ -8,4 +8,5 @@ object FFmpeg : PackageBase() {
override val bundledVersion: String get() = "v7.0.1"
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubPackageName: String get() = "ffmpeg"
override val apkPackage: String get() = "com.deniscerri.ytdl.ffmpeg"
}

@ -8,4 +8,5 @@ object NodeJS : PackageBase() {
override val bundledVersion: String get() = ""
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubPackageName: String get() = "nodejs"
override val apkPackage: String get() = "com.deniscerri.ytdl.nodejs"
}

@ -1,7 +1,10 @@
package com.deniscerri.ytdl.core.packages
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.edit
import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
@ -29,6 +32,7 @@ abstract class PackageBase {
protected abstract val canUninstall: Boolean // set false if library is essential
protected abstract val githubRepo: String // e.g deniscerri/ytdlnis-packages
protected abstract val githubPackageName: String // e.g ffmpeg
abstract val apkPackage: String // e.g. com.deniscerri.ytdl.ffmpeg
fun getInstance(): PackageBase = this
abstract val bundledVersion: String?
@ -82,7 +86,19 @@ abstract class PackageBase {
val packageDir = File(baseDir, "$packagesRoot/$packageFolderName")
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
//try init bundled
initBundled(context, packageDir)
val bundledZip = File(context.applicationInfo.nativeLibraryDir, bundledZipName)
initBundled(context, bundledZip, packageDir)
if (apkPackage.isNotBlank()) {
//try init from package apk
try {
context.packageManager.getApplicationInfo(apkPackage, 0)
} catch(e: Exception) {
null
}?.apply {
val apkBundledZip = File(this.nativeLibraryDir, bundledZipName)
initBundled(context, apkBundledZip, getDownloadedDir(context), packageApkVersion = getDownloadedPackageAppVersion(context))
}
}
location = getLocation(context, baseDir)
downloadedVersion = if (location.isDownloaded) {
@ -92,19 +108,29 @@ abstract class PackageBase {
}
}
private fun initBundled(context: Context, targetDir: File) {
val bundledZip = File(context.applicationInfo.nativeLibraryDir, bundledZipName)
private fun initBundled(context: Context, bundledZip: File, targetDir: File, packageApkVersion: String? = null) {
if (!bundledZip.exists()) return
val currentSize = bundledZip.length().toString()
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
if (!targetDir.exists() || prefs.getString(bundledVerKey, "") != currentSize) {
val bundledVerKey = prefs.getString(bundledVerKey, "")
val downloadedVerKey = prefs.getString(downloadedVersionKey, "")
val sizeMismatch = if (packageApkVersion != null) downloadedVerKey != packageApkVersion else bundledVerKey != currentSize
if (!targetDir.exists() || sizeMismatch) {
FileUtils.deleteQuietly(targetDir)
targetDir.mkdirs()
try {
ZipUtils.unzip(bundledZip, targetDir)
prefs.edit(commit = true) { putString(bundledVerKey, currentSize) }
prefs.edit(commit = true) {
if (packageApkVersion != null) {
putString(downloadedVersionKey, packageApkVersion)
} else {
putString(bundledVerKey, currentSize)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
@ -117,28 +143,42 @@ abstract class PackageBase {
}
fun getLocation(context: Context, baseDir: File): PackageLocation {
//downloaded
val downloadedDir = getDownloadedDir(context)
val downloadedBinDir = downloadedDir
val downloadedLDLibDir = downloadedDir
val downloadedExe = File(downloadedDir, "lib$executableName.so")
val mainNativeDir = context.applicationInfo.nativeLibraryDir
var packageBinDir: String? = null
if (apkPackage.isNotBlank()) {
try {
packageBinDir = context.packageManager.getApplicationInfo(apkPackage, 0).nativeLibraryDir
} catch (e: Exception) {}
}
val packageExe = if (packageBinDir != null) File(packageBinDir, "lib$executableName.so") else null
val isPackageActive = packageExe?.exists() == true
var isBundleActive = false
//bundled
val bundledDir = File(baseDir, packagesRoot)
val bundledBinDir = File(context.applicationInfo.nativeLibraryDir)
val bundledLDLibDir = File(bundledDir, packageFolderName)
val bundledExe = File(bundledBinDir, "lib$executableName.so")
val finalExe: File
val binDir: File
val ldDir: File
val isDownloaded = downloadedExe.exists()
val isBundled = bundledExe.exists()
if (isPackageActive) {
finalExe = packageExe
binDir = File(packageBinDir!!)
ldDir = getDownloadedDir(context)
} else {
val bundledDir = File(baseDir, packagesRoot)
binDir = File(context.applicationInfo.nativeLibraryDir)
ldDir = File(bundledDir, packageFolderName)
finalExe = File(binDir, "lib$executableName.so")
isBundleActive = finalExe.exists()
}
return PackageLocation(
binDir = if (isDownloaded) downloadedBinDir else bundledBinDir,
ldDir = if (isDownloaded) downloadedLDLibDir else bundledLDLibDir,
executable = if (isDownloaded) downloadedExe else bundledExe,
isDownloaded,
isBundled,
isDownloaded || isBundled,
binDir = binDir,
ldDir = ldDir,
executable = finalExe,
isDownloaded = isPackageActive,
isBundled = isBundleActive,
isPackageActive || isBundleActive,
canUninstall
)
}
@ -221,7 +261,7 @@ abstract class PackageBase {
}
}
fun uninstallDownloaded(context: Context): Result<Unit> {
fun uninstallDownloadedRuntimeDir(context: Context): Result<Unit> {
return kotlin.runCatching {
val runtimeDir = getDownloadedDir(context)
@ -287,6 +327,32 @@ abstract class PackageBase {
}
}
fun getDownloadedPackageAppVersion(context: Context): String? {
if (apkPackage.isBlank()) return null
return try {
val packageManager = context.packageManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val info = packageManager.getPackageInfo(apkPackage, PackageManager.PackageInfoFlags.of(0))
"v${info.versionName}"
} else {
@Suppress("DEPRECATION")
val info = packageManager.getPackageInfo(apkPackage, 0)
"v${info.versionName}"
}
} catch (e: PackageManager.NameNotFoundException) {
null // Package not installed
}
}
fun isPackageAppInstalled(context: Context): Boolean {
return try {
context.packageManager.getPackageInfo(apkPackage, 0)
true
} catch (e: PackageManager.NameNotFoundException) {
false
}
}
fun getArchSuffix(): String {
val abi = Build.SUPPORTED_ABIS[0]

@ -8,4 +8,5 @@ object Python : PackageBase() {
override val canUninstall: Boolean = false
override val githubRepo: String get() = "deniscerri/ytdlnis-plugins"
override val githubPackageName: String get() = "python"
override val apkPackage: String get() = "com.deniscerri.ytdl.python"
}

@ -8,4 +8,5 @@ object QuickJS : PackageBase() {
override val canUninstall: Boolean = false
override val githubRepo: String get() = ""
override val githubPackageName: String get() = ""
override val apkPackage: String get() = ""
}

@ -0,0 +1,48 @@
package com.deniscerri.ytdl.database.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.DBManager
import com.deniscerri.ytdl.database.enums.DownloadType
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.models.Format
import com.deniscerri.ytdl.database.models.FormatRecyclerView
import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.ui.downloadcard.FormatSelectionBottomSheetDialog.FormatCategory
import com.deniscerri.ytdl.ui.downloadcard.FormatSelectionBottomSheetDialog.FormatSorting
import com.deniscerri.ytdl.ui.downloadcard.FormatTuple
import com.deniscerri.ytdl.ui.downloadcard.MultipleItemFormatTuple
import com.deniscerri.ytdl.util.Extensions.isYoutubeURL
import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdl.util.FormatUtil
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import java.io.File
class DownloadCardViewModel(private val application: Application) : AndroidViewModel(application) {
var resultItem: ResultItem? = null
private set
var downloadItem: DownloadItem? = null
private set
init {
}
fun setDownloadItem(item: DownloadItem?) {
downloadItem = item
}
fun setResultItem(item: ResultItem?) {
resultItem = item
}
}

@ -26,10 +26,14 @@ open class BaseActivity : AppCompatActivity() {
fun askPermissions() {
val permissions = arrayListOf<String>()
val hasFilePerm = (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
val hasFilePerm = if (Build.VERSION.SDK_INT >= 30) {
true
}else {
(ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) &&
(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
}
if (!hasFilePerm){
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE)

@ -51,6 +51,7 @@ import com.deniscerri.ytdl.database.enums.DownloadType
import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdl.database.models.SearchSuggestionItem
import com.deniscerri.ytdl.database.models.SearchSuggestionType
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
@ -102,6 +103,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, SearchSuggesti
private lateinit var resultViewModel : ResultViewModel
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var historyViewModel : HistoryViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private var fragmentView: View? = null
private var activity: Activity? = null
@ -153,6 +155,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, SearchSuggesti
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
downloadQueue = ArrayList()
resultsList = mutableListOf()
@ -766,7 +769,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, SearchSuggesti
){
//show the fragment if its not in the backstack
val bundle = Bundle()
bundle.putParcelable("result", resultItem)
downloadCardViewModel.setResultItem(resultItem)
downloadCardViewModel.setDownloadItem(null)
bundle.putSerializable("type", downloadViewModel.getDownloadType(type, resultItem.url))
if (disableUpdateData) {
bundle.putBoolean("disableUpdateData", true)

@ -36,6 +36,7 @@ import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
@ -70,6 +71,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var historyViewModel: HistoryViewModel
private lateinit var resultViewModel: ResultViewModel
private lateinit var downloadCardViewModel: DownloadCardViewModel
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var commandTemplateViewModel : CommandTemplateViewModel
private lateinit var sharedPreferences : SharedPreferences
@ -95,17 +97,12 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java]
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(requireActivity())[CommandTemplateViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val res: ResultItem?
val dwl: DownloadItem?
if (Build.VERSION.SDK_INT >= 33){
res = arguments?.getParcelable("result", ResultItem::class.java)
dwl = arguments?.getParcelable("downloadItem", DownloadItem::class.java)
}else{
res = arguments?.getParcelable<ResultItem>("result")
dwl = arguments?.getParcelable<DownloadItem>("downloadItem")
}
val res = downloadCardViewModel.resultItem
val dwl = downloadCardViewModel.downloadItem
type = arguments?.getSerializable("type") as DownloadType
disableUpdateData = arguments?.getBoolean("disableUpdateData") == true
ignoreDuplicates = arguments?.getBoolean("ignore_duplicates") == true

@ -41,6 +41,7 @@ import com.deniscerri.ytdl.database.enums.DownloadType
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.models.ResultItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
@ -79,6 +80,7 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var resultViewModel: ResultViewModel
private lateinit var ytdlpViewModel: YTDLPViewModel
private lateinit var downloadCardViewModel: DownloadCardViewModel
private lateinit var activeAdapter: ActiveDownloadMinifiedAdapter
private lateinit var queuedAdapter: GenericDownloadAdapter
@ -95,6 +97,7 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
ytdlpViewModel = ViewModelProvider(this)[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
downloadManager = requireContext().getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
}
@ -312,7 +315,8 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
private fun onButtonClick(type: DownloadType){
if (sharedPreferences.getBoolean("download_card", true)) {
val bundle = Bundle()
bundle.putParcelable("result", item)
downloadCardViewModel.setResultItem(item)
downloadCardViewModel.setDownloadItem(null)
bundle.putSerializable("type", type)
findNavController().navigateUp()
findNavController().navigate(R.id.downloadBottomSheetDialog, bundle)
@ -463,9 +467,10 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
}
},
longClickDownloadButton = {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type)
)
)

@ -32,6 +32,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.ui.adapter.GenericDownloadAdapter
@ -58,6 +59,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var cancelledRecyclerView : RecyclerView
private lateinit var preferences : SharedPreferences
private lateinit var adapter : GenericDownloadAdapter
@ -78,6 +80,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
activity = getActivity()
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
return fragmentView
}
@ -184,9 +187,10 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
}
},
longClickDownloadButton = {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type)
)
)
@ -307,10 +311,11 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
downloadViewModel.getItemByID(selectedObjects.first())
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(itm))
downloadCardViewModel.setDownloadItem(itm)
withContext(Dispatchers.Main) {
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", itm),
Pair("result", downloadViewModel.createResultItemFromDownload(itm)),
Pair("type", itm.type)
))
}

@ -18,6 +18,7 @@ import androidx.viewpager2.widget.ViewPager2
import androidx.work.WorkManager
import com.deniscerri.ytdl.MainActivity
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.util.Extensions.createBadge
import com.deniscerri.ytdl.util.NavbarUtil
@ -34,6 +35,7 @@ import kotlinx.coroutines.withContext
class DownloadQueueMainFragment : Fragment(){
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var downloadCardViewModel: DownloadCardViewModel
private lateinit var topAppBar: MaterialToolbar
private lateinit var workManager: WorkManager
private lateinit var tabLayout: TabLayout
@ -58,6 +60,7 @@ class DownloadQueueMainFragment : Fragment(){
super.onViewCreated(view, savedInstanceState)
workManager = WorkManager.getInstance(requireContext())
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
topAppBar = view.findViewById(R.id.downloads_toolbar)
val isInNavBar = NavbarUtil.getNavBarItems(requireActivity()).any { n -> n.itemId == R.id.downloadQueueMainFragment && n.isVisible }
@ -132,11 +135,11 @@ class DownloadQueueMainFragment : Fragment(){
val item = withContext(Dispatchers.IO){
downloadViewModel.getItemByID(reconfigureID)
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(item))
downloadCardViewModel.setDownloadItem(item)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", item),
Pair("result", downloadViewModel.createResultItemFromDownload(item)),
Pair("type", item.type)
)
)
)
}
}

@ -33,6 +33,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.ui.adapter.GenericDownloadAdapter
@ -59,6 +60,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var erroredRecyclerView : RecyclerView
private lateinit var preferences : SharedPreferences
private lateinit var noResults : RelativeLayout
@ -79,6 +81,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
activity = getActivity()
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
return fragmentView
}
@ -188,9 +191,10 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
}
},
longClickDownloadButton = {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type)
))
},
@ -298,10 +302,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
downloadViewModel.getItemByID(selectedObjects.first())
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(itm))
downloadCardViewModel.setDownloadItem(itm)
withContext(Dispatchers.Main) {
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", itm),
Pair("result", downloadViewModel.createResultItemFromDownload(itm)),
Pair("type", itm.type)
))
}
@ -386,9 +391,10 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
downloadViewModel.getItemByID(itemID)
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(item))
downloadCardViewModel.setDownloadItem(item)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", item),
Pair("result", downloadViewModel.createResultItemFromDownload(item)),
Pair("type", item.type)
))

@ -44,6 +44,7 @@ import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.DBManager.SORTING
import com.deniscerri.ytdl.database.enums.DownloadType
import com.deniscerri.ytdl.database.repository.HistoryRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdl.ui.adapter.HistoryPaginatedAdapter
@ -73,6 +74,7 @@ import kotlinx.coroutines.withContext
class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
private lateinit var historyViewModel : HistoryViewModel
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var fragmentView: View
private var mainActivity: MainActivity? = null
@ -195,6 +197,7 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
}
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
lifecycleScope.launch{
downloadViewModel.alreadyExistsUiState.collectLatest { res ->
if (res.isNotEmpty()){
@ -535,8 +538,10 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
historyViewModel.delete(it, false)
},
redownloadShowDownloadCard = {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromHistory(it))
downloadCardViewModel.setDownloadItem(null)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("result", downloadViewModel.createResultItemFromHistory(it)),
Pair("type", it.type),
Pair("ignore_duplicates", true),
))
@ -660,8 +665,10 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
historyViewModel.getByID(selectedObjects.first())
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromHistory(tmp))
downloadCardViewModel.setDownloadItem(null)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("result", downloadViewModel.createResultItemFromHistory(tmp)),
Pair("type", tmp.type),
Pair("ignore_duplicates", true)
))
@ -756,8 +763,11 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
historyViewModel.getByID(itemID)
}
historyAdapter.notifyItemChanged(position)
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromHistory(item))
downloadCardViewModel.setDownloadItem(null)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("result", downloadViewModel.createResultItemFromHistory(item)),
Pair("type", item.type),
Pair("ignore_duplicates", true)
))

@ -32,6 +32,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.ui.adapter.QueuedDownloadAdapter
@ -59,6 +60,7 @@ class QueuedDownloadsFragment : Fragment(), QueuedDownloadAdapter.OnItemClickLis
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var queuedRecyclerView : RecyclerView
private lateinit var adapter : QueuedDownloadAdapter
private lateinit var noResults : RelativeLayout
@ -79,6 +81,7 @@ class QueuedDownloadsFragment : Fragment(), QueuedDownloadAdapter.OnItemClickLis
notificationUtil = NotificationUtil(requireContext())
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
ytdlpViewModel = ViewModelProvider(this)[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
return fragmentView
}
@ -467,9 +470,9 @@ class QueuedDownloadsFragment : Fragment(), QueuedDownloadAdapter.OnItemClickLis
withContext(Dispatchers.IO){
downloadViewModel.updateToStatus(it.id, DownloadRepository.Status.Saved)
}
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type)
)
)

@ -32,6 +32,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.ui.adapter.GenericDownloadAdapter
@ -58,6 +59,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var savedRecyclerView: RecyclerView
private lateinit var adapter: GenericDownloadAdapter
private lateinit var preferences: SharedPreferences
@ -78,6 +80,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
activity = getActivity()
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
return fragmentView
}
@ -196,9 +199,9 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
}
},
longClickDownloadButton = { it: DownloadItem ->
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type),
))
},
@ -306,9 +309,9 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
}
withContext(Dispatchers.Main) {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(itm))
downloadCardViewModel.setDownloadItem(itm)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", itm),
Pair("result", downloadViewModel.createResultItemFromDownload(itm)),
Pair("type", itm.type)
))
}

@ -32,6 +32,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.DownloadItem
import com.deniscerri.ytdl.database.repository.DownloadRepository
import com.deniscerri.ytdl.database.viewmodel.DownloadCardViewModel
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.ui.adapter.ScheduledDownloadAdapter
@ -55,6 +56,7 @@ class ScheduledDownloadsFragment : Fragment(), ScheduledDownloadAdapter.OnItemCl
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var downloadCardViewModel : DownloadCardViewModel
private lateinit var scheduledRecyclerView : RecyclerView
private lateinit var preferences : SharedPreferences
private lateinit var adapter : ScheduledDownloadAdapter
@ -75,6 +77,7 @@ class ScheduledDownloadsFragment : Fragment(), ScheduledDownloadAdapter.OnItemCl
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
ytdlpViewModel = ViewModelProvider(this)[YTDLPViewModel::class.java]
downloadCardViewModel = ViewModelProvider(requireActivity())[DownloadCardViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
return fragmentView
}
@ -191,9 +194,9 @@ class ScheduledDownloadsFragment : Fragment(), ScheduledDownloadAdapter.OnItemCl
}
},
longClickDownloadButton = {
downloadCardViewModel.setResultItem(downloadViewModel.createResultItemFromDownload(it))
downloadCardViewModel.setDownloadItem(it)
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
Pair("downloadItem", it),
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
Pair("type", it.type)
)
)

@ -50,6 +50,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import androidx.core.net.toUri
class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, PackageReleaseAdapter.OnItemClickListener {
@ -61,6 +62,7 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
private lateinit var preferences: SharedPreferences
private var tmpItem: PackageItem? = null
private var tmpInstance: PackageBase? = null
private var tmpDownloadJob: Job? = null
private var packages: List<PackageItem> = mutableListOf()
private var packageReleases: List<PackageBase.PackageRelease> = mutableListOf()
@ -185,6 +187,20 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
}
}
val uninstallLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (tmpInstance?.isPackageAppInstalled(requireContext()) == false) {
val resp = tmpInstance?.uninstallDownloadedRuntimeDir(requireContext())
resp?.onFailure {
Snackbar.make(requireView(), it.message ?: getString(R.string.errored), Snackbar.LENGTH_LONG).show()
}
resp?.onSuccess {
bottomSheet?.dismiss()
listAdapter.notifyDataSetChanged()
RuntimeManager.reInit(requireContext())
}
}
}
override fun onDeleteDownloadedPackageClick(item: PackageBase.PackageRelease) {
deleteDownloadedVersion(tmpItem!!, item.version)
}
@ -199,15 +215,9 @@ class PackagesFragment : Fragment(), PackagesAdapter.OnItemClickListener, Packag
"${item.title} (${version})"
) {
val instance = item.getInstance()
val resp = instance.uninstallDownloaded(requireContext())
resp.onFailure {
Snackbar.make(requireView(), it.message ?: getString(R.string.errored), Snackbar.LENGTH_LONG).show()
}
resp.onSuccess {
bottomSheet?.dismiss()
listAdapter.notifyDataSetChanged()
RuntimeManager.reInit(requireContext())
}
tmpInstance = instance
val intent = Intent(Intent.ACTION_DELETE, "package:${instance.apkPackage}".toUri())
uninstallLauncher.launch(intent)
}
}

Loading…
Cancel
Save