added swipes for download cards
This commit is contained in:
parent
b236b65446
commit
a1655810f0
16 changed files with 401 additions and 33 deletions
|
|
@ -179,5 +179,6 @@ dependencies {
|
|||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
|
||||
implementation "com.google.android.exoplayer:exoplayer:2.18.5"
|
||||
implementation 'it.xabaras.android:recyclerview-swipedecorator:1.4'
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.deniscerri.ytdlnis
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
|
|
@ -82,6 +83,18 @@ class MainActivity : AppCompatActivity() {
|
|||
if (isImeVisible) View.GONE else View.VISIBLE
|
||||
view.onApplyWindowInsets(windowInsets)
|
||||
}
|
||||
var sharedPreferences = getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||
|
||||
val startDestination = sharedPreferences.getString("start_destination", "")
|
||||
val graph = navHostFragment.navController.navInflater.inflate(R.navigation.nav_graph)
|
||||
when(startDestination) {
|
||||
"History" -> graph.setStartDestination(R.id.historyFragment)
|
||||
"More" -> graph.setStartDestination(R.id.moreFragment)
|
||||
else -> graph.setStartDestination(R.id.homeFragment)
|
||||
}
|
||||
navHostFragment.navController.graph = graph
|
||||
|
||||
|
||||
|
||||
navigationView.setupWithNavController(navController)
|
||||
navigationView.setOnItemReselectedListener {
|
||||
|
|
|
|||
|
|
@ -41,23 +41,25 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
}
|
||||
|
||||
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
|
||||
if (sharedPreferences.getBoolean("home_recommendations", false)){
|
||||
try {
|
||||
val item = repository.getFirstResult()
|
||||
if (
|
||||
item.playlistTitle == getApplication<App>().getString(R.string.trendingPlaylist)
|
||||
&& item.creationTime < (System.currentTimeMillis() / 1000) - 86400
|
||||
){
|
||||
getTrending()
|
||||
}
|
||||
}catch (e : Exception){
|
||||
e.printStackTrace()
|
||||
try {
|
||||
val item = repository.getFirstResult()
|
||||
if (
|
||||
item.playlistTitle == getApplication<App>().getString(R.string.trendingPlaylist)
|
||||
&& item.creationTime < (System.currentTimeMillis() / 1000) - 86400
|
||||
){
|
||||
getTrending()
|
||||
}
|
||||
}catch (e : Exception){
|
||||
e.printStackTrace()
|
||||
getTrending()
|
||||
}
|
||||
}
|
||||
fun getTrending() = viewModelScope.launch(Dispatchers.IO){
|
||||
repository.updateTrending()
|
||||
if (sharedPreferences.getBoolean("home_recommendations", false)){
|
||||
repository.updateTrending()
|
||||
}else{
|
||||
deleteAll()
|
||||
}
|
||||
}
|
||||
suspend fun parseQueries(inputQueries: List<String>){
|
||||
if (inputQueries.size == 1){
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
private var sharedPreferences: SharedPreferences? = null
|
||||
private var _binding : FragmentHomeBinding? = null
|
||||
private var actionMode: ActionMode? = null
|
||||
private var appBarLayout: AppBarLayout? = null
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
|
|
@ -126,6 +127,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
//initViews
|
||||
shimmerCards = view.findViewById(R.id.shimmer_results_framelayout)
|
||||
searchBar = view.findViewById(R.id.search_bar)
|
||||
appBarLayout = view.findViewById(R.id.home_appbarlayout)
|
||||
queriesChipGroup = view.findViewById(R.id.queries)
|
||||
searchSuggestions = view.findViewById(R.id.search_suggestions_scroll_view)
|
||||
searchSuggestionsLinearLayout = view.findViewById(R.id.search_suggestions_linear_layout)
|
||||
|
|
@ -620,7 +622,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
clearCheckedItems()
|
||||
searchBar!!.isEnabled = true
|
||||
searchBar!!.menu.forEach { it.isEnabled = true }
|
||||
searchBar?.expand(searchBar!!.parent as AppBarLayout)
|
||||
searchBar?.expand(appBarLayout!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import android.app.Activity
|
|||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.util.DisplayMetrics
|
||||
|
|
@ -16,6 +18,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||
import androidx.core.view.get
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdlnis.R
|
||||
|
|
@ -34,6 +37,9 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -91,6 +97,8 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
|||
recyclerView = view.findViewById(R.id.downloadMultipleRecyclerview)
|
||||
recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
recyclerView.adapter = listAdapter
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
listAdapter.submitList(items.toList())
|
||||
|
||||
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
||||
|
|
@ -332,5 +340,70 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
|||
listAdapter.submitList(items.toList())
|
||||
}
|
||||
|
||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
when (direction) {
|
||||
ItemTouchHelper.LEFT -> {
|
||||
val deletedItem = items[position]
|
||||
items.remove(deletedItem)
|
||||
listAdapter.submitList(items.toList())
|
||||
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
items.add(position, deletedItem)
|
||||
listAdapter.submitList(items.toList())
|
||||
}.show()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
c: Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
RecyclerViewSwipeDecorator.Builder(
|
||||
requireContext(),
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
.addSwipeLeftBackgroundColor(Color.RED)
|
||||
.addSwipeLeftActionIcon(R.drawable.baseline_delete_24)
|
||||
.addSwipeRightBackgroundColor(
|
||||
MaterialColors.getColor(
|
||||
requireContext(),
|
||||
R.attr.colorOnSurfaceInverse, Color.TRANSPARENT
|
||||
)
|
||||
)
|
||||
.create()
|
||||
.decorate()
|
||||
super.onChildDraw(
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder!!,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ package com.deniscerri.ytdlnis.ui.downloads
|
|||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
|
@ -16,7 +17,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.adapter.GenericDownloadAdapter
|
||||
|
|
@ -28,7 +29,10 @@ import com.deniscerri.ytdlnis.util.UiUtil
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
||||
|
|
@ -39,7 +43,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
private lateinit var downloadViewModel : DownloadViewModel
|
||||
private lateinit var cancelledRecyclerView : RecyclerView
|
||||
private lateinit var cancelledDownloads : GenericDownloadAdapter
|
||||
private lateinit var items : List<DownloadItem>
|
||||
private lateinit var items : MutableList<DownloadItem>
|
||||
private lateinit var fileUtil: FileUtil
|
||||
private lateinit var uiUtil : UiUtil
|
||||
|
||||
|
|
@ -52,7 +56,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
|
||||
activity = getActivity()
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
items = listOf()
|
||||
items = mutableListOf()
|
||||
fileUtil = FileUtil()
|
||||
uiUtil = UiUtil(fileUtil)
|
||||
return fragmentView
|
||||
|
|
@ -69,6 +73,8 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
|
||||
cancelledRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||
cancelledRecyclerView.adapter = cancelledDownloads
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(cancelledRecyclerView)
|
||||
|
||||
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||
if (landScape){
|
||||
|
|
@ -77,7 +83,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
if (resources.getBoolean(R.bool.isTablet)) cancelledRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||
|
||||
downloadViewModel.cancelledDownloads.observe(viewLifecycleOwner) {
|
||||
items = it
|
||||
items = it.toMutableList()
|
||||
cancelledDownloads.submitList(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -202,4 +208,73 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
}
|
||||
deleteDialog.show()
|
||||
}
|
||||
|
||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
||||
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
when (direction) {
|
||||
ItemTouchHelper.LEFT -> {
|
||||
val deletedItem = items[position]
|
||||
items.remove(deletedItem)
|
||||
cancelledDownloads.submitList(items.toList())
|
||||
Snackbar.make(cancelledRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
items.add(position, deletedItem)
|
||||
cancelledDownloads.submitList(items.toList())
|
||||
}.show()
|
||||
}
|
||||
ItemTouchHelper.RIGHT -> {
|
||||
onActionButtonClick(items[position].id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
c: Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
RecyclerViewSwipeDecorator.Builder(
|
||||
requireContext(),
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
.addSwipeLeftBackgroundColor(Color.RED)
|
||||
.addSwipeLeftActionIcon(R.drawable.baseline_delete_24)
|
||||
.addSwipeRightBackgroundColor(
|
||||
MaterialColors.getColor(
|
||||
requireContext(),
|
||||
R.attr.colorOnSurfaceInverse,Color.TRANSPARENT
|
||||
)
|
||||
)
|
||||
.addSwipeRightActionIcon(R.drawable.ic_refresh)
|
||||
.create()
|
||||
.decorate()
|
||||
super.onChildDraw(
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder!!,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ import android.app.Activity
|
|||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -18,6 +20,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdlnis.R
|
||||
|
|
@ -31,7 +34,10 @@ import com.deniscerri.ytdlnis.util.UiUtil
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
||||
|
|
@ -42,7 +48,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
private lateinit var downloadViewModel : DownloadViewModel
|
||||
private lateinit var erroredRecyclerView : RecyclerView
|
||||
private lateinit var erroredDownloads : GenericDownloadAdapter
|
||||
private lateinit var items : List<DownloadItem>
|
||||
private lateinit var items : MutableList<DownloadItem>
|
||||
private lateinit var fileUtil: FileUtil
|
||||
private lateinit var uiUtil : UiUtil
|
||||
override fun onCreateView(
|
||||
|
|
@ -54,7 +60,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
|
||||
activity = getActivity()
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
items = listOf()
|
||||
items = mutableListOf()
|
||||
fileUtil = FileUtil()
|
||||
uiUtil = UiUtil(fileUtil)
|
||||
return fragmentView
|
||||
|
|
@ -71,6 +77,8 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
|
||||
erroredRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||
erroredRecyclerView.adapter = erroredDownloads
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(erroredRecyclerView)
|
||||
|
||||
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||
if (landScape){
|
||||
|
|
@ -79,7 +87,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
if (resources.getBoolean(R.bool.isTablet)) erroredRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||
|
||||
downloadViewModel.erroredDownloads.observe(viewLifecycleOwner) {
|
||||
items = it
|
||||
items = it.toMutableList()
|
||||
erroredDownloads.submitList(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -205,5 +213,69 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
when (direction) {
|
||||
ItemTouchHelper.LEFT -> {
|
||||
val deletedItem = items[position]
|
||||
items.remove(deletedItem)
|
||||
erroredDownloads.submitList(items.toList())
|
||||
Snackbar.make(erroredRecyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
items.add(position, deletedItem)
|
||||
erroredDownloads.submitList(items.toList())
|
||||
}.show()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
c: Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
RecyclerViewSwipeDecorator.Builder(
|
||||
requireContext(),
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
.addSwipeLeftBackgroundColor(Color.RED)
|
||||
.addSwipeLeftActionIcon(R.drawable.baseline_delete_24)
|
||||
.addSwipeRightBackgroundColor(
|
||||
MaterialColors.getColor(
|
||||
requireContext(),
|
||||
R.attr.colorOnSurfaceInverse, Color.TRANSPARENT
|
||||
)
|
||||
)
|
||||
.create()
|
||||
.decorate()
|
||||
super.onChildDraw(
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder!!,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.deniscerri.ytdlnis.ui.downloads
|
|||
|
||||
import android.app.Activity
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.util.DisplayMetrics
|
||||
|
|
@ -17,6 +19,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.work.WorkManager
|
||||
|
|
@ -31,7 +34,10 @@ import com.deniscerri.ytdlnis.util.UiUtil
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.yausername.youtubedl_android.YoutubeDL
|
||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
@ -48,7 +54,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
private lateinit var queuedRecyclerView : RecyclerView
|
||||
private lateinit var queuedDownloads : GenericDownloadAdapter
|
||||
private lateinit var notificationUtil: NotificationUtil
|
||||
private lateinit var items : List<DownloadItem>
|
||||
private lateinit var items : MutableList<DownloadItem>
|
||||
private lateinit var fileUtil: FileUtil
|
||||
private lateinit var uiUtil: UiUtil
|
||||
|
||||
|
|
@ -62,7 +68,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
activity = getActivity()
|
||||
notificationUtil = NotificationUtil(requireContext())
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
items = listOf()
|
||||
items = mutableListOf()
|
||||
fileUtil = FileUtil()
|
||||
uiUtil = UiUtil(fileUtil)
|
||||
return fragmentView
|
||||
|
|
@ -79,6 +85,8 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
|
||||
queuedRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||
queuedRecyclerView.adapter = queuedDownloads
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(queuedRecyclerView)
|
||||
|
||||
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||
if (landScape){
|
||||
|
|
@ -87,7 +95,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
if (resources.getBoolean(R.bool.isTablet)) queuedRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||
|
||||
downloadViewModel.queuedDownloads.observe(viewLifecycleOwner) {
|
||||
items = it
|
||||
items = it.toMutableList()
|
||||
queuedDownloads.submitList(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -216,4 +224,69 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
notificationUtil.cancelDownloadNotification(id)
|
||||
}
|
||||
|
||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
when (direction) {
|
||||
ItemTouchHelper.LEFT -> {
|
||||
val deletedItem = items[position]
|
||||
cancelDownload(deletedItem.id)
|
||||
Snackbar.make(queuedRecyclerView, getString(R.string.cancelled) + ": " + deletedItem.title, Snackbar.LENGTH_LONG)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
downloadViewModel.queueDownloads(listOf(deletedItem))
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
c: Canvas,
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dX: Float,
|
||||
dY: Float,
|
||||
actionState: Int,
|
||||
isCurrentlyActive: Boolean
|
||||
) {
|
||||
RecyclerViewSwipeDecorator.Builder(
|
||||
requireContext(),
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
.addSwipeLeftBackgroundColor(Color.RED)
|
||||
.addSwipeLeftActionIcon(R.drawable.baseline_delete_24)
|
||||
.addSwipeRightBackgroundColor(
|
||||
MaterialColors.getColor(
|
||||
requireContext(),
|
||||
R.attr.colorOnSurfaceInverse, Color.TRANSPARENT
|
||||
)
|
||||
)
|
||||
.create()
|
||||
.decorate()
|
||||
super.onChildDraw(
|
||||
c,
|
||||
recyclerView,
|
||||
viewHolder!!,
|
||||
dX,
|
||||
dY,
|
||||
actionState,
|
||||
isCurrentlyActive
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import android.content.SharedPreferences
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.FileObserver
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
|
@ -21,6 +22,7 @@ import android.widget.TextView
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.forEach
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.work.*
|
||||
|
|
@ -129,7 +131,6 @@ class TerminalActivity : AppCompatActivity() {
|
|||
input!!.visibility = View.GONE
|
||||
output!!.text = "${output!!.text}\n~ $ ${input!!.text}\n"
|
||||
showCancelFab()
|
||||
downloadFile.appendText("~ $ ${input!!.text}\n")
|
||||
imm.hideSoftInputFromWindow(input?.windowToken, 0)
|
||||
startDownload(
|
||||
input!!.text.toString()
|
||||
|
|
@ -149,7 +150,8 @@ class TerminalActivity : AppCompatActivity() {
|
|||
runOnUiThread{
|
||||
try {
|
||||
val newText = downloadFile.readText()
|
||||
output!!.text = newText
|
||||
if (newText.isBlank()) return@runOnUiThread
|
||||
output!!.append(newText)
|
||||
output!!.scrollTo(0, output!!.height)
|
||||
scrollView!!.fullScroll(View.FOCUS_DOWN)
|
||||
}catch (ignored: Exception) {}
|
||||
|
|
@ -163,7 +165,8 @@ class TerminalActivity : AppCompatActivity() {
|
|||
runOnUiThread{
|
||||
try {
|
||||
val newText = downloadFile.readText()
|
||||
output!!.text = newText
|
||||
if (newText.isBlank()) return@runOnUiThread
|
||||
output!!.append(newText)
|
||||
output!!.scrollTo(0, output!!.height)
|
||||
scrollView!!.fullScroll(View.FOCUS_DOWN)
|
||||
}catch (ignored: Exception) {}
|
||||
|
|
@ -183,7 +186,19 @@ class TerminalActivity : AppCompatActivity() {
|
|||
input!!.requestFocus()
|
||||
input!!.setSelection(input!!.text.length)
|
||||
hideCancelFab()
|
||||
downloadFile.writeText("")
|
||||
}
|
||||
val outputData = work.progress.getString("output")
|
||||
if (!outputData.isNullOrBlank()){
|
||||
runOnUiThread{
|
||||
try {
|
||||
output!!.append("\n$outputData")
|
||||
output!!.scrollTo(0, output!!.height)
|
||||
scrollView!!.fullScroll(View.FOCUS_DOWN)
|
||||
}catch (ignored: Exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
initMenu()
|
||||
|
|
@ -227,10 +242,12 @@ class TerminalActivity : AppCompatActivity() {
|
|||
private fun hideCancelFab() {
|
||||
fab!!.text = getString(R.string.run_command)
|
||||
fab!!.setIconResource(R.drawable.ic_baseline_keyboard_arrow_right_24)
|
||||
topAppBar!!.menu.forEach { it.isEnabled = true }
|
||||
}
|
||||
private fun showCancelFab() {
|
||||
fab!!.text = getString(R.string.cancel_download)
|
||||
fab!!.setIconResource(R.drawable.ic_cancel)
|
||||
topAppBar!!.menu.forEach { it.isEnabled = false }
|
||||
}
|
||||
|
||||
private fun showShortcuts() {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private var incognito: SwitchPreferenceCompat? = null
|
||||
private var preferredDownloadType : ListPreference? = null
|
||||
private var searchEngine : ListPreference? = null
|
||||
private var startDestination : ListPreference? = null
|
||||
private var downloadCard: SwitchPreferenceCompat? = null
|
||||
private var meteredNetwork: SwitchPreferenceCompat? = null
|
||||
private var apiKey: EditTextPreference? = null
|
||||
|
|
@ -110,6 +111,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
incognito = findPreference("incognito")
|
||||
preferredDownloadType = findPreference("preferred_download_type")
|
||||
searchEngine = findPreference("search_engine")
|
||||
startDestination = findPreference("start_destination")
|
||||
downloadCard = findPreference("download_card")
|
||||
meteredNetwork = findPreference("metered_networks")
|
||||
apiKey = findPreference("api_key")
|
||||
|
|
@ -177,6 +179,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
editor.putBoolean("incognito", incognito!!.isChecked)
|
||||
editor.putString("preferred_download_type", preferredDownloadType!!.value)
|
||||
editor.putString("search_engine", searchEngine!!.value)
|
||||
editor.putString("start_destination", startDestination!!.value)
|
||||
editor.putBoolean("download_card", downloadCard!!.isChecked)
|
||||
editor.putBoolean("metered_networks", meteredNetwork!!.isChecked)
|
||||
editor.putString("api_key", apiKey!!.text)
|
||||
|
|
@ -303,6 +306,12 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
editor.apply()
|
||||
true
|
||||
}
|
||||
startDestination!!.onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||
editor.putString("start_destination", newValue.toString())
|
||||
editor.apply()
|
||||
true
|
||||
}
|
||||
downloadCard!!.onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||
val enable = newValue as Boolean
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class TerminalDownloadWorker(
|
|||
}
|
||||
|
||||
YoutubeDL.getInstance().execute(request, itemId.toString()){ progress, _, line ->
|
||||
outputFile.appendText("${line}\n")
|
||||
setProgressAsync(workDataOf("progress" to progress.toInt(), "output" to line.chunked(5000).first().toString(), "id" to itemId, "log" to logDownloads))
|
||||
val title: String = command.take(65)
|
||||
notificationUtil.updateDownloadNotification(
|
||||
itemId,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?android:colorAccent" android:pathData="M18,1.01L8,1c-1.1,0 -2,0.9 -2,2v3h2V5h10v14H8v-1H6v3c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM10,15h2V8H5v2h3.59L3,15.59 4.41,17 10,11.41z"/>
|
||||
</vector>
|
||||
|
|
@ -207,4 +207,8 @@
|
|||
<string name="format_source">Burimi i Formateve</string>
|
||||
<string name="video_recommendations">Rekomendimet e Videove</string>
|
||||
<string name="video_recommendations_summary">Merr video Youtube te rekomanduara në faqen kryesore nga Invidious</string>
|
||||
<string name="preferred_search_engine">Kërkuesi i Preferuar</string>
|
||||
<string name="preferred_search_engine_summary">Kërkuesi që do të përdoret për kërkimet në aplikacion</string>
|
||||
<string name="format_filtering_hint">Të gjithë elementet duhet të jenë të një i njëjti lloj për të përdorur këtë opsion</string>
|
||||
<string name="preferred_home_screen">Faqja e preferuar kryesore</string>
|
||||
</resources>
|
||||
|
|
@ -151,4 +151,16 @@
|
|||
<item>bilisearch</item>
|
||||
<item>netsearch</item>
|
||||
</array>
|
||||
|
||||
<array name="start_destination">
|
||||
<item>@string/home</item>
|
||||
<item>@string/downloads</item>
|
||||
<item>@string/more</item>
|
||||
</array>
|
||||
|
||||
<array name="start_destination_values">
|
||||
<item>Home</item>
|
||||
<item>History</item>
|
||||
<item>More</item>
|
||||
</array>
|
||||
</resources>
|
||||
|
|
@ -217,4 +217,6 @@
|
|||
<string name="preferred_search_engine">Preferred Search Engine</string>
|
||||
<string name="preferred_search_engine_summary">The search engine to use for in-app searches</string>
|
||||
<string name="format_filtering_hint">All items must be of the same type to use this option</string>
|
||||
<string name="preferred_home_screen">Preferred Home Screen</string>
|
||||
<string name="undo">Undo</string>
|
||||
</resources>
|
||||
|
|
@ -92,6 +92,14 @@
|
|||
app:summary="@string/preferred_search_engine_summary"
|
||||
app:title="@string/preferred_search_engine" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="Home"
|
||||
android:entries="@array/start_destination"
|
||||
android:entryValues="@array/start_destination_values"
|
||||
app:icon="@drawable/baseline_add_to_home_screen_24"
|
||||
app:key="start_destination"
|
||||
app:title="@string/preferred_home_screen" />
|
||||
|
||||
<EditTextPreference
|
||||
android:icon="@drawable/ic_key"
|
||||
app:key="api_key"
|
||||
|
|
@ -276,6 +284,11 @@
|
|||
app:summary="@string/ytdl_update_hint"
|
||||
app:title="@string/update_ytdl" />
|
||||
|
||||
<Preference
|
||||
app:icon="@drawable/ic_info"
|
||||
app:key="ytdl-version"
|
||||
app:title="@string/ytdl_version"/>
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
android:defaultValue="false"
|
||||
|
|
@ -366,11 +379,6 @@
|
|||
android:data="https://github.com/deniscerri/ytdlnis" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
app:icon="@drawable/ic_info"
|
||||
app:key="ytdl-version"
|
||||
app:title="@string/ytdl_version"/>
|
||||
|
||||
<Preference
|
||||
app:icon="@drawable/ic_info"
|
||||
app:key="version"
|
||||
|
|
|
|||
Loading…
Reference in a new issue