mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
feat: split downloads fragment into audio and video category
This commit is contained in:
parent
db0dc4c4fc
commit
f0fb359b5d
@ -7,7 +7,6 @@ import androidx.media3.common.MediaItem
|
|||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.db.DatabaseHolder
|
|
||||||
import com.github.libretube.db.DatabaseHolder.Database
|
import com.github.libretube.db.DatabaseHolder.Database
|
||||||
import com.github.libretube.enums.FileType
|
import com.github.libretube.enums.FileType
|
||||||
import com.github.libretube.extensions.toAndroidUri
|
import com.github.libretube.extensions.toAndroidUri
|
||||||
|
@ -16,9 +16,11 @@ import com.github.libretube.databinding.DownloadedMediaRowBinding
|
|||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.db.obj.DownloadWithItems
|
import com.github.libretube.db.obj.DownloadWithItems
|
||||||
import com.github.libretube.extensions.formatAsFileSize
|
import com.github.libretube.extensions.formatAsFileSize
|
||||||
|
import com.github.libretube.helpers.BackgroundHelper
|
||||||
import com.github.libretube.helpers.ImageHelper
|
import com.github.libretube.helpers.ImageHelper
|
||||||
import com.github.libretube.ui.activities.OfflinePlayerActivity
|
import com.github.libretube.ui.activities.OfflinePlayerActivity
|
||||||
import com.github.libretube.ui.base.BaseActivity
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
|
import com.github.libretube.ui.fragments.DownloadTab
|
||||||
import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet
|
import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet
|
||||||
import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet.Companion.DELETE_DOWNLOAD_REQUEST_KEY
|
import com.github.libretube.ui.sheets.DownloadOptionsBottomSheet.Companion.DELETE_DOWNLOAD_REQUEST_KEY
|
||||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||||
@ -32,6 +34,7 @@ import kotlin.io.path.fileSize
|
|||||||
|
|
||||||
class DownloadsAdapter(
|
class DownloadsAdapter(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
private val downloadTab: DownloadTab,
|
||||||
private val downloads: MutableList<DownloadWithItems>,
|
private val downloads: MutableList<DownloadWithItems>,
|
||||||
private val toggleDownload: (DownloadWithItems) -> Boolean
|
private val toggleDownload: (DownloadWithItems) -> Boolean
|
||||||
) : RecyclerView.Adapter<DownloadsViewHolder>() {
|
) : RecyclerView.Adapter<DownloadsViewHolder>() {
|
||||||
@ -98,9 +101,13 @@ class DownloadsAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
val intent = Intent(root.context, OfflinePlayerActivity::class.java)
|
if (downloadTab == DownloadTab.VIDEO) {
|
||||||
intent.putExtra(IntentData.videoId, download.videoId)
|
val intent = Intent(root.context, OfflinePlayerActivity::class.java)
|
||||||
root.context.startActivity(intent)
|
intent.putExtra(IntentData.videoId, download.videoId)
|
||||||
|
root.context.startActivity(intent)
|
||||||
|
} else {
|
||||||
|
BackgroundHelper.playOnBackgroundOffline(root.context, download.videoId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
|
@ -11,20 +11,26 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
|
import com.github.libretube.databinding.FragmentDownloadContentBinding
|
||||||
import com.github.libretube.databinding.FragmentDownloadsBinding
|
import com.github.libretube.databinding.FragmentDownloadsBinding
|
||||||
import com.github.libretube.db.DatabaseHolder.Database
|
import com.github.libretube.db.DatabaseHolder.Database
|
||||||
import com.github.libretube.db.obj.DownloadWithItems
|
import com.github.libretube.db.obj.DownloadWithItems
|
||||||
|
import com.github.libretube.enums.FileType
|
||||||
import com.github.libretube.extensions.ceilHalf
|
import com.github.libretube.extensions.ceilHalf
|
||||||
import com.github.libretube.extensions.formatAsFileSize
|
import com.github.libretube.extensions.formatAsFileSize
|
||||||
import com.github.libretube.helpers.BackgroundHelper
|
import com.github.libretube.extensions.serializable
|
||||||
import com.github.libretube.helpers.DownloadHelper
|
import com.github.libretube.helpers.DownloadHelper
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import com.github.libretube.obj.DownloadStatus
|
import com.github.libretube.obj.DownloadStatus
|
||||||
@ -35,20 +41,77 @@ import com.github.libretube.ui.base.DynamicLayoutManagerFragment
|
|||||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.io.path.fileSize
|
import kotlin.io.path.fileSize
|
||||||
|
|
||||||
class DownloadsFragment : DynamicLayoutManagerFragment() {
|
enum class DownloadTab {
|
||||||
|
VIDEO,
|
||||||
|
AUDIO
|
||||||
|
}
|
||||||
|
|
||||||
|
class DownloadsFragment : Fragment() {
|
||||||
private var _binding: FragmentDownloadsBinding? = null
|
private var _binding: FragmentDownloadsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = FragmentDownloadsBinding.inflate(inflater)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.downloadsPager.adapter = DownloadsFragmentAdapter(this)
|
||||||
|
|
||||||
|
TabLayoutMediator(binding.tabLayout, binding.downloadsPager) { tab, position ->
|
||||||
|
tab.text = when (position) {
|
||||||
|
DownloadTab.VIDEO.ordinal -> getString(R.string.video)
|
||||||
|
DownloadTab.AUDIO.ordinal -> getString(R.string.audio)
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bindDownloadService() {
|
||||||
|
childFragmentManager.fragments.filterIsInstance<DownloadsFragmentPage>().forEach {
|
||||||
|
it.bindDownloadService()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DownloadsFragmentAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
|
||||||
|
override fun getItemCount() = DownloadTab.entries.size
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return DownloadsFragmentPage().apply {
|
||||||
|
arguments = bundleOf(IntentData.currentPosition to DownloadTab.entries[position])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DownloadsFragmentPage : DynamicLayoutManagerFragment() {
|
||||||
private lateinit var adapter: DownloadsAdapter
|
private lateinit var adapter: DownloadsAdapter
|
||||||
|
private var _binding: FragmentDownloadContentBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private var binder: DownloadService.LocalBinder? = null
|
private var binder: DownloadService.LocalBinder? = null
|
||||||
private val downloads = mutableListOf<DownloadWithItems>()
|
private val downloads = mutableListOf<DownloadWithItems>()
|
||||||
private val downloadReceiver = DownloadReceiver()
|
private val downloadReceiver = DownloadReceiver()
|
||||||
|
private lateinit var downloadTabSelf: DownloadTab
|
||||||
|
|
||||||
private val serviceConnection = object : ServiceConnection {
|
private val serviceConnection = object : ServiceConnection {
|
||||||
var isBound = false
|
var isBound = false
|
||||||
@ -71,21 +134,28 @@ class DownloadsFragment : DynamicLayoutManagerFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
this.downloadTabSelf = requireArguments().serializable(IntentData.currentPosition)!!
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
_binding = FragmentDownloadsBinding.inflate(inflater)
|
_binding = FragmentDownloadContentBinding.inflate(layoutInflater)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLayoutManagers(gridItems: Int) {
|
override fun setLayoutManagers(gridItems: Int) {
|
||||||
_binding?.downloads?.layoutManager = GridLayoutManager(context, gridItems.ceilHalf())
|
_binding?.downloadsRecView?.layoutManager = GridLayoutManager(context, gridItems.ceilHalf())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
var selectedSortType =
|
var selectedSortType =
|
||||||
PreferenceHelper.getInt(PreferenceKeys.SELECTED_DOWNLOAD_SORT_TYPE, 0)
|
PreferenceHelper.getInt(PreferenceKeys.SELECTED_DOWNLOAD_SORT_TYPE, 0)
|
||||||
val filterOptions = resources.getStringArray(R.array.downloadSortOptions)
|
val filterOptions = resources.getStringArray(R.array.downloadSortOptions)
|
||||||
@ -95,6 +165,7 @@ class DownloadsFragment : DynamicLayoutManagerFragment() {
|
|||||||
binding.sortType.text = filterOptions[index]
|
binding.sortType.text = filterOptions[index]
|
||||||
if (::adapter.isInitialized) {
|
if (::adapter.isInitialized) {
|
||||||
sortDownloadList(index, selectedSortType)
|
sortDownloadList(index, selectedSortType)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
selectedSortType = index
|
selectedSortType = index
|
||||||
PreferenceHelper.putInt(
|
PreferenceHelper.putInt(
|
||||||
@ -104,96 +175,111 @@ class DownloadsFragment : DynamicLayoutManagerFragment() {
|
|||||||
}.show(childFragmentManager)
|
}.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dbDownloads = runBlocking(Dispatchers.IO) {
|
lifecycleScope.launch {
|
||||||
Database.downloadDao().getAll()
|
val dbDownloads = withContext(Dispatchers.IO) {
|
||||||
}.takeIf { it.isNotEmpty() } ?: return
|
Database.downloadDao().getAll()
|
||||||
|
|
||||||
downloads.clear()
|
|
||||||
downloads.addAll(dbDownloads)
|
|
||||||
binding.downloadsEmpty.isGone = true
|
|
||||||
binding.downloads.isVisible = true
|
|
||||||
adapter = DownloadsAdapter(requireContext(), downloads) {
|
|
||||||
var isDownloading = false
|
|
||||||
val ids = it.downloadItems
|
|
||||||
.filter { item -> item.path.fileSize() < item.downloadSize }
|
|
||||||
.map { item -> item.id }
|
|
||||||
|
|
||||||
if (!serviceConnection.isBound) {
|
|
||||||
DownloadHelper.startDownloadService(requireContext())
|
|
||||||
bindDownloadService(ids.toIntArray())
|
|
||||||
return@DownloadsAdapter true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binder?.getService()?.let { service ->
|
downloads.clear()
|
||||||
isDownloading = ids.any { id -> service.isDownloading(id) }
|
downloads.addAll(dbDownloads.filter { dl ->
|
||||||
|
when (downloadTabSelf) {
|
||||||
|
DownloadTab.AUDIO -> {
|
||||||
|
dl.downloadItems.any { it.type == FileType.AUDIO } && dl.downloadItems.none { it.type == FileType.VIDEO }
|
||||||
|
}
|
||||||
|
|
||||||
ids.forEach { id ->
|
DownloadTab.VIDEO -> {
|
||||||
if (isDownloading) {
|
dl.downloadItems.any { it.type == FileType.VIDEO }
|
||||||
service.pause(id)
|
|
||||||
} else {
|
|
||||||
service.resume(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
return@DownloadsAdapter isDownloading.not()
|
|
||||||
}
|
|
||||||
sortDownloadList(selectedSortType)
|
|
||||||
binding.downloads.adapter = adapter
|
|
||||||
|
|
||||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
if (downloads.isEmpty()) return@launch
|
||||||
override fun getMovementFlags(
|
|
||||||
recyclerView: RecyclerView,
|
|
||||||
viewHolder: RecyclerView.ViewHolder
|
|
||||||
): Int = makeMovementFlags(0, ItemTouchHelper.LEFT)
|
|
||||||
|
|
||||||
override fun onMove(
|
sortDownloadList(selectedSortType)
|
||||||
recyclerView: RecyclerView,
|
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
|
||||||
target: RecyclerView.ViewHolder
|
|
||||||
): Boolean = false
|
|
||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
adapter = DownloadsAdapter(requireContext(), downloadTabSelf, downloads) {
|
||||||
adapter.showDeleteDialog(requireContext(), viewHolder.absoluteAdapterPosition)
|
var isDownloading = false
|
||||||
// put the item back to the center, as it's currently out of the screen
|
val ids = it.downloadItems
|
||||||
adapter.restoreItem(viewHolder.absoluteAdapterPosition)
|
.filter { item -> item.path.fileSize() < item.downloadSize }
|
||||||
}
|
.map { item -> item.id }
|
||||||
}
|
|
||||||
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.downloads)
|
|
||||||
|
|
||||||
binding.downloads.adapter?.registerAdapterDataObserver(
|
if (!serviceConnection.isBound) {
|
||||||
object : RecyclerView.AdapterDataObserver() {
|
DownloadHelper.startDownloadService(requireContext())
|
||||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
bindDownloadService(ids.toIntArray())
|
||||||
super.onItemRangeRemoved(positionStart, itemCount)
|
return@DownloadsAdapter true
|
||||||
toggleButtonsVisibility()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
toggleButtonsVisibility()
|
binder?.getService()?.let { service ->
|
||||||
|
isDownloading = ids.any { id -> service.isDownloading(id) }
|
||||||
|
|
||||||
|
ids.forEach { id ->
|
||||||
|
if (isDownloading) {
|
||||||
|
service.pause(id)
|
||||||
|
} else {
|
||||||
|
service.resume(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@DownloadsAdapter isDownloading.not()
|
||||||
|
}
|
||||||
|
binding.downloadsRecView.adapter = adapter
|
||||||
|
|
||||||
|
val itemTouchCallback =
|
||||||
|
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||||
|
override fun getMovementFlags(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder
|
||||||
|
): Int = makeMovementFlags(0, ItemTouchHelper.LEFT)
|
||||||
|
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
target: RecyclerView.ViewHolder
|
||||||
|
): Boolean = false
|
||||||
|
|
||||||
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
|
adapter.showDeleteDialog(
|
||||||
|
requireContext(),
|
||||||
|
viewHolder.absoluteAdapterPosition
|
||||||
|
)
|
||||||
|
// put the item back to the center, as it's currently out of the screen
|
||||||
|
adapter.restoreItem(viewHolder.absoluteAdapterPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.downloadsRecView)
|
||||||
|
|
||||||
|
binding.downloadsRecView.adapter?.registerAdapterDataObserver(
|
||||||
|
object : RecyclerView.AdapterDataObserver() {
|
||||||
|
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||||
|
super.onItemRangeRemoved(positionStart, itemCount)
|
||||||
|
toggleVisibilities()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
toggleVisibilities()
|
||||||
|
}
|
||||||
|
|
||||||
binding.deleteAll.setOnClickListener {
|
binding.deleteAll.setOnClickListener {
|
||||||
showDeleteAllDialog(binding.root.context, adapter)
|
showDeleteAllDialog(binding.root.context, adapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleButtonsVisibility() {
|
private fun toggleVisibilities() {
|
||||||
val binding = _binding ?: return
|
val binding = _binding ?: return
|
||||||
|
|
||||||
val isEmpty = binding.downloads.adapter?.itemCount == 0
|
val isEmpty = downloads.isEmpty()
|
||||||
binding.downloadsEmpty.isVisible = isEmpty
|
binding.downloadsEmpty.isVisible = isEmpty
|
||||||
binding.downloads.isGone = isEmpty
|
binding.downloadsContainer.isGone = isEmpty
|
||||||
binding.sortType.isGone = isEmpty
|
|
||||||
binding.deleteAll.isGone = isEmpty
|
binding.deleteAll.isGone = isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortDownloadList(sortType: Int, previousSortType: Int? = null) {
|
private fun sortDownloadList(sortType: Int, previousSortType: Int? = null) {
|
||||||
if (previousSortType == null && sortType == 1) {
|
if (previousSortType == null && sortType == 1) {
|
||||||
downloads.reverse()
|
downloads.reverse()
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
if (previousSortType != null && sortType != previousSortType) {
|
if (previousSortType != null && sortType != previousSortType) {
|
||||||
downloads.reverse()
|
downloads.reverse()
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +332,7 @@ class DownloadsFragment : DynamicLayoutManagerFragment() {
|
|||||||
it.downloadItems.any { item -> item.id == id }
|
it.downloadItems.any { item -> item.id == id }
|
||||||
}
|
}
|
||||||
val view =
|
val view =
|
||||||
_binding?.downloads?.findViewHolderForAdapterPosition(index) as? DownloadsViewHolder
|
_binding?.downloadsRecView?.findViewHolderForAdapterPosition(index) as? DownloadsViewHolder
|
||||||
|
|
||||||
view?.binding?.apply {
|
view?.binding?.apply {
|
||||||
when (status) {
|
when (status) {
|
||||||
|
79
app/src/main/res/layout/fragment_download_content.xml
Normal file
79
app/src/main/res/layout/fragment_download_content.xml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/downloads_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sort_type"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="6dp"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:layout_marginVertical="4dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:paddingVertical="5dp"
|
||||||
|
android:text="@string/sort_by"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:drawableEndCompat="@drawable/ic_sort"
|
||||||
|
android:background="@drawable/rounded_ripple" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/downloads_recView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/downloads_empty"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:src="@drawable/ic_download" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/emptyList"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/delete_all"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_marginEnd="18dp"
|
||||||
|
android:layout_marginBottom="18dp"
|
||||||
|
android:contentDescription="@string/delete_all"
|
||||||
|
android:src="@drawable/ic_delete"
|
||||||
|
android:tooltipText="@string/delete"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
tools:targetApi="o"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,79 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:attr/colorBackground">
|
android:background="?android:attr/colorBackground">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sort_type"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:drawablePadding="10dp"
|
|
||||||
android:focusable="true"
|
|
||||||
android:fontFamily="@font/roboto"
|
|
||||||
android:paddingVertical="5dp"
|
|
||||||
android:text="@string/sort_by"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:drawableEndCompat="@drawable/ic_sort"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/downloads_empty"
|
android:id="@+id/downloads_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:orientation="vertical">
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:layout_width="100dp"
|
android:id="@+id/tab_layout"
|
||||||
android:layout_height="100dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:src="@drawable/ic_download" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="10dp"
|
app:tabMode="scrollable" />
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/emptyList"
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:textSize="20sp"
|
android:id="@+id/downloads_pager"
|
||||||
android:textStyle="bold" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/downloads"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/sort_type" />
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/delete_all"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_marginEnd="18dp"
|
|
||||||
android:layout_marginBottom="18dp"
|
|
||||||
android:contentDescription="@string/shuffle"
|
|
||||||
android:src="@drawable/ic_delete"
|
|
||||||
android:tooltipText="@string/delete"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:targetApi="o"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue
Block a user