implemented work calls after processing downloads
This commit is contained in:
parent
5e47c98ec5
commit
544a8eab14
20 changed files with 926 additions and 246 deletions
|
|
@ -25,6 +25,7 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderService
|
import com.deniscerri.ytdlnis.service.IDownloaderService
|
||||||
|
import com.deniscerri.ytdlnis.ui.DownloadFragment
|
||||||
import com.deniscerri.ytdlnis.ui.HistoryFragment
|
import com.deniscerri.ytdlnis.ui.HistoryFragment
|
||||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
import com.deniscerri.ytdlnis.ui.HomeFragment
|
||||||
import com.deniscerri.ytdlnis.ui.MoreFragment
|
import com.deniscerri.ytdlnis.ui.MoreFragment
|
||||||
|
|
@ -46,6 +47,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
private lateinit var homeFragment: HomeFragment
|
private lateinit var homeFragment: HomeFragment
|
||||||
private lateinit var historyFragment: HistoryFragment
|
private lateinit var historyFragment: HistoryFragment
|
||||||
|
private lateinit var downloadFragment: DownloadFragment
|
||||||
private lateinit var workManager: WorkManager
|
private lateinit var workManager: WorkManager
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -61,6 +63,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
homeFragment = HomeFragment()
|
homeFragment = HomeFragment()
|
||||||
historyFragment = HistoryFragment()
|
historyFragment = HistoryFragment()
|
||||||
|
downloadFragment = DownloadFragment()
|
||||||
moreFragment = MoreFragment()
|
moreFragment = MoreFragment()
|
||||||
initFragments()
|
initFragments()
|
||||||
binding.bottomNavigationView.setOnItemSelectedListener { item: MenuItem ->
|
binding.bottomNavigationView.setOnItemSelectedListener { item: MenuItem ->
|
||||||
|
|
@ -77,10 +80,18 @@ class MainActivity : AppCompatActivity() {
|
||||||
if (lastFragment === historyFragment) {
|
if (lastFragment === historyFragment) {
|
||||||
historyFragment.scrollToTop()
|
historyFragment.scrollToTop()
|
||||||
} else {
|
} else {
|
||||||
this.title = getString(R.string.downloads)
|
this.title = getString(R.string.history)
|
||||||
}
|
}
|
||||||
replaceFragment(historyFragment)
|
replaceFragment(historyFragment)
|
||||||
}
|
}
|
||||||
|
R.id.downloads -> {
|
||||||
|
if (lastFragment === downloadFragment) {
|
||||||
|
downloadFragment.scrollToTop()
|
||||||
|
} else {
|
||||||
|
this.title = getString(R.string.downloads)
|
||||||
|
}
|
||||||
|
replaceFragment(downloadFragment)
|
||||||
|
}
|
||||||
R.id.more -> {
|
R.id.more -> {
|
||||||
if (lastFragment === moreFragment) {
|
if (lastFragment === moreFragment) {
|
||||||
val intent = Intent(context, SettingsActivity::class.java)
|
val intent = Intent(context, SettingsActivity::class.java)
|
||||||
|
|
@ -118,6 +129,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
Log.e(TAG, action)
|
Log.e(TAG, action)
|
||||||
homeFragment = HomeFragment()
|
homeFragment = HomeFragment()
|
||||||
historyFragment = HistoryFragment()
|
historyFragment = HistoryFragment()
|
||||||
|
downloadFragment = DownloadFragment()
|
||||||
moreFragment = MoreFragment()
|
moreFragment = MoreFragment()
|
||||||
if (type.equals("application/txt", ignoreCase = true)) {
|
if (type.equals("application/txt", ignoreCase = true)) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -152,9 +164,11 @@ class MainActivity : AppCompatActivity() {
|
||||||
fm.beginTransaction()
|
fm.beginTransaction()
|
||||||
.replace(R.id.frame_layout, homeFragment)
|
.replace(R.id.frame_layout, homeFragment)
|
||||||
.add(R.id.frame_layout, historyFragment)
|
.add(R.id.frame_layout, historyFragment)
|
||||||
|
.add(R.id.frame_layout, downloadFragment)
|
||||||
.add(R.id.frame_layout, moreFragment)
|
.add(R.id.frame_layout, moreFragment)
|
||||||
.hide(historyFragment)
|
.hide(historyFragment)
|
||||||
.hide(moreFragment)
|
.hide(moreFragment)
|
||||||
|
.hide(downloadFragment)
|
||||||
.commit()
|
.commit()
|
||||||
lastFragment = homeFragment
|
lastFragment = homeFragment
|
||||||
listeners = ArrayList()
|
listeners = ArrayList()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
import java.io.File
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<HistoryItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val checkedItems: ArrayList<Long>
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkedItems = ArrayList()
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.downloads_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.history_card, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val item = getItem(position)
|
||||||
|
val card = holder.cardView
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
|
||||||
|
val imageURL = item!!.thumb
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
if (imageURL.isNotEmpty()) {
|
||||||
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
|
} else {
|
||||||
|
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
|
||||||
|
}
|
||||||
|
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0))
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val itemTitle = card.findViewById<TextView>(R.id.downloads_title)
|
||||||
|
var title = item.title
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
itemTitle.text = title
|
||||||
|
|
||||||
|
// Bottom Info ----------------------------------
|
||||||
|
val bottomInfo = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||||
|
var info = item.author
|
||||||
|
if (item.duration.isNotEmpty()) {
|
||||||
|
if (item.author.isNotEmpty()) info += " • "
|
||||||
|
info += item.duration
|
||||||
|
}
|
||||||
|
bottomInfo.text = info
|
||||||
|
|
||||||
|
// TIME DOWNLOADED ----------------------------------
|
||||||
|
val datetime = card.findViewById<TextView>(R.id.downloads_info_time)
|
||||||
|
val time = item.time
|
||||||
|
val downloadedTime: String
|
||||||
|
if (time == 0L) {
|
||||||
|
downloadedTime = activity.getString(R.string.currently_downloading) + " " + item.type
|
||||||
|
} else {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
val date = Date(time * 1000L)
|
||||||
|
cal.time = date
|
||||||
|
val day = cal[Calendar.DAY_OF_MONTH]
|
||||||
|
val month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault())
|
||||||
|
val year = cal[Calendar.YEAR]
|
||||||
|
val formatter: DateFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||||
|
val timeString = formatter.format(date)
|
||||||
|
downloadedTime = "$day $month $year - $timeString"
|
||||||
|
}
|
||||||
|
datetime.text = downloadedTime
|
||||||
|
|
||||||
|
// BUTTON ----------------------------------
|
||||||
|
val buttonLayout = card.findViewById<LinearLayout>(R.id.downloads_download_button_layout)
|
||||||
|
val btn = buttonLayout.findViewById<MaterialButton>(R.id.downloads_download_button_type)
|
||||||
|
var filePresent = true
|
||||||
|
|
||||||
|
//IS IN THE FILE SYSTEM?
|
||||||
|
val path = item.downloadPath
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists() && path.isNotEmpty()) {
|
||||||
|
filePresent = false
|
||||||
|
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
||||||
|
init {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
thumbnail.alpha = 0.7f
|
||||||
|
}
|
||||||
|
if (item.type.isNotEmpty()) {
|
||||||
|
if (item.type == "audio") {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music)
|
||||||
|
} else {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (btn.hasOnClickListeners()) btn.setOnClickListener(null)
|
||||||
|
if (checkedItems.contains(item.id)) {
|
||||||
|
card.isChecked = true
|
||||||
|
card.strokeWidth = 5
|
||||||
|
} else {
|
||||||
|
card.isChecked = false
|
||||||
|
card.strokeWidth = 0
|
||||||
|
}
|
||||||
|
val finalFilePresent = filePresent
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
card.setOnClickListener {
|
||||||
|
if (checkedItems.size > 0) {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
} else {
|
||||||
|
onItemClickListener.onCardClick(item.id, finalFilePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCard(card: MaterialCardView, itemID: Long) {
|
||||||
|
if (card.isChecked) {
|
||||||
|
card.strokeWidth = 0
|
||||||
|
checkedItems.remove(itemID)
|
||||||
|
} else {
|
||||||
|
card.strokeWidth = 5
|
||||||
|
checkedItems.add(itemID)
|
||||||
|
}
|
||||||
|
card.isChecked = !card.isChecked
|
||||||
|
onItemClickListener.onCardSelect(itemID, card.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onCardClick(itemID: Long, isPresent: Boolean)
|
||||||
|
fun onCardSelect(itemID: Long, isChecked: Boolean)
|
||||||
|
fun onButtonClick(position: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun clearCheckeditems() {
|
||||||
|
for (i in 0 until itemCount){
|
||||||
|
val item = getItem(i)
|
||||||
|
if (checkedItems.find { it == item?.id } != null){
|
||||||
|
checkedItems.remove(item?.id)
|
||||||
|
notifyItemChanged(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedItems.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<HistoryItem> = object : DiffUtil.ItemCallback<HistoryItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
val ranged = arrayListOf(oldItem.id, newItem.id)
|
||||||
|
return ranged[0] == ranged[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
return oldItem.time == newItem.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import android.graphics.ColorMatrix
|
||||||
import android.graphics.ColorMatrixColorFilter
|
import android.graphics.ColorMatrixColorFilter
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
@ -111,6 +112,7 @@ class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activit
|
||||||
//IS IN THE FILE SYSTEM?
|
//IS IN THE FILE SYSTEM?
|
||||||
val path = item.downloadPath
|
val path = item.downloadPath
|
||||||
val file = File(path)
|
val file = File(path)
|
||||||
|
Log.e("aa", file.absolutePath + " " + file.isFile)
|
||||||
if (!file.exists() && path.isNotEmpty()) {
|
if (!file.exists() && path.isNotEmpty()) {
|
||||||
filePresent = false
|
filePresent = false
|
||||||
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
import java.io.File
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class QueuedDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<HistoryItem?, QueuedDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val checkedItems: ArrayList<Long>
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkedItems = ArrayList()
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.downloads_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.history_card, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val item = getItem(position)
|
||||||
|
val card = holder.cardView
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
|
||||||
|
val imageURL = item!!.thumb
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
if (imageURL.isNotEmpty()) {
|
||||||
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
|
} else {
|
||||||
|
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
|
||||||
|
}
|
||||||
|
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0))
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val itemTitle = card.findViewById<TextView>(R.id.downloads_title)
|
||||||
|
var title = item.title
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
itemTitle.text = title
|
||||||
|
|
||||||
|
// Bottom Info ----------------------------------
|
||||||
|
val bottomInfo = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||||
|
var info = item.author
|
||||||
|
if (item.duration.isNotEmpty()) {
|
||||||
|
if (item.author.isNotEmpty()) info += " • "
|
||||||
|
info += item.duration
|
||||||
|
}
|
||||||
|
bottomInfo.text = info
|
||||||
|
|
||||||
|
// TIME DOWNLOADED ----------------------------------
|
||||||
|
val datetime = card.findViewById<TextView>(R.id.downloads_info_time)
|
||||||
|
val time = item.time
|
||||||
|
val downloadedTime: String
|
||||||
|
if (time == 0L) {
|
||||||
|
downloadedTime = activity.getString(R.string.currently_downloading) + " " + item.type
|
||||||
|
} else {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
val date = Date(time * 1000L)
|
||||||
|
cal.time = date
|
||||||
|
val day = cal[Calendar.DAY_OF_MONTH]
|
||||||
|
val month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault())
|
||||||
|
val year = cal[Calendar.YEAR]
|
||||||
|
val formatter: DateFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||||
|
val timeString = formatter.format(date)
|
||||||
|
downloadedTime = "$day $month $year - $timeString"
|
||||||
|
}
|
||||||
|
datetime.text = downloadedTime
|
||||||
|
|
||||||
|
// BUTTON ----------------------------------
|
||||||
|
val buttonLayout = card.findViewById<LinearLayout>(R.id.downloads_download_button_layout)
|
||||||
|
val btn = buttonLayout.findViewById<MaterialButton>(R.id.downloads_download_button_type)
|
||||||
|
var filePresent = true
|
||||||
|
|
||||||
|
//IS IN THE FILE SYSTEM?
|
||||||
|
val path = item.downloadPath
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists() && path.isNotEmpty()) {
|
||||||
|
filePresent = false
|
||||||
|
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
||||||
|
init {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
thumbnail.alpha = 0.7f
|
||||||
|
}
|
||||||
|
if (item.type.isNotEmpty()) {
|
||||||
|
if (item.type == "audio") {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music)
|
||||||
|
} else {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (btn.hasOnClickListeners()) btn.setOnClickListener(null)
|
||||||
|
if (checkedItems.contains(item.id)) {
|
||||||
|
card.isChecked = true
|
||||||
|
card.strokeWidth = 5
|
||||||
|
} else {
|
||||||
|
card.isChecked = false
|
||||||
|
card.strokeWidth = 0
|
||||||
|
}
|
||||||
|
val finalFilePresent = filePresent
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
card.setOnClickListener {
|
||||||
|
if (checkedItems.size > 0) {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
} else {
|
||||||
|
onItemClickListener.onCardClick(item.id, finalFilePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCard(card: MaterialCardView, itemID: Long) {
|
||||||
|
if (card.isChecked) {
|
||||||
|
card.strokeWidth = 0
|
||||||
|
checkedItems.remove(itemID)
|
||||||
|
} else {
|
||||||
|
card.strokeWidth = 5
|
||||||
|
checkedItems.add(itemID)
|
||||||
|
}
|
||||||
|
card.isChecked = !card.isChecked
|
||||||
|
onItemClickListener.onCardSelect(itemID, card.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onCardClick(itemID: Long, isPresent: Boolean)
|
||||||
|
fun onCardSelect(itemID: Long, isChecked: Boolean)
|
||||||
|
fun onButtonClick(position: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun clearCheckeditems() {
|
||||||
|
for (i in 0 until itemCount){
|
||||||
|
val item = getItem(i)
|
||||||
|
if (checkedItems.find { it == item?.id } != null){
|
||||||
|
checkedItems.remove(item?.id)
|
||||||
|
notifyItemChanged(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedItems.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<HistoryItem> = object : DiffUtil.ItemCallback<HistoryItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
val ranged = arrayListOf(oldItem.id, newItem.id)
|
||||||
|
return ranged[0] == ranged[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
return oldItem.time == newItem.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ interface DownloadDao {
|
||||||
fun getProcessingDownloads() : LiveData<List<DownloadItem>>
|
fun getProcessingDownloads() : LiveData<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE workID=:workID")
|
@Query("SELECT * FROM downloads WHERE workID=:workID")
|
||||||
fun getDownloadByWorkId(workID: Int) : DownloadItem
|
fun getDownloadByWorkId(workID: Long) : DownloadItem
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
||||||
fun getDownloadById(id: Long) : DownloadItem
|
fun getDownloadById(id: Long) : DownloadItem
|
||||||
|
|
|
||||||
|
|
@ -26,5 +26,5 @@ data class DownloadItem(
|
||||||
val SaveThumb: Boolean,
|
val SaveThumb: Boolean,
|
||||||
@ColumnInfo(defaultValue = "Queued")
|
@ColumnInfo(defaultValue = "Queued")
|
||||||
var status: String,
|
var status: String,
|
||||||
val workID: Int
|
var workID: Long
|
||||||
)
|
)
|
||||||
|
|
@ -27,7 +27,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
downloadDao.update(item)
|
downloadDao.update(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDownloadByWorkID(workID: Int) : DownloadItem{
|
fun getDownloadByWorkID(workID: Long) : DownloadItem{
|
||||||
return downloadDao.getDownloadByWorkId(workID)
|
return downloadDao.getDownloadByWorkId(workID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
282
app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadFragment.kt
Normal file
282
app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadFragment.kt
Normal file
|
|
@ -0,0 +1,282 @@
|
||||||
|
package com.deniscerri.ytdlnis.ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.*
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.*
|
||||||
|
import android.view.View.*
|
||||||
|
import android.widget.*
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.adapter.ActiveDownloadAdapter
|
||||||
|
import com.deniscerri.ytdlnis.adapter.QueuedDownloadAdapter
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import com.deniscerri.ytdlnis.databinding.FragmentHistoryBinding
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.facebook.shimmer.ShimmerFrameLayout
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.chip.ChipGroup
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fragment representing a list of Items.
|
||||||
|
*/
|
||||||
|
class DownloadFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, QueuedDownloadAdapter.OnItemClickListener,
|
||||||
|
OnClickListener, OnLongClickListener {
|
||||||
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
|
|
||||||
|
private var downloading = false
|
||||||
|
private var fragmentView: View? = null
|
||||||
|
private var activity: Activity? = null
|
||||||
|
private var mainActivity: MainActivity? = null
|
||||||
|
private var fragmentContext: Context? = null
|
||||||
|
private var layoutinflater: LayoutInflater? = null
|
||||||
|
private var shimmerCards: ShimmerFrameLayout? = null
|
||||||
|
private var topAppBar: MaterialToolbar? = null
|
||||||
|
private var activeRecyclerView: RecyclerView? = null
|
||||||
|
private var othersRecyclerView: RecyclerView? = null
|
||||||
|
private var downloadsAdapter: ActiveDownloadAdapter? = null
|
||||||
|
private var queuedDownloadsAdapter: QueuedDownloadAdapter? = null
|
||||||
|
private var bottomSheet: BottomSheetDialog? = null
|
||||||
|
private var sortSheet: BottomSheetDialog? = null
|
||||||
|
private var uiHandler: Handler? = null
|
||||||
|
private var noResults: RelativeLayout? = null
|
||||||
|
private var websiteGroup: ChipGroup? = null
|
||||||
|
private var downloadsList: List<DownloadItem?>? = null
|
||||||
|
private var allDownloadsList: List<DownloadItem?>? = null
|
||||||
|
private var selectedObjects: ArrayList<DownloadItem>? = null
|
||||||
|
private var deleteFab: ExtendedFloatingActionButton? = null
|
||||||
|
private var fileUtil: FileUtil? = null
|
||||||
|
|
||||||
|
private var _binding : FragmentHistoryBinding? = null
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentHistoryBinding.inflate(inflater, container, false)
|
||||||
|
fragmentView = inflater.inflate(R.layout.fragment_downloads, container, false)
|
||||||
|
activity = getActivity()
|
||||||
|
mainActivity = activity as MainActivity?
|
||||||
|
|
||||||
|
return fragmentView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
fragmentContext = context
|
||||||
|
layoutinflater = LayoutInflater.from(context)
|
||||||
|
topAppBar = view.findViewById(R.id.downloads_toolbar)
|
||||||
|
noResults = view.findViewById(R.id.no_results)
|
||||||
|
websiteGroup = view.findViewById(R.id.website_chip_group)
|
||||||
|
deleteFab = view.findViewById(R.id.delete_selected_fab)
|
||||||
|
fileUtil = FileUtil()
|
||||||
|
deleteFab?.tag = "deleteSelected"
|
||||||
|
deleteFab?.setOnClickListener(this)
|
||||||
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
selectedObjects = ArrayList()
|
||||||
|
downloading = mainActivity!!.isDownloadServiceRunning()
|
||||||
|
|
||||||
|
|
||||||
|
downloadsList = mutableListOf()
|
||||||
|
allDownloadsList = mutableListOf()
|
||||||
|
|
||||||
|
downloadsAdapter =
|
||||||
|
ActiveDownloadAdapter(
|
||||||
|
this,
|
||||||
|
requireActivity()
|
||||||
|
)
|
||||||
|
activeRecyclerView = view.findViewById(R.id.recyclerviewactivedownloads)
|
||||||
|
activeRecyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
activeRecyclerView?.adapter = downloadsAdapter
|
||||||
|
|
||||||
|
queuedDownloadsAdapter =
|
||||||
|
QueuedDownloadAdapter(
|
||||||
|
this,
|
||||||
|
requireActivity()
|
||||||
|
)
|
||||||
|
othersRecyclerView = view.findViewById(R.id.recyclerviewotherdownloads)
|
||||||
|
othersRecyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
othersRecyclerView?.adapter = queuedDownloadsAdapter
|
||||||
|
|
||||||
|
noResults?.visibility = GONE
|
||||||
|
shimmerCards?.visibility = GONE
|
||||||
|
|
||||||
|
|
||||||
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
downloadViewModel.activeDownloads.observe(viewLifecycleOwner){
|
||||||
|
// update active
|
||||||
|
}
|
||||||
|
downloadViewModel.queuedDownloads.observe(viewLifecycleOwner){
|
||||||
|
// update queued
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scrollToTop() {
|
||||||
|
activeRecyclerView!!.scrollToPosition(0)
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
(topAppBar!!.parent as AppBarLayout).setExpanded(
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(v: View): Boolean {
|
||||||
|
val id = v.id
|
||||||
|
if (id == R.id.bottom_sheet_link) {
|
||||||
|
copyLinkToClipBoard(v.tag as Long)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeSelectedItems() {
|
||||||
|
// if (bottomSheet != null) bottomSheet!!.hide()
|
||||||
|
// val deleteFile = booleanArrayOf(false)
|
||||||
|
// val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
// deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items))
|
||||||
|
// deleteDialog.setMultiChoiceItems(
|
||||||
|
// arrayOf(getString(R.string.delete_files_too)),
|
||||||
|
// booleanArrayOf(false)
|
||||||
|
// ) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
|
||||||
|
// deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
// deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
// for (item in selectedObjects!!){
|
||||||
|
// historyViewModel.delete(item, deleteFile[0])
|
||||||
|
// }
|
||||||
|
// selectedObjects = ArrayList()
|
||||||
|
// historyAdapter!!.clearCheckeditems()
|
||||||
|
// deleteFab!!.visibility = GONE
|
||||||
|
// }
|
||||||
|
// deleteDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeItem(id: Long) {
|
||||||
|
// if (bottomSheet != null) bottomSheet!!.hide()
|
||||||
|
// val deleteFile = booleanArrayOf(false)
|
||||||
|
// val v = findItem(id)
|
||||||
|
// val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
// deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + v!!.title + "\"!")
|
||||||
|
// deleteDialog.setMultiChoiceItems(
|
||||||
|
// arrayOf(getString(R.string.delete_file_too)),
|
||||||
|
// booleanArrayOf(false)
|
||||||
|
// ) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
|
||||||
|
// deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
// deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
// historyViewModel.delete(v, deleteFile[0])
|
||||||
|
// }
|
||||||
|
// deleteDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyLinkToClipBoard(id: Long) {
|
||||||
|
val url = findItem(id)?.url
|
||||||
|
val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = ClipData.newPlainText(getString(R.string.url), url)
|
||||||
|
clipboard.setPrimaryClip(clip)
|
||||||
|
if (bottomSheet != null) bottomSheet!!.hide()
|
||||||
|
Toast.makeText(context, getString(R.string.link_copied_to_clipboard), Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openLinkIntent(id: Long) {
|
||||||
|
val url = findItem(id)?.url
|
||||||
|
val i = Intent(Intent.ACTION_VIEW)
|
||||||
|
i.data = Uri.parse(url)
|
||||||
|
if (bottomSheet != null) bottomSheet!!.hide()
|
||||||
|
startActivity(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openFileIntent(id: Long) {
|
||||||
|
val downloadPath = findItem(id)!!.downloadPath
|
||||||
|
val file = File(downloadPath)
|
||||||
|
val uri = FileProvider.getUriForFile(
|
||||||
|
fragmentContext!!,
|
||||||
|
fragmentContext!!.packageName + ".fileprovider",
|
||||||
|
file
|
||||||
|
)
|
||||||
|
val mime = mainActivity!!.contentResolver.getType(uri)
|
||||||
|
val i = Intent(Intent.ACTION_VIEW)
|
||||||
|
i.setDataAndType(uri, mime)
|
||||||
|
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
startActivity(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCardClick(videoID: Long, isPresent: Boolean) {
|
||||||
|
bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||||
|
bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
bottomSheet!!.setContentView(R.layout.history_item_details_bottom_sheet)
|
||||||
|
val video = findItem(videoID)
|
||||||
|
val title = bottomSheet!!.findViewById<TextView>(R.id.bottom_sheet_title)
|
||||||
|
title!!.text = video!!.title
|
||||||
|
val author = bottomSheet!!.findViewById<TextView>(R.id.bottom_sheet_author)
|
||||||
|
author!!.text = video.author
|
||||||
|
val link = bottomSheet!!.findViewById<Button>(R.id.bottom_sheet_link)
|
||||||
|
val url = video.url
|
||||||
|
link!!.text = url
|
||||||
|
link.tag = videoID
|
||||||
|
link.setOnClickListener(this)
|
||||||
|
link.setOnLongClickListener(this)
|
||||||
|
val remove = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_remove_button)
|
||||||
|
remove!!.tag = videoID
|
||||||
|
remove.setOnClickListener(this)
|
||||||
|
val openFile = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_open_file_button)
|
||||||
|
openFile!!.tag = videoID
|
||||||
|
openFile.setOnClickListener(this)
|
||||||
|
if (!isPresent) openFile.visibility = GONE
|
||||||
|
bottomSheet!!.show()
|
||||||
|
bottomSheet!!.window!!.setLayout(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCardSelect(videoID: Long, isChecked: Boolean) {
|
||||||
|
val item = findItem(videoID)
|
||||||
|
if (isChecked) selectedObjects!!.add(item!!)
|
||||||
|
else selectedObjects!!.remove(item)
|
||||||
|
if (selectedObjects!!.size > 1) {
|
||||||
|
deleteFab!!.visibility = VISIBLE
|
||||||
|
} else {
|
||||||
|
deleteFab!!.visibility = GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onButtonClick(position: Int) {
|
||||||
|
// val vid = downloadsObjects!![position]
|
||||||
|
// try {
|
||||||
|
// //mainActivity!!.removeItemFromDownloadQueue(vid, vid!!.downloadedType)
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// val info = DownloadInfo()
|
||||||
|
// info.video = vid
|
||||||
|
// info.downloadType = vid!!.downloadedType
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findItem(id : Long): DownloadItem? {
|
||||||
|
return downloadsList?.find { it?.id == id }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "downloadsFragment"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(p0: View?) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,7 +42,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
OnClickListener, OnLongClickListener {
|
OnClickListener, OnLongClickListener {
|
||||||
private lateinit var historyViewModel : HistoryViewModel
|
private lateinit var historyViewModel : HistoryViewModel
|
||||||
|
|
||||||
private var downloading = false
|
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private var mainActivity: MainActivity? = null
|
private var mainActivity: MainActivity? = null
|
||||||
|
|
@ -58,8 +57,8 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
private var noResults: RelativeLayout? = null
|
private var noResults: RelativeLayout? = null
|
||||||
private var selectionChips: LinearLayout? = null
|
private var selectionChips: LinearLayout? = null
|
||||||
private var websiteGroup: ChipGroup? = null
|
private var websiteGroup: ChipGroup? = null
|
||||||
private var downloadsList: List<HistoryItem?>? = null
|
private var historyList: List<HistoryItem?>? = null
|
||||||
private var allDownloadsList: List<HistoryItem?>? = null
|
private var allhistoryList: List<HistoryItem?>? = null
|
||||||
private var selectedObjects: ArrayList<HistoryItem>? = null
|
private var selectedObjects: ArrayList<HistoryItem>? = null
|
||||||
private var deleteFab: ExtendedFloatingActionButton? = null
|
private var deleteFab: ExtendedFloatingActionButton? = null
|
||||||
private var fileUtil: FileUtil? = null
|
private var fileUtil: FileUtil? = null
|
||||||
|
|
@ -83,10 +82,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
|
|
||||||
fragmentContext = context
|
fragmentContext = context
|
||||||
layoutinflater = LayoutInflater.from(context)
|
layoutinflater = LayoutInflater.from(context)
|
||||||
shimmerCards = view.findViewById(R.id.shimmer_downloads_framelayout)
|
shimmerCards = view.findViewById(R.id.shimmer_history_framelayout)
|
||||||
topAppBar = view.findViewById(R.id.downloads_toolbar)
|
topAppBar = view.findViewById(R.id.history_toolbar)
|
||||||
noResults = view.findViewById(R.id.downloads_no_results)
|
noResults = view.findViewById(R.id.no_results)
|
||||||
selectionChips = view.findViewById(R.id.downloads_selection_chips)
|
selectionChips = view.findViewById(R.id.history_selection_chips)
|
||||||
websiteGroup = view.findViewById(R.id.website_chip_group)
|
websiteGroup = view.findViewById(R.id.website_chip_group)
|
||||||
deleteFab = view.findViewById(R.id.delete_selected_fab)
|
deleteFab = view.findViewById(R.id.delete_selected_fab)
|
||||||
fileUtil = FileUtil()
|
fileUtil = FileUtil()
|
||||||
|
|
@ -94,18 +93,17 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
deleteFab?.setOnClickListener(this)
|
deleteFab?.setOnClickListener(this)
|
||||||
uiHandler = Handler(Looper.getMainLooper())
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
downloading = mainActivity!!.isDownloadServiceRunning()
|
|
||||||
|
|
||||||
|
|
||||||
downloadsList = mutableListOf()
|
historyList = mutableListOf()
|
||||||
allDownloadsList = mutableListOf()
|
allhistoryList = mutableListOf()
|
||||||
|
|
||||||
historyAdapter =
|
historyAdapter =
|
||||||
HistoryAdapter(
|
HistoryAdapter(
|
||||||
this,
|
this,
|
||||||
requireActivity()
|
requireActivity()
|
||||||
)
|
)
|
||||||
recyclerView = view.findViewById(R.id.recyclerviewdownloadss)
|
recyclerView = view.findViewById(R.id.recyclerviewhistorys)
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
recyclerView?.adapter = historyAdapter
|
recyclerView?.adapter = historyAdapter
|
||||||
|
|
||||||
|
|
@ -116,7 +114,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
|
|
||||||
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
|
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
|
||||||
historyViewModel.allItems.observe(viewLifecycleOwner) {
|
historyViewModel.allItems.observe(viewLifecycleOwner) {
|
||||||
allDownloadsList = it
|
allhistoryList = it
|
||||||
if(it.isEmpty()){
|
if(it.isEmpty()){
|
||||||
noResults!!.visibility = VISIBLE
|
noResults!!.visibility = VISIBLE
|
||||||
selectionChips!!.visibility = GONE
|
selectionChips!!.visibility = GONE
|
||||||
|
|
@ -130,7 +128,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
|
|
||||||
historyViewModel.getFilteredList().observe(viewLifecycleOwner) {
|
historyViewModel.getFilteredList().observe(viewLifecycleOwner) {
|
||||||
historyAdapter!!.submitList(it)
|
historyAdapter!!.submitList(it)
|
||||||
downloadsList = it
|
historyList = it
|
||||||
}
|
}
|
||||||
|
|
||||||
initMenu()
|
initMenu()
|
||||||
|
|
@ -158,14 +156,14 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
topAppBar!!.menu.findItem(R.id.search_downloads)
|
topAppBar!!.menu.findItem(R.id.search_history)
|
||||||
.setOnActionExpandListener(onActionExpandListener)
|
.setOnActionExpandListener(onActionExpandListener)
|
||||||
val searchView = topAppBar!!.menu.findItem(R.id.search_downloads).actionView as SearchView?
|
val searchView = topAppBar!!.menu.findItem(R.id.search_history).actionView as SearchView?
|
||||||
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
||||||
searchView.queryHint = getString(R.string.search_history_hint)
|
searchView.queryHint = getString(R.string.search_history_hint)
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
topAppBar!!.menu.findItem(R.id.search_downloads).collapseActionView()
|
topAppBar!!.menu.findItem(R.id.search_history).collapseActionView()
|
||||||
historyViewModel.setQueryFilter(query)
|
historyViewModel.setQueryFilter(query)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -178,8 +176,8 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
topAppBar!!.setOnClickListener { scrollToTop() }
|
topAppBar!!.setOnClickListener { scrollToTop() }
|
||||||
topAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
|
topAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
|
||||||
when (m.itemId) {
|
when (m.itemId) {
|
||||||
R.id.remove_downloads -> {
|
R.id.remove_history -> {
|
||||||
if(allDownloadsList!!.isEmpty()){
|
if(allhistoryList!!.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
|
@ -192,8 +190,8 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
deleteDialog.show()
|
deleteDialog.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.remove_deleted_downloads -> {
|
R.id.remove_deleted_history -> {
|
||||||
if(allDownloadsList!!.isEmpty()){
|
if(allhistoryList!!.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
|
@ -207,7 +205,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.remove_duplicates -> {
|
R.id.remove_duplicates -> {
|
||||||
if(allDownloadsList!!.isEmpty()){
|
if(allhistoryList!!.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
|
@ -283,7 +281,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
if (!websites.contains(item.website)) websites.add(item.website)
|
if (!websites.contains(item.website)) websites.add(item.website)
|
||||||
}
|
}
|
||||||
websiteGroup!!.removeAllViews()
|
websiteGroup!!.removeAllViews()
|
||||||
//val websites = downloadsRecyclerViewAdapter!!.websites
|
//val websites = historyRecyclerViewAdapter!!.websites
|
||||||
for (i in websites.indices) {
|
for (i in websites.indices) {
|
||||||
val w = websites[i]
|
val w = websites[i]
|
||||||
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
|
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
|
||||||
|
|
@ -441,7 +439,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onButtonClick(position: Int) {
|
override fun onButtonClick(position: Int) {
|
||||||
// val vid = downloadsObjects!![position]
|
// val vid = historyObjects!![position]
|
||||||
// try {
|
// try {
|
||||||
// //mainActivity!!.removeItemFromDownloadQueue(vid, vid!!.downloadedType)
|
// //mainActivity!!.removeItemFromDownloadQueue(vid, vid!!.downloadedType)
|
||||||
// } catch (e: Exception) {
|
// } catch (e: Exception) {
|
||||||
|
|
@ -452,10 +450,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findItem(id : Long): HistoryItem? {
|
private fun findItem(id : Long): HistoryItem? {
|
||||||
return downloadsList?.find { it?.id == id }
|
return historyList?.find { it?.id == id }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "downloadsFragment"
|
private const val TAG = "historyFragment"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
|
@ -22,12 +23,10 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
||||||
import com.deniscerri.ytdlnis.service.DownloadInfo
|
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
|
@ -37,14 +36,10 @@ import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.ChipGroup
|
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
||||||
private var progressBar: LinearProgressIndicator? = null
|
|
||||||
private var inputQuery: String? = null
|
private var inputQuery: String? = null
|
||||||
private var inputQueries: LinkedList<String?>? = null
|
private var inputQueries: LinkedList<String?>? = null
|
||||||
private var inputQueriesLength = 0
|
private var inputQueriesLength = 0
|
||||||
|
|
@ -56,7 +51,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
private var homeFabs: CoordinatorLayout? = null
|
private var homeFabs: CoordinatorLayout? = null
|
||||||
private var infoUtil: InfoUtil? = null
|
private var infoUtil: InfoUtil? = null
|
||||||
private var downloadQueue: ArrayList<ResultItem>? = null
|
private var downloadQueue: ArrayList<ResultItem>? = null
|
||||||
private var downloadInfo: DownloadInfo? = null
|
|
||||||
|
|
||||||
private lateinit var resultViewModel : ResultViewModel
|
private lateinit var resultViewModel : ResultViewModel
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
|
|
@ -70,17 +64,12 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
private var shimmerCards: ShimmerFrameLayout? = null
|
private var shimmerCards: ShimmerFrameLayout? = null
|
||||||
private var topAppBar: MaterialToolbar? = null
|
private var topAppBar: MaterialToolbar? = null
|
||||||
private var recyclerView: RecyclerView? = null
|
private var recyclerView: RecyclerView? = null
|
||||||
private var bottomSheet: BottomSheetDialog? = null
|
|
||||||
private var uiHandler: Handler? = null
|
private var uiHandler: Handler? = null
|
||||||
private var noResults: RelativeLayout? = null
|
|
||||||
private var selectionChips: LinearLayout? = null
|
|
||||||
private var websiteGroup: ChipGroup? = null
|
|
||||||
private var resultsList: List<ResultItem?>? = null
|
private var resultsList: List<ResultItem?>? = null
|
||||||
private var selectedObjects: ArrayList<ResultItem>? = null
|
private var selectedObjects: ArrayList<ResultItem>? = null
|
||||||
private var deleteFab: ExtendedFloatingActionButton? = null
|
|
||||||
private var fileUtil: FileUtil? = null
|
private var fileUtil: FileUtil? = null
|
||||||
private var firstBoot = true
|
private var firstBoot = true
|
||||||
|
private var sharedPreferences: SharedPreferences? = null
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
|
@ -99,15 +88,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
|
|
||||||
fragmentContext = context
|
fragmentContext = context
|
||||||
layoutinflater = LayoutInflater.from(context)
|
layoutinflater = LayoutInflater.from(context)
|
||||||
shimmerCards = view.findViewById(R.id.shimmer_downloads_framelayout)
|
|
||||||
topAppBar = view.findViewById(R.id.downloads_toolbar)
|
topAppBar = view.findViewById(R.id.downloads_toolbar)
|
||||||
noResults = view.findViewById(R.id.downloads_no_results)
|
|
||||||
selectionChips = view.findViewById(R.id.downloads_selection_chips)
|
|
||||||
websiteGroup = view.findViewById(R.id.website_chip_group)
|
|
||||||
deleteFab = view.findViewById(R.id.delete_selected_fab)
|
|
||||||
fileUtil = FileUtil()
|
fileUtil = FileUtil()
|
||||||
deleteFab?.tag = "deleteSelected"
|
|
||||||
deleteFab?.setOnClickListener(this)
|
|
||||||
uiHandler = Handler(Looper.getMainLooper())
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
downloading = mainActivity!!.isDownloadServiceRunning()
|
downloading = mainActivity!!.isDownloadServiceRunning()
|
||||||
|
|
@ -118,6 +100,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
resultsList = mutableListOf()
|
resultsList = mutableListOf()
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
|
|
||||||
|
sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
|
|
||||||
//initViews
|
//initViews
|
||||||
shimmerCards = view.findViewById(R.id.shimmer_results_framelayout)
|
shimmerCards = view.findViewById(R.id.shimmer_results_framelayout)
|
||||||
topAppBar = view.findViewById(R.id.home_toolbar)
|
topAppBar = view.findViewById(R.id.home_toolbar)
|
||||||
|
|
@ -143,8 +127,10 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
}else{
|
}else{
|
||||||
downloadAllFabCoordinator!!.visibility = GONE
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
}
|
}
|
||||||
}else if(it.size == 1 && !firstBoot && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){
|
}else if (sharedPreferences!!.getBoolean("download_card", true)){
|
||||||
showSingleDownloadSheet(it[0], "audio")
|
if(it.size == 1 && !firstBoot && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){
|
||||||
|
showSingleDownloadSheet(it[0], "audio")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
firstBoot = false
|
firstBoot = false
|
||||||
}
|
}
|
||||||
|
|
@ -338,9 +324,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// } catch (ignored: Exception) {
|
// } catch (ignored: Exception) {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
val sharedPreferences =
|
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
|
||||||
if (sharedPreferences.getBoolean("download_card", true)) {
|
|
||||||
// selectedObjects!!.clear()
|
// selectedObjects!!.clear()
|
||||||
// selectedObjects!!.add(item!!)
|
// selectedObjects!!.add(item!!)
|
||||||
//showConfigureSingleDownloadCard(createDownloadItem(item!!, type), item)
|
//showConfigureSingleDownloadCard(createDownloadItem(item!!, type), item)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.SystemClock
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
@ -15,10 +16,15 @@ import androidx.fragment.app.FragmentTransaction
|
||||||
import androidx.fragment.app.findFragment
|
import androidx.fragment.app.findFragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.ExistingWorkPolicy
|
||||||
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import com.deniscerri.ytdlnis.work.DownloadWorker
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
|
@ -99,27 +105,20 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
|
||||||
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
downloadItem.status = DownloadRepository.status.Queued.toString()
|
downloadItem.status = DownloadRepository.status.Queued.toString()
|
||||||
|
val workID = SystemClock.uptimeMillis()
|
||||||
|
downloadItem.workID = workID
|
||||||
downloadViewModel.insertDownload(downloadItem)
|
downloadViewModel.insertDownload(downloadItem)
|
||||||
|
|
||||||
|
val workRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
|
||||||
|
.setInputData(Data.Builder().putLong("workID", workID).build())
|
||||||
|
.build()
|
||||||
|
WorkManager.getInstance(requireContext()).beginUniqueWork(
|
||||||
|
downloadItem.id.toString(),
|
||||||
|
ExistingWorkPolicy.KEEP,
|
||||||
|
workRequest
|
||||||
|
).enqueue()
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
||||||
|
|
||||||
// for (i in selectedObjects!!.indices) {
|
|
||||||
// val vid = findVideo(
|
|
||||||
// selectedObjects!![i]!!.getURL()
|
|
||||||
// )
|
|
||||||
// vid!!.downloadedType = type
|
|
||||||
// updateDownloadingStatusOnResult(vid, type, true)
|
|
||||||
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
|
||||||
// downloadQueue!!.add(vid)
|
|
||||||
// }
|
|
||||||
// selectedObjects = ArrayList()
|
|
||||||
// homeAdapter!!.clearCheckedVideos()
|
|
||||||
// downloadFabs!!.visibility = View.GONE
|
|
||||||
// if (isStoragePermissionGranted) {
|
|
||||||
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
|
||||||
// downloadQueue!!.clear()
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ package com.deniscerri.ytdlnis.util
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
|
import android.util.Log
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
|
@ -11,6 +13,8 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.StandardCopyOption
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import kotlin.math.log10
|
import kotlin.math.log10
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
@ -54,19 +58,14 @@ class FileUtil() {
|
||||||
return formattedPath.toString()
|
return formattedPath.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scanMedia(video: DownloadItem, context: Context) : String {
|
fun scanMedia(destDir: String, context: Context) : String {
|
||||||
val files = ArrayList<File>()
|
val files = ArrayList<File>()
|
||||||
val title: String = video.title.replace("[^a-zA-Z0-9]".toRegex(), "")
|
val path = File(formatPath(destDir))
|
||||||
var pathTmp: String
|
|
||||||
val path = File(video.downloadPath)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (file in path.listFiles()!!) {
|
for (file in path.listFiles()!!) {
|
||||||
if (file.isFile) {
|
if (file.isFile) {
|
||||||
pathTmp = file.absolutePath.replace("[^a-zA-Z0-9]".toRegex(), "")
|
files.add(file)
|
||||||
if (pathTmp.contains(title)) {
|
|
||||||
files.add(file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,47 +79,59 @@ class FileUtil() {
|
||||||
|
|
||||||
return context.getString(R.string.unfound_file);
|
return context.getString(R.string.unfound_file);
|
||||||
}
|
}
|
||||||
fun moveFile(originDir : File, context:Context, destDir : Uri, progress: (p: Int) -> Unit){
|
fun moveFile(originDir: File, context: Context, destDir: String, progress: (p: Int) -> Unit){
|
||||||
originDir.listFiles()?.forEach {
|
originDir.listFiles()?.forEach {
|
||||||
val mimeType =
|
|
||||||
MimeTypeMap.getSingleton().getMimeTypeFromExtension(it.extension) ?: "*/*"
|
|
||||||
|
|
||||||
if (it.name.equals("rList")){
|
if (it.name.equals("rList")){
|
||||||
it.delete()
|
it.delete()
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
val destUri = DocumentsContract.createDocument(
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||||
context.contentResolver,
|
val f = File(formatPath(destDir)+"/"+it.name)
|
||||||
destDir,
|
if (!f.exists()) f.mkdir()
|
||||||
mimeType,
|
Files.move(it.toPath(), f.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||||
it.name
|
progress(100)
|
||||||
) ?: return@forEach
|
}else{
|
||||||
|
val mimeType =
|
||||||
|
MimeTypeMap.getSingleton().getMimeTypeFromExtension(it.extension) ?: "*/*"
|
||||||
|
|
||||||
val inputStream = it.inputStream()
|
val destination = Uri.parse(destDir).run {
|
||||||
val outputStream = context.contentResolver.openOutputStream(destUri) ?: return@forEach
|
DocumentsContract.buildChildDocumentsUriUsingTree(this, DocumentsContract.getTreeDocumentId(this))
|
||||||
val fileLength = it.length()
|
|
||||||
var bytesCopied: Long = 0
|
|
||||||
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
|
|
||||||
var bytes = inputStream.read(buffer)
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (bytes >= 0) {
|
|
||||||
outputStream.write(buffer, 0, bytes)
|
|
||||||
bytesCopied += bytes
|
|
||||||
progress((bytesCopied * 100 / fileLength).toInt())
|
|
||||||
bytes = inputStream.read(buffer)
|
|
||||||
}
|
}
|
||||||
}catch (e : Exception){
|
|
||||||
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
val destUri = DocumentsContract.createDocument(
|
||||||
|
context.contentResolver,
|
||||||
|
destination,
|
||||||
|
mimeType,
|
||||||
|
it.name
|
||||||
|
) ?: return@forEach
|
||||||
|
|
||||||
|
val inputStream = it.inputStream()
|
||||||
|
val outputStream = context.contentResolver.openOutputStream(destUri) ?: return@forEach
|
||||||
|
val fileLength = it.length()
|
||||||
|
var bytesCopied: Long = 0
|
||||||
|
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
|
||||||
|
var bytes = inputStream.read(buffer)
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (bytes >= 0) {
|
||||||
|
outputStream.write(buffer, 0, bytes)
|
||||||
|
bytesCopied += bytes
|
||||||
|
progress((bytesCopied * 100 / fileLength).toInt())
|
||||||
|
bytes = inputStream.read(buffer)
|
||||||
|
}
|
||||||
|
}catch (e : Exception){
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.close()
|
||||||
|
outputStream.close()
|
||||||
|
|
||||||
|
it.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
inputStream.close()
|
|
||||||
outputStream.close()
|
|
||||||
|
|
||||||
it.delete()
|
|
||||||
}
|
}
|
||||||
originDir.delete()
|
originDir.delete()
|
||||||
|
scanMedia(destDir, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertFileSize(s: Long): String{
|
fun convertFileSize(s: Long): String{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver
|
||||||
class NotificationUtil(var context: Context) {
|
class NotificationUtil(var context: Context) {
|
||||||
private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID)
|
private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID)
|
||||||
private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID)
|
private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID)
|
||||||
private val fileTransferNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, FILE_TRANSFER_CHANNEL_ID)
|
|
||||||
private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java)
|
private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java)
|
||||||
|
|
||||||
fun createNotificationChannel() {
|
fun createNotificationChannel() {
|
||||||
|
|
@ -39,43 +38,6 @@ class NotificationUtil(var context: Context) {
|
||||||
channel = NotificationChannel(COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
|
channel = NotificationChannel(COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
|
||||||
channel.description = description
|
channel.description = description
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
|
||||||
//file transfers
|
|
||||||
name = context.getString(R.string.file_transfer_notification_channel_name)
|
|
||||||
description = context.getString(R.string.file_transfer_notification_channel_description)
|
|
||||||
channel = NotificationChannel(FILE_TRANSFER_CHANNEL_ID, name, importance)
|
|
||||||
channel.description = description
|
|
||||||
notificationManager.createNotificationChannel(channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createFileTransferNotification(
|
|
||||||
pendingIntent: PendingIntent?,
|
|
||||||
title: String?,
|
|
||||||
) : Notification {
|
|
||||||
val intent = Intent(context, CancelDownloadNotificationReceiver::class.java)
|
|
||||||
|
|
||||||
return fileTransferNotificationBuilder
|
|
||||||
.setContentTitle(title)
|
|
||||||
.setCategory(Notification.CATEGORY_PROGRESS)
|
|
||||||
.setSmallIcon(R.drawable.ic_app_icon)
|
|
||||||
.setContentText("")
|
|
||||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
.setProgress(PROGRESS_MAX, PROGRESS_CURR, false)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateFileTransferNotification(
|
|
||||||
id: Int,
|
|
||||||
progress: Int
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
fileTransferNotificationBuilder.setProgress(100, progress, false)
|
|
||||||
notificationManager.notify(id, fileTransferNotificationBuilder.build())
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +45,6 @@ class NotificationUtil(var context: Context) {
|
||||||
when(channel) {
|
when(channel) {
|
||||||
DOWNLOAD_SERVICE_CHANNEL_ID -> { return downloadNotificationBuilder}
|
DOWNLOAD_SERVICE_CHANNEL_ID -> { return downloadNotificationBuilder}
|
||||||
COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder }
|
COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder }
|
||||||
FILE_TRANSFER_CHANNEL_ID -> { return fileTransferNotificationBuilder }
|
|
||||||
}
|
}
|
||||||
return downloadNotificationBuilder
|
return downloadNotificationBuilder
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +63,7 @@ class NotificationUtil(var context: Context) {
|
||||||
intent.putExtra("workID", workID)
|
intent.putExtra("workID", workID)
|
||||||
val cancelNotificationPendingIntent = PendingIntent.getBroadcast(
|
val cancelNotificationPendingIntent = PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
0,
|
workID,
|
||||||
intent,
|
intent,
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
PendingIntent.FLAG_IMMUTABLE
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Looper
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
@ -26,6 +27,7 @@ import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
class DownloadWorker(
|
class DownloadWorker(
|
||||||
|
|
@ -33,7 +35,7 @@ class DownloadWorker(
|
||||||
workerParams: WorkerParameters
|
workerParams: WorkerParameters
|
||||||
) : Worker(context, workerParams) {
|
) : Worker(context, workerParams) {
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
workID = inputData.getInt("workID", SystemClock.uptimeMillis().toInt())
|
workID = inputData.getLong("workID", SystemClock.uptimeMillis())
|
||||||
val notificationUtil = NotificationUtil(context)
|
val notificationUtil = NotificationUtil(context)
|
||||||
val dbManager = DBManager.getInstance(context)
|
val dbManager = DBManager.getInstance(context)
|
||||||
val dao = dbManager.downloadDao
|
val dao = dbManager.downloadDao
|
||||||
|
|
@ -47,8 +49,8 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, workID, NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
|
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, workID.toInt(), NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
|
||||||
val foregroundInfo = ForegroundInfo(workID, notification)
|
val foregroundInfo = ForegroundInfo(workID.toInt(), notification)
|
||||||
setForegroundAsync(foregroundInfo)
|
setForegroundAsync(foregroundInfo)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -123,10 +125,6 @@ class DownloadWorker(
|
||||||
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
||||||
}
|
}
|
||||||
"video" -> {
|
"video" -> {
|
||||||
if (downloadLocation == context.getString(R.string.video_path)){
|
|
||||||
tempFileDir = File(context.getString(R.string.video_path))
|
|
||||||
}
|
|
||||||
|
|
||||||
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||||
if (addChapters) {
|
if (addChapters) {
|
||||||
request.addOption("--sponsorblock-mark", "all")
|
request.addOption("--sponsorblock-mark", "all")
|
||||||
|
|
@ -136,17 +134,19 @@ class DownloadWorker(
|
||||||
request.addOption("--embed-subs", "")
|
request.addOption("--embed-subs", "")
|
||||||
}
|
}
|
||||||
var videoFormatID = downloadItem.format.format_id
|
var videoFormatID = downloadItem.format.format_id
|
||||||
if (videoFormatID.isEmpty()) videoFormatID = "bestvideo"
|
Log.e(TAG, videoFormatID)
|
||||||
val formatArgument = StringBuilder(videoFormatID)
|
var formatArgument = "bestvideo+bestaudio/best"
|
||||||
formatArgument.append("+bestaudio/best")
|
if (videoFormatID.isNotEmpty()) {
|
||||||
request.addOption("-f", formatArgument.toString())
|
if (videoFormatID == "Best Quality") videoFormatID = "bestvideo"
|
||||||
var format = downloadItem.format.container
|
else if (videoFormatID == "Worst Quality") videoFormatID = "worst"
|
||||||
if (format.isNotEmpty()) {
|
formatArgument = videoFormatID + if (downloadItem.removeAudio) "" else "+bestaudio"
|
||||||
format = sharedPreferences.getString("video_format", "")!!
|
|
||||||
if (format != "DEFAULT") request.addOption("--merge-output-format", format)
|
|
||||||
}
|
}
|
||||||
|
request.addOption("-f", formatArgument)
|
||||||
if (format != "webm") {
|
val format = downloadItem.format.container
|
||||||
|
if(format.isNotEmpty()){
|
||||||
|
request.addOption("--merge-output-format", format)
|
||||||
|
}
|
||||||
|
if (format != "webm" && format != "DEFAULT") {
|
||||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||||
if (embedThumb) {
|
if (embedThumb) {
|
||||||
request.addOption("--embed-thumbnail")
|
request.addOption("--embed-thumbnail")
|
||||||
|
|
@ -173,13 +173,14 @@ class DownloadWorker(
|
||||||
setProgressAsync(workDataOf("progress" to progress.toInt()))
|
setProgressAsync(workDataOf("progress" to progress.toInt()))
|
||||||
val title: String = downloadItem.title
|
val title: String = downloadItem.title
|
||||||
notificationUtil.updateDownloadNotification(
|
notificationUtil.updateDownloadNotification(
|
||||||
workID,
|
downloadItem.workID.toInt(),
|
||||||
line, progress.toInt(), 0, title,
|
line, progress.toInt(), 0, title,
|
||||||
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
//move file from internal to set download directory
|
//move file from internal to set download directory
|
||||||
|
|
||||||
moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
|
moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
|
||||||
setProgressAsync(workDataOf("progress" to progress))
|
setProgressAsync(workDataOf("progress" to progress))
|
||||||
}
|
}
|
||||||
|
|
@ -187,22 +188,31 @@ class DownloadWorker(
|
||||||
val incognito = sharedPreferences.getBoolean("incognito", false)
|
val incognito = sharedPreferences.getBoolean("incognito", false)
|
||||||
if (!incognito) {
|
if (!incognito) {
|
||||||
val unixtime = System.currentTimeMillis() / 1000
|
val unixtime = System.currentTimeMillis() / 1000
|
||||||
val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, downloadItem.downloadPath, downloadItem.website, downloadItem.format)
|
val fileUtil = FileUtil()
|
||||||
|
val finalPath = fileUtil.formatPath(downloadItem.downloadPath) + downloadItem.author + " - " + downloadItem.title + "." + downloadItem.format.container
|
||||||
|
val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, finalPath, downloadItem.website, downloadItem.format)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
historyDao.insert(historyItem)
|
historyDao.insert(historyItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
runBlocking {
|
||||||
|
dao.delete(downloadItem.id)
|
||||||
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
tempFileDir.delete()
|
tempFileDir.delete()
|
||||||
if (BuildConfig.DEBUG) {
|
Looper.prepare()
|
||||||
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
|
||||||
Log.e(TAG, context.getString(R.string.failed_download), it)
|
Log.e(TAG, context.getString(R.string.failed_download), it)
|
||||||
}
|
|
||||||
notificationUtil.updateDownloadNotification(
|
notificationUtil.updateDownloadNotification(
|
||||||
workID,
|
downloadItem.workID.toInt(),
|
||||||
context.getString(R.string.failed_download), 0, 0, downloadItem.title,
|
context.getString(R.string.failed_download), 0, 0, downloadItem.title,
|
||||||
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
downloadItem.status = DownloadRepository.status.Errored.toString()
|
||||||
|
runBlocking {
|
||||||
|
dao.update(downloadItem)
|
||||||
|
}
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,13 +237,13 @@ class DownloadWorker(
|
||||||
DocumentsContract.buildChildDocumentsUriUsingTree(this, DocumentsContract.getTreeDocumentId(this))
|
DocumentsContract.buildChildDocumentsUriUsingTree(this, DocumentsContract.getTreeDocumentId(this))
|
||||||
}
|
}
|
||||||
val fileUtil = FileUtil()
|
val fileUtil = FileUtil()
|
||||||
fileUtil.moveFile(originDir, context, destDir){ p ->
|
fileUtil.moveFile(originDir, context, downLocation){ p ->
|
||||||
progress(p)
|
progress(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var workID: Int = 0
|
var workID: Long = 0
|
||||||
const val TAG = "DownloadWorker"
|
const val TAG = "DownloadWorker"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.work
|
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.SystemClock
|
|
||||||
import android.provider.DocumentsContract
|
|
||||||
import androidx.work.CoroutineWorker
|
|
||||||
import androidx.work.ForegroundInfo
|
|
||||||
import androidx.work.WorkerParameters
|
|
||||||
import androidx.work.workDataOf
|
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class FileTransferWorker(
|
|
||||||
private val context: Context,
|
|
||||||
workerParams: WorkerParameters
|
|
||||||
) : CoroutineWorker(context, workerParams) {
|
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
|
||||||
val originDir = File(inputData.getString(originDir)!!)
|
|
||||||
val downLocation = inputData.getString(downLocation)
|
|
||||||
val fileTitle = inputData.getString(title) ?: ""
|
|
||||||
val destDir = Uri.parse(downLocation).run {
|
|
||||||
DocumentsContract.buildChildDocumentsUriUsingTree(this, DocumentsContract.getTreeDocumentId(this))
|
|
||||||
}
|
|
||||||
|
|
||||||
val fileUtil = FileUtil()
|
|
||||||
|
|
||||||
val notificationUtil = NotificationUtil(context)
|
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
|
||||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
val title = "Moving $fileTitle to ${fileUtil.formatPath(downLocation!!)}"
|
|
||||||
val id : Int = SystemClock.uptimeMillis().toInt()
|
|
||||||
val notification = notificationUtil.createFileTransferNotification(pendingIntent, title)
|
|
||||||
val foregroundInfo = ForegroundInfo(id, notification)
|
|
||||||
setForeground(foregroundInfo)
|
|
||||||
|
|
||||||
fileUtil.moveFile(originDir, context, destDir){ progress ->
|
|
||||||
setProgressAsync(workDataOf("progress" to progress))
|
|
||||||
notificationUtil.updateFileTransferNotification(id, progress)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val downLocation = "downLocation"
|
|
||||||
const val originDir = "originDir"
|
|
||||||
const val title = "title"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -123,7 +123,7 @@
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/chipGroup"
|
android:id="@+id/chipGroup"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
app:singleLine="true"
|
app:singleLine="false"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
|
|
|
||||||
85
app/src/main/res/layout/fragment_downloads.xml
Normal file
85
app/src/main/res/layout/fragment_downloads.xml
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/downloadscoordinator"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/downloads_appbarlayout"
|
||||||
|
app:liftOnScroll="false"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/downloads_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways|snap"
|
||||||
|
app:title="@string/downloads"
|
||||||
|
android:theme="@style/Toolbar"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerviewactivedownloads"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="150dp"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
|
||||||
|
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerviewotherdownloads"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="150dp"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
|
||||||
|
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/delete_selected_coordinator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/delete_selected_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:text="@string/delete_selected"
|
||||||
|
app:icon="@drawable/ic_delete_all"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<include layout="@layout/history_no_results"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
@ -3,23 +3,23 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/downloadscoordinator"
|
android:id="@+id/historycoordinator"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/downloads_appbarlayout"
|
android:id="@+id/history_appbarlayout"
|
||||||
app:liftOnScroll="false"
|
app:liftOnScroll="false"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/downloads_toolbar"
|
android:id="@+id/history_toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:layout_scrollFlags="scroll|enterAlways|snap"
|
app:layout_scrollFlags="scroll|enterAlways|snap"
|
||||||
app:title="@string/history"
|
app:title="@string/history"
|
||||||
app:menu="@menu/downloads_menu"
|
app:menu="@menu/history_menu"
|
||||||
android:theme="@style/Toolbar"
|
android:theme="@style/Toolbar"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/downloads_selection_chips"
|
android:id="@+id/history_selection_chips"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerviewdownloadss"
|
android:id="@+id/recyclerviewhistorys"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/chips_recycler_horizontalscrollview"
|
android:layout_below="@+id/chips_recycler_horizontalscrollview"
|
||||||
|
|
@ -119,12 +119,12 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@+id/chips_recycler_horizontalscrollview"
|
android:layout_below="@+id/chips_recycler_horizontalscrollview"
|
||||||
android:id="@+id/shimmer_downloads_framelayout"
|
android:id="@+id/shimmer_history_framelayout"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/shimmer_downloads_linear_layout"
|
android:id="@+id/shimmer_history_linear_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/downloads_no_results"
|
android:id="@+id/no_results"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,20 @@
|
||||||
tools:context=".MainActivity" >
|
tools:context=".MainActivity" >
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/search_downloads"
|
android:id="@+id/search_history"
|
||||||
android:title="@string/search"
|
android:title="@string/search"
|
||||||
android:icon="@drawable/ic_search"
|
android:icon="@drawable/ic_search"
|
||||||
app:showAsAction="collapseActionView|always"
|
app:showAsAction="collapseActionView|always"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/remove_downloads"
|
android:id="@+id/remove_history"
|
||||||
android:icon="@drawable/ic_delete_all"
|
android:icon="@drawable/ic_delete_all"
|
||||||
android:title="@string/remove_all"
|
android:title="@string/remove_all"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/remove_deleted_downloads"
|
android:id="@+id/remove_deleted_history"
|
||||||
android:icon="@drawable/ic_delete_all"
|
android:icon="@drawable/ic_delete_all"
|
||||||
android:title="@string/remove_deleted"
|
android:title="@string/remove_deleted"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
Loading…
Reference in a new issue