diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5cb71889..86104984 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,7 +5,8 @@
-
+
@@ -35,12 +36,6 @@
-
-
-
-
-
-
@@ -49,20 +44,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
> = resultDao.getResults()
+ var itemCount = MutableLiveData(0)
suspend fun insert(it: ResultItem){
resultDao.insert(it)
@@ -26,23 +28,27 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
deleteAll()
val infoUtil = InfoUtil(context)
val items = infoUtil.getTrending(context)
+ itemCount.postValue(items.size)
for (i in items){
resultDao.insert(i!!)
}
}
- suspend fun search(inputQuery: String, resetResults: Boolean){
+ suspend fun search(inputQuery: String, resetResults: Boolean) : ArrayList{
val infoUtil = InfoUtil(context)
try{
if (resetResults) deleteAll()
val res = infoUtil.search(inputQuery)
+ itemCount.postValue(res.size)
res.forEach {
resultDao.insert(it!!)
}
+ return res
}catch (ignored: Exception){}
+ return arrayListOf()
}
- suspend fun getOne(inputQuery: String, resetResults: Boolean){
+ suspend fun getOne(inputQuery: String, resetResults: Boolean) : ArrayList{
var el: Array =
inputQuery.split("/".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()
@@ -60,13 +66,16 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
try {
val v = infoUtil.getVideo(query!!)
if (resetResults) deleteAll()
+ itemCount.postValue(1)
resultDao.insert(v!!)
+ return arrayListOf(v)
} catch (e: Exception) {
Log.e(tag, e.toString())
}
+ return arrayListOf()
}
- suspend fun getPlaylist(inputQuery: String, resetResults: Boolean){
+ suspend fun getPlaylist(inputQuery: String, resetResults: Boolean) : ArrayList{
val query = inputQuery.split("list=".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()[1]
var nextPageToken = ""
@@ -81,26 +90,32 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
if (tmpToken == nextPageToken) break
nextPageToken = tmpToken
} while (true)
+ itemCount.postValue(items.size)
items.forEach {
resultDao.insert(it!!)
}
+ return items
}
- suspend fun getDefault(inputQuery: String, resetResults: Boolean){
+ suspend fun getDefault(inputQuery: String, resetResults: Boolean) : ArrayList {
val infoUtil = InfoUtil(context)
try {
if (resetResults) deleteAll()
val items = infoUtil.getFromYTDL(inputQuery)
+ itemCount.postValue(items.size)
items.forEach {
resultDao.insert(it!!)
}
+ return items
} catch (e: Exception) {
Log.e(tag, e.toString())
}
+ return arrayListOf()
}
suspend fun deleteAll(){
+ itemCount.postValue(0)
resultDao.deleteAll()
}
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 1ff93e5a..3faa4bf0 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
@@ -57,6 +57,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
bestVideoFormat = Format(
videoFormat[videoFormat.lastIndex],
videoContainer!!,
+ "",
+ "",
+ "",
0,
videoFormat[videoFormat.lastIndex]
)
@@ -65,6 +68,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
bestAudioFormat = Format(
"",
audioContainer!!,
+ "",
+ "",
+ "",
0,
""
)
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt
index 7102f031..7c60e222 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt
@@ -17,6 +17,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
private val repository : ResultRepository
val items : LiveData>
val loadingItems = MutableLiveData()
+ var itemCount : LiveData
init {
val dao = DBManager.getInstance(application).resultDao
@@ -24,6 +25,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
repository = ResultRepository(dao, commandDao, getApplication().applicationContext)
items = repository.allResults
loadingItems.postValue(false)
+ itemCount = repository.itemCount
}
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
@@ -41,7 +43,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
}
fun getTrending() = viewModelScope.launch(Dispatchers.IO){
loadingItems.postValue(true)
- repository.updateTrending();
+ repository.updateTrending()
loadingItems.postValue(false)
}
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 89164c9c..eba2e4ca 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt
@@ -1,34 +1,50 @@
package com.deniscerri.ytdlnis.receiver
+import android.Manifest
+import android.app.Activity
import android.content.Context
+import android.content.DialogInterface
import android.content.Intent
+import android.content.SharedPreferences
+import android.content.pm.PackageManager
+import android.content.res.Configuration
import android.graphics.drawable.ColorDrawable
import android.net.Uri
+import android.os.Build
+import android.os.Build.VERSION_CODES
import android.os.Bundle
-import android.util.Log
+import android.provider.Settings
+import android.view.Window
import android.view.WindowManager
-import androidx.fragment.app.FragmentManager
-import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
-import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
-import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
-import com.deniscerri.ytdlnis.ui.MoreFragment
-import java.io.BufferedReader
-import java.io.InputStreamReader
-import java.io.Reader
-import java.nio.charset.Charset
-import java.nio.charset.StandardCharsets
-import java.util.*
-import kotlin.system.exitProcess
+import android.widget.TextView
import androidx.activity.ComponentActivity
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
+import androidx.lifecycle.ViewModelProvider
+import com.deniscerri.ytdlnis.MainActivity
+import com.deniscerri.ytdlnis.R
+import com.deniscerri.ytdlnis.database.models.ResultItem
+import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
+import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
+import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import java.io.File
+import kotlin.system.exitProcess
-class ShareActivity : ComponentActivity() {
+class ShareActivity : AppCompatActivity() {
- private lateinit var binding: ActivityMainBinding
lateinit var context: Context
private lateinit var resultViewModel: ResultViewModel
private lateinit var downloadViewModel: DownloadViewModel
+ private lateinit var sharedPreferences: SharedPreferences
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -37,12 +53,28 @@ class ShareActivity : ComponentActivity() {
v.setPadding(0, 0, 0, 0)
insets
}
- window.setBackgroundDrawable(ColorDrawable(0))
- window.setLayout(
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT
- )
+ window.run {
+ setBackgroundDrawable(ColorDrawable(0))
+ setLayout(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.MATCH_PARENT
+ )
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
+ } else {
+ setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
+ }
+ }
+
+ setContentView(R.layout.activity_share)
+ context = baseContext
+ resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
+ downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
+ sharedPreferences = getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
+
+ askPermissions()
+ val intent = intent
handleIntents(intent)
}
@@ -55,46 +87,130 @@ class ShareActivity : ComponentActivity() {
val action = intent.action
val type = intent.type
if (Intent.ACTION_SEND == action && type != null) {
- Log.e(TAG, action)
- moreFragment = MoreFragment()
- if (type.equals("application/txt", ignoreCase = true)) {
- try {
- val uri = intent.getParcelableExtra(Intent.EXTRA_STREAM)
- val `is` = contentResolver.openInputStream(uri!!)
- val textBuilder = StringBuilder()
- val reader: Reader = BufferedReader(
- InputStreamReader(
- `is`, Charset.forName(
- StandardCharsets.UTF_8.name()
- )
- )
- )
- var c: Int
- while (reader.read().also { c = it } != -1) {
- textBuilder.append(c.toChar())
+ val loadingBottomSheet = BottomSheetDialog(this)
+ loadingBottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
+ loadingBottomSheet.setContentView(R.layout.please_wait_bottom_sheet)
+ loadingBottomSheet.show()
+ val cancel = loadingBottomSheet.findViewById(R.id.cancel)
+ cancel!!.setOnClickListener {
+ this.finish()
+ }
+
+ val inputQuery = intent.getStringExtra(Intent.EXTRA_TEXT)
+ try {
+ val result = resultViewModel.getItemByURL(inputQuery!!)
+ loadingBottomSheet.cancel()
+ showDownloadSheet(result)
+ }catch (e: Exception){
+ resultViewModel.deleteAll()
+ CoroutineScope(Dispatchers.IO).launch {
+ resultViewModel.parseQuery(inputQuery!!, true)
+ }
+
+ resultViewModel.items.observe(this) {
+ if (it.isNotEmpty()){
+ if(resultViewModel.itemCount.value!! == it.size){
+ loadingBottomSheet.cancel()
+ showDownloadSheet(it[0])
+ }
}
- val l = listOf(*textBuilder.toString().split("\n").toTypedArray())
- val lines = LinkedList(l)
- } catch (e: Exception) {
- e.printStackTrace()
}
- } else {
- //TODO
}
}
}
+ private fun showDownloadSheet(it: ResultItem){
+ if (sharedPreferences.getBoolean("download_card", true)){
+ val bottomSheet = DownloadBottomSheetDialog(it, DownloadViewModel.Type.video)
+ bottomSheet.show(supportFragmentManager, "downloadSingleSheet")
+ }else{
+ val downloadItem = downloadViewModel.createDownloadItemFromResult(it, DownloadViewModel.Type.video)
+ downloadViewModel.queueDownloads(listOf(downloadItem))
+ this.finish()
+ }
+ }
+ private fun askPermissions() {
+ if (Build.VERSION.SDK_INT < VERSION_CODES.TIRAMISU && !checkFilePermission()) {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
+ 1
+ )
+ }else if (!checkNotificationPermission()){
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.POST_NOTIFICATIONS),
+ 1
+ )
+ }
+ }
+
+
+ private fun createDefaultFolders(){
+ val audio = File(getString(R.string.music_path))
+ val video = File(getString(R.string.video_path))
+ val command = File(getString(R.string.command_path))
+
+ audio.mkdirs()
+ video.mkdirs()
+ command.mkdirs()
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ for (i in permissions.indices) {
+ if (permissions.contains(Manifest.permission.POST_NOTIFICATIONS)) break
+ if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
+ createPermissionRequestDialog()
+ }else{
+ createDefaultFolders()
+ }
+ }
+ }
private fun exit() {
finishAffinity()
exitProcess(0)
}
+ private fun checkFilePermission(): Boolean {
+ return (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ == PackageManager.PERMISSION_GRANTED)
+ }
+
+ private fun checkNotificationPermission(): Boolean {
+ return (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
+ == PackageManager.PERMISSION_GRANTED)
+ }
+
+ private fun createPermissionRequestDialog() {
+ val dialog = MaterialAlertDialogBuilder(this)
+ dialog.setTitle(getString(R.string.warning))
+ dialog.setMessage(getString(R.string.request_permission_desc))
+ dialog.setOnCancelListener { exit() }
+ dialog.setNegativeButton(getString(R.string.exit_app)) { _: DialogInterface?, _: Int -> exit() }
+ dialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
+ val intent = Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.fromParts("package", packageName, null)
+ )
+ startActivity(intent)
+ exitProcess(0)
+ }
+ dialog.show()
+ }
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ startActivity(Intent(this, MainActivity::class.java))
+ super.onConfigurationChanged(newConfig)
+ }
companion object {
private const val TAG = "ShareActivity"
- private lateinit var moreFragment: MoreFragment
- private lateinit var fm: FragmentManager
+
}
}
\ No newline at end of file
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 97cf8fed..7fdce1f9 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt
@@ -128,13 +128,14 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
resultViewModel.items.observe(viewLifecycleOwner) {
homeAdapter!!.submitList(it)
resultsList = it
- if(it.size > 1){
+ Log.e(TAG, resultViewModel.itemCount.toString())
+ if(resultViewModel.itemCount.value!! > 1){
if (it[0].playlistTitle.isNotEmpty() && it[0].playlistTitle != getString(R.string.trendingPlaylist)){
downloadAllFabCoordinator!!.visibility = VISIBLE
}else{
downloadAllFabCoordinator!!.visibility = GONE
}
- }else if (it.size == 1){
+ }else if (resultViewModel.itemCount.value!! == 1){
if (sharedPreferences!!.getBoolean("download_card", true)){
if(it.size == 1 && !firstBoot && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){
showSingleDownloadSheet(it[0], DownloadViewModel.Type.video)
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
index 999a7921..bac99288 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
@@ -14,17 +14,21 @@ import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
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.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.util.FileUtil
+import com.deniscerri.ytdlnis.util.UiUtil
import com.google.android.material.chip.Chip
import com.google.android.material.textfield.TextInputLayout
import kotlinx.coroutines.launch
@@ -34,9 +38,9 @@ class DownloadAudioFragment(private var resultItem: ResultItem) : Fragment() {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
- private var mainActivity: MainActivity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var fileUtil : FileUtil
+ private lateinit var uiUtil : UiUtil
private lateinit var title : TextInputLayout
private lateinit var author : TextInputLayout
@@ -56,10 +60,10 @@ class DownloadAudioFragment(private var resultItem: ResultItem) : Fragment() {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_audio, container, false)
activity = getActivity()
- mainActivity = activity as MainActivity?
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, Type.audio)
fileUtil = FileUtil()
+ uiUtil = UiUtil(fileUtil)
return fragmentView
}
@@ -109,8 +113,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem) : Fragment() {
audioPathResultLauncher.launch(intent)
}
- val format = view.findViewById(R.id.format)
- val formats = resultItem.formats.filter { it.format_note.contains("audio", ignoreCase = true) }
+ var formats = resultItem.formats.filter { it.format_note.contains("audio", ignoreCase = true) }
val containers = requireContext().resources.getStringArray(R.array.audio_containers)
val container = view.findViewById(R.id.downloadContainer)
@@ -118,49 +121,35 @@ class DownloadAudioFragment(private var resultItem: ResultItem) : Fragment() {
view.findViewById(R.id.container_textview)
-
+ val formatCard = view.findViewById(R.id.format_card_constraintLayout)
if (formats.isEmpty()) {
- format.visibility = View.GONE
+ formatCard.visibility = View.GONE
} else {
- val formatTitles = formats.map {
- if (it.format_note.contains("AUDIO_QUALITY_")) {
- it.format_note.replace(
- "AUDIO_QUALITY_",
- ""
- ) + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
- } else {
- it.format_note + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(
- it.filesize
- )
- }
- }
-
- val autoCompleteTextView =
- view.findViewById(R.id.format_textview)
- autoCompleteTextView?.setAdapter(
- ArrayAdapter(
- requireContext(),
- android.R.layout.simple_dropdown_item_1line,
- formatTitles
- )
- )
- if (formatTitles.isNotEmpty()) {
- autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
- }
- (format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
- AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
- downloadItem.format.format_note = formats[index].format_note
- downloadItem.format.format_id = formats[index].format_id
- downloadItem.format.filesize = formats[index].filesize
-
- if (containers.contains(formats[index].container)){
- downloadItem.format.container = formats[index].container
- containerAutoCompleteTextView.setText(formats[index].container, false)
+ val chosenFormat = formats[formats.lastIndex]
+ uiUtil.populateFormatCard(formatCard, chosenFormat)
+ val listener = object : OnFormatClickListener {
+ override fun onFormatClick(allFormats: List, item: Format) {
+ downloadItem.format = item
+
+ if (containers.contains(item.container)){
+ downloadItem.format.container = item.container
+ containerAutoCompleteTextView.setText(item.container, false)
}else{
downloadItem.format.container = containers[0]
containerAutoCompleteTextView.setText(containers[0], false)
}
+ uiUtil.populateFormatCard(formatCard, item)
+ formats = allFormats
+ }
+ }
+ formatCard.setOnClickListener{_ ->
+ formats.forEach {
+ Log.e("aa", it.toString())
}
+ val bottomSheet = FormatSelectionBottomSheetDialog(formats, listener)
+ bottomSheet.show(parentFragmentManager, "formatSheet")
+ }
+
}
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 33946b71..f92d9abd 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
@@ -16,12 +16,14 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.get
import androidx.core.view.size
import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
+import com.deniscerri.ytdlnis.receiver.ShareActivity
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton
@@ -57,12 +59,18 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
behavior = BottomSheetBehavior.from(view.parent as View)
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
- behavior.peekHeight = displayMetrics.heightPixels - 400
+ behavior.peekHeight = displayMetrics.heightPixels - 700
}
+
tabLayout = view.findViewById(R.id.download_tablayout)
viewPager2 = view.findViewById(R.id.download_viewpager)
+ (viewPager2.getChildAt(0) as? RecyclerView)?.apply {
+ isNestedScrollingEnabled = false
+ overScrollMode = View.OVER_SCROLL_NEVER
+ }
+
val fragmentManager = parentFragmentManager
fragmentAdapter = DownloadFragmentAdapter(
resultItem,
@@ -158,18 +166,18 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
}
private fun getDownloadItem() : DownloadItem{
- when(tabLayout.selectedTabPosition){
+ return when(tabLayout.selectedTabPosition){
0 -> {
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
- return f.downloadItem
+ f.downloadItem
}
1 -> {
val f = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
- return f.downloadItem
+ f.downloadItem
}
else -> {
val f = fragmentManager?.findFragmentByTag("f2") as DownloadCommandFragment
- return f.downloadItem
+ f.downloadItem
}
}
}
@@ -192,6 +200,9 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
}
}
+ if (activity is ShareActivity){
+ (activity as ShareActivity).finish()
+ }
}
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
index c19f4a00..de1fa368 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
@@ -35,7 +35,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem) : Fragment() {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
- private var mainActivity: MainActivity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var fileUtil : FileUtil
@@ -52,7 +51,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem) : Fragment() {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_command, container, false)
activity = getActivity()
- mainActivity = activity as MainActivity?
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, DownloadViewModel.Type.command)
fileUtil = FileUtil()
@@ -73,6 +71,9 @@ class DownloadCommandFragment(private val resultItem: ResultItem) : Fragment() {
downloadItem.format = Format(
chosenCommand!!.title,
"",
+ "",
+ "",
+ "",
0,
chosenCommand.content
)
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
index f6a2c767..269c2ab4 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
@@ -10,6 +10,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@@ -28,16 +29,16 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
+import com.deniscerri.ytdlnis.util.UiUtil
class DownloadVideoFragment(private val resultItem: ResultItem) : Fragment() {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
- private var mainActivity: MainActivity? = null
- private lateinit var resultViewModel : ResultViewModel
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var fileUtil : FileUtil
+ private lateinit var uiUtil : UiUtil
private lateinit var title : TextInputLayout
private lateinit var author : TextInputLayout
@@ -53,10 +54,10 @@ class DownloadVideoFragment(private val resultItem: ResultItem) : Fragment() {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_video, container, false)
activity = getActivity()
- mainActivity = activity as MainActivity?
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, Type.video)
fileUtil = FileUtil()
+ uiUtil = UiUtil(fileUtil)
return fragmentView
}
@@ -111,30 +112,12 @@ class DownloadVideoFragment(private val resultItem: ResultItem) : Fragment() {
if (formats.isEmpty()) {
val videoFormats = resources.getStringArray(R.array.video_formats)
val container = sharedPreferences.getString("video_format", "Default")
- videoFormats.forEach { formats.add(Format(it, container!!, 0, it)) }
+ videoFormats.forEach { formats.add(Format(it, container!!,"","", "",0, it)) }
}
- val formatTitles = formats.map {
- it.format_note + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
- }
-
-
downloadItem.format = formats[formats.lastIndex]
val containers = requireContext().resources.getStringArray(R.array.video_containers)
- val format = view.findViewById(R.id.format)
- val autoCompleteTextView =
- view.findViewById(R.id.format_textview)
- autoCompleteTextView?.setAdapter(
- ArrayAdapter(
- requireContext(),
- android.R.layout.simple_dropdown_item_1line,
- formatTitles
- )
- )
- if (formatTitles.isNotEmpty()) {
- autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
- }
val container = view.findViewById(R.id.downloadContainer)
val containerAutoCompleteTextView =
@@ -151,27 +134,27 @@ class DownloadVideoFragment(private val resultItem: ResultItem) : Fragment() {
val selectedContainer: String = downloadItem.format.container
containerAutoCompleteTextView!!.setText(selectedContainer, false)
- (format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
- AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
- downloadItem.format.format_note = formats[index].format_note
- downloadItem.format.format_id = formats[index].format_id
- downloadItem.format.filesize = formats[index].filesize
-
- if (containers.contains(formats[index].container)){
- downloadItem.format.container = formats[index].container
- containerAutoCompleteTextView.setText(formats[index].container, false)
+ val formatCard = view.findViewById(R.id.format_card_constraintLayout)
+ val chosenFormat = formats[formats.lastIndex]
+ uiUtil.populateFormatCard(formatCard, chosenFormat)
+ val listener = object : OnFormatClickListener {
+ override fun onFormatClick(allFormats: List, item: Format) {
+ downloadItem.format = item
+
+ if (containers.contains(item.container)){
+ downloadItem.format.container = item.container
+ containerAutoCompleteTextView.setText(item.container, false)
+ }else{
+ downloadItem.format.container = containers[0]
+ containerAutoCompleteTextView.setText(containers[0], false)
}
-
- }
-
- (container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
- AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
- downloadItem.format.container = containers[index]
+ uiUtil.populateFormatCard(formatCard, item)
}
-
-
-
-
+ }
+ formatCard.setOnClickListener{_ ->
+ val bottomSheet = FormatSelectionBottomSheetDialog(formats, listener)
+ bottomSheet.show(parentFragmentManager, "formatSheet")
+ }
val embedSubs = view.findViewById(R.id.embed_subtitles)
embedSubs!!.isChecked = downloadItem.videoPreferences.embedSubs
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt
new file mode 100644
index 00000000..73f75acc
--- /dev/null
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt
@@ -0,0 +1,104 @@
+package com.deniscerri.ytdlnis.ui.downloadcard
+
+import android.annotation.SuppressLint
+import android.app.DatePickerDialog
+import android.app.Dialog
+import android.app.TimePickerDialog
+import android.content.DialogInterface
+import android.os.Bundle
+import android.util.DisplayMetrics
+import android.util.Log
+import android.view.Display
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.Adapter
+import android.widget.Button
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.view.get
+import androidx.core.view.size
+import androidx.lifecycle.ViewModelProvider
+import androidx.viewpager2.widget.ViewPager2
+import com.deniscerri.ytdlnis.R
+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.viewmodel.DownloadViewModel
+import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
+import com.deniscerri.ytdlnis.util.FileUtil
+import com.deniscerri.ytdlnis.util.UiUtil
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.google.android.material.button.MaterialButton
+import com.google.android.material.datepicker.CalendarConstraints
+import com.google.android.material.datepicker.DateValidatorPointBackward
+import com.google.android.material.datepicker.DateValidatorPointForward
+import com.google.android.material.datepicker.MaterialDatePicker
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.timepicker.MaterialTimePicker
+import com.google.android.material.timepicker.TimeFormat
+import java.util.*
+
+
+class FormatSelectionBottomSheetDialog(private val formats: List, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
+ private lateinit var behavior: BottomSheetBehavior
+ private lateinit var fileUtil: FileUtil
+ private lateinit var uiUtil: UiUtil
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ fileUtil = FileUtil()
+ uiUtil = UiUtil(fileUtil)
+ }
+
+
+ @SuppressLint("RestrictedApi")
+ override fun setupDialog(dialog: Dialog, style: Int) {
+ super.setupDialog(dialog, style)
+ val view = LayoutInflater.from(context).inflate(R.layout.format_select_bottom_sheet, null)
+ dialog.setContentView(view)
+
+ dialog.setOnShowListener {
+ behavior = BottomSheetBehavior.from(view.parent as View)
+ val displayMetrics = DisplayMetrics()
+ requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
+ behavior.peekHeight = displayMetrics.heightPixels / 2
+ }
+
+ val linearLayout = view.findViewById(R.id.format_list_linear_layout)
+
+ for (i in formats.lastIndex downTo 0){
+ val it = formats[i]
+ val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
+ uiUtil.populateFormatCard(formatItem as ConstraintLayout, it)
+ formatItem.setOnClickListener{_ ->
+ listener.onFormatClick(formats, it)
+ dismiss()
+ }
+ linearLayout.addView(formatItem)
+ }
+ }
+
+
+
+ override fun onCancel(dialog: DialogInterface) {
+ super.onCancel(dialog)
+ cleanUp()
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ super.onDismiss(dialog)
+ cleanUp()
+ }
+
+
+ private fun cleanUp(){
+ parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("formatSheet")!!).commit()
+ }
+}
+
+interface OnFormatClickListener{
+ fun onFormatClick(allFormats: List, item: Format)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt
new file mode 100644
index 00000000..5b44e91d
--- /dev/null
+++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt
@@ -0,0 +1,30 @@
+package com.deniscerri.ytdlnis.util
+
+import android.view.View
+import android.widget.TextView
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.deniscerri.ytdlnis.R
+import com.deniscerri.ytdlnis.database.models.Format
+
+class UiUtil(private val fileUtil: FileUtil) {
+ fun populateFormatCard(formatCard : ConstraintLayout, chosenFormat: Format){
+ formatCard.findViewById(R.id.container).text = chosenFormat.container.uppercase()
+ formatCard.findViewById(R.id.format_note).text = chosenFormat.format_note.uppercase()
+ formatCard.findViewById(R.id.format_id).text = "id: ${chosenFormat.format_id}"
+ val codec =
+ if (chosenFormat.encoding != "") {
+ chosenFormat.encoding.uppercase()
+ }else if (chosenFormat.vcodec != "none" && chosenFormat.vcodec != ""){
+ chosenFormat.vcodec.uppercase()
+ } else {
+ chosenFormat.acodec.uppercase()
+ }
+ if (codec == "" || codec == "none"){
+ formatCard.findViewById(R.id.codec).visibility = View.GONE
+ }else{
+ formatCard.findViewById(R.id.codec).text = codec
+ }
+ formatCard.findViewById(R.id.file_size).text = fileUtil.convertFileSize(chosenFormat.filesize)
+
+ }
+}
\ No newline at end of file
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 50c52797..69870525 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt
@@ -114,11 +114,13 @@ class DownloadWorker(
DownloadViewModel.Type.audio -> {
request.addOption("-x")
var audioQualityId : String = downloadItem.format.format_id
- if (audioQualityId == "0" || audioQualityId.isEmpty()) audioQualityId = "ba"
- request.addOption("-f", audioQualityId)
+ if (audioQualityId.isEmpty() || audioQualityId == "0") audioQualityId = ""
+ if (audioQualityId.isNotEmpty()){
+ request.addOption("-f", audioQualityId)
+ }
val ext = downloadItem.format.container
- if(ext != context.getString(R.string.defaultValue)){
+ if(ext != context.getString(R.string.defaultValue) && ext != "webm"){
request.addOption("--audio-format", ext)
}else{
request.addOption("--audio-format", sharedPreferences.getString("audio_format", "mp3")!!)
diff --git a/app/src/main/res/layout/activity_share.xml b/app/src/main/res/layout/activity_share.xml
new file mode 100644
index 00000000..e2d336fa
--- /dev/null
+++ b/app/src/main/res/layout/activity_share.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/download_bottom_sheet.xml b/app/src/main/res/layout/download_bottom_sheet.xml
index 062ac769..0cd19daf 100644
--- a/app/src/main/res/layout/download_bottom_sheet.xml
+++ b/app/src/main/res/layout/download_bottom_sheet.xml
@@ -6,111 +6,102 @@
android:orientation="vertical"
android:layout_height="match_parent">
-
-
+ android:layout_marginHorizontal="20dp"
+ android:orientation="horizontal"
+ android:paddingTop="20dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/format_item.xml b/app/src/main/res/layout/format_item.xml
new file mode 100644
index 00000000..a538c14d
--- /dev/null
+++ b/app/src/main/res/layout/format_item.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/format_select_bottom_sheet.xml b/app/src/main/res/layout/format_select_bottom_sheet.xml
new file mode 100644
index 00000000..77513b1e
--- /dev/null
+++ b/app/src/main/res/layout/format_select_bottom_sheet.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_download_audio.xml b/app/src/main/res/layout/fragment_download_audio.xml
index 5c38a28b..4a14ae2f 100644
--- a/app/src/main/res/layout/fragment_download_audio.xml
+++ b/app/src/main/res/layout/fragment_download_audio.xml
@@ -1,95 +1,78 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ android:layout_height="match_parent"
+ android:padding="10dp"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ android:paddingBottom="10dp"
+ android:orientation="horizontal">
-
+ android:layout_weight="40"
+ android:hint="@string/author"
+ style="@style/Widget.Material3.TextInputLayout.FilledBox">
-
+
-
+
-
-
+
-
+
+
-
+
-
+
+
+
+
+ android:hint="@string/save_dir">
-
+
+
-
-
+ android:orientation="vertical"
+ >
-
+
-
-
+ app:singleLine="false"
+ android:layout_height="wrap_content">
-
+
+
-
-
+
+
+
-
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_download_video.xml b/app/src/main/res/layout/fragment_download_video.xml
index 38ba6d14..8a01e1c0 100644
--- a/app/src/main/res/layout/fragment_download_video.xml
+++ b/app/src/main/res/layout/fragment_download_video.xml
@@ -1,101 +1,102 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:paddingBottom="10dp">
+ android:inputType="text" />
+ android:orientation="horizontal"
+ android:paddingBottom="10dp">
+ android:hint="@string/author">
+ android:inputType="text" />
@@ -104,70 +105,58 @@
android:id="@+id/downloadContainer"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="0dp"
- android:layout_weight="45"
- android:paddingStart="10dp"
android:layout_height="wrap_content"
- android:hint="@string/container">
+ android:layout_weight="45"
+ android:hint="@string/container"
+ android:paddingStart="10dp">
+ app:simpleItems="@array/audio_containers" />
-
-
-
+ android:text="@string/video_format" />
-
+
+ android:paddingTop="10dp">
+ android:layout_height="wrap_content"
+ android:inputType="text" />
+ android:padding="10dp">
+ android:paddingBottom="5dp"
+ android:text="@string/adjust_video"
+ android:textSize="15sp" />
+ android:layout_height="wrap_content"
+ app:singleLine="false">
+ android:text="@string/embed_subtitles" />
+ android:text="@string/add_chapter" />
+ android:text="@string/save_thumb" />
@@ -215,4 +204,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/please_wait_bottom_sheet.xml b/app/src/main/res/layout/please_wait_bottom_sheet.xml
new file mode 100644
index 00000000..224c5ee1
--- /dev/null
+++ b/app/src/main/res/layout/please_wait_bottom_sheet.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index cb857761..b2609846 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -170,4 +170,7 @@
Language
Command Templates
Terminal
+ Format
+ Select Format
+ Please Wait
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 88768f6d..f0ae50a6 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -9,6 +9,14 @@
- 28dp
+
+