implemented tablet ui & folder picker in terminal
This commit is contained in:
parent
81a47c3407
commit
326e701812
24 changed files with 474 additions and 122 deletions
|
|
@ -25,16 +25,14 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
import androidx.test.InstrumentationRegistry
|
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
import com.deniscerri.ytdlnis.ui.HomeFragment
|
||||||
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
|
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
|
||||||
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
|
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
|
||||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.navigation.NavigationBarView
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
|
|
@ -51,7 +49,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
private lateinit var preferences: SharedPreferences
|
private lateinit var preferences: SharedPreferences
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
private lateinit var cookieViewModel: CookieViewModel
|
private lateinit var cookieViewModel: CookieViewModel
|
||||||
private lateinit var bottomNav: BottomNavigationView
|
private lateinit var navigationView: NavigationBarView
|
||||||
private lateinit var navHostFragment : NavHostFragment
|
private lateinit var navHostFragment : NavHostFragment
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,20 +71,20 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
navHostFragment = supportFragmentManager.findFragmentById(R.id.frame_layout) as NavHostFragment
|
navHostFragment = supportFragmentManager.findFragmentById(R.id.frame_layout) as NavHostFragment
|
||||||
val navController = navHostFragment.findNavController()
|
val navController = navHostFragment.findNavController()
|
||||||
bottomNav = findViewById(R.id.bottomNavigationView)
|
navigationView = findViewById(R.id.bottomNavigationView)
|
||||||
|
|
||||||
window.decorView.setOnApplyWindowInsetsListener { view: View, windowInsets: WindowInsets? ->
|
window.decorView.setOnApplyWindowInsetsListener { view: View, windowInsets: WindowInsets? ->
|
||||||
val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(
|
val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(
|
||||||
windowInsets!!, view
|
windowInsets!!, view
|
||||||
)
|
)
|
||||||
val isImeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())
|
val isImeVisible = windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())
|
||||||
bottomNav.visibility =
|
navigationView.visibility =
|
||||||
if (isImeVisible) View.GONE else View.VISIBLE
|
if (isImeVisible) View.GONE else View.VISIBLE
|
||||||
view.onApplyWindowInsets(windowInsets)
|
view.onApplyWindowInsets(windowInsets)
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomNav.setupWithNavController(navController)
|
navigationView.setupWithNavController(navController)
|
||||||
bottomNav.setOnItemReselectedListener {
|
navigationView.setOnItemReselectedListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.homeFragment -> {
|
R.id.homeFragment -> {
|
||||||
(navHostFragment.childFragmentManager.primaryNavigationFragment!! as HomeFragment).scrollToTop()
|
(navHostFragment.childFragmentManager.primaryNavigationFragment!! as HomeFragment).scrollToTop()
|
||||||
|
|
@ -119,19 +117,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideNav() {
|
fun hideNav() {
|
||||||
bottomNav.visibility = View.GONE
|
navigationView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showNav() {
|
fun showNav() {
|
||||||
bottomNav.visibility = View.VISIBLE
|
navigationView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun disableBottomNavigation(){
|
fun disableBottomNavigation(){
|
||||||
bottomNav.menu.forEach { it.isEnabled = false }
|
navigationView.menu.forEach { it.isEnabled = false }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enableBottomNavigation(){
|
fun enableBottomNavigation(){
|
||||||
bottomNav.menu.forEach { it.isEnabled = true }
|
navigationView.menu.forEach { it.isEnabled = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
fun getActiveDownloads() : LiveData<List<DownloadItem>>
|
fun getActiveDownloads() : LiveData<List<DownloadItem>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
|
fun getActiveDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedDownloads() : LiveData<List<DownloadItem>>
|
fun getQueuedDownloads() : LiveData<List<DownloadItem>>
|
||||||
|
|
||||||
|
|
@ -46,8 +49,8 @@ interface DownloadDao {
|
||||||
@Query("DELETE FROM downloads WHERE status='Error'")
|
@Query("DELETE FROM downloads WHERE status='Error'")
|
||||||
suspend fun deleteErrored()
|
suspend fun deleteErrored()
|
||||||
|
|
||||||
@Query("DELETE FROM downloads WHERE status='Queued'")
|
@Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued'")
|
||||||
suspend fun deleteQueued()
|
suspend fun cancelQueued()
|
||||||
|
|
||||||
@Query("DELETE FROM downloads WHERE status='Processing' AND id=:id")
|
@Query("DELETE FROM downloads WHERE status='Processing' AND id=:id")
|
||||||
suspend fun deleteSingleProcessing(id: Long)
|
suspend fun deleteSingleProcessing(id: Long)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
return downloadDao.getDownloadById(id)
|
return downloadDao.getDownloadById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getActiveDownloads() : List<DownloadItem> {
|
||||||
|
return downloadDao.getActiveDownloadsList()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun deleteCancelled(){
|
suspend fun deleteCancelled(){
|
||||||
downloadDao.deleteCancelled()
|
downloadDao.deleteCancelled()
|
||||||
}
|
}
|
||||||
|
|
@ -52,8 +56,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
downloadDao.deleteErrored()
|
downloadDao.deleteErrored()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteQueued(){
|
suspend fun cancelQueued(){
|
||||||
downloadDao.deleteQueued()
|
downloadDao.cancelQueued()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkIfPresentForProcessing(item: ResultItem): DownloadItem{
|
fun checkIfPresentForProcessing(item: ResultItem): DownloadItem{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.deniscerri.ytdlnis.work.DownloadWorker
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
@ -261,29 +262,6 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putDownloadsForProcessing(items: List<ResultItem?>, downloadItems: List<DownloadItem>) : LiveData<List<Long>> {
|
|
||||||
val result = MutableLiveData<List<Long>>()
|
|
||||||
viewModelScope.launch(Dispatchers.IO){
|
|
||||||
val list : MutableList<Long> = mutableListOf()
|
|
||||||
items.forEachIndexed { i, it ->
|
|
||||||
val tmpDownloadItem = downloadItems[i]
|
|
||||||
try {
|
|
||||||
val item = repository.checkIfPresentForProcessing(it!!)
|
|
||||||
tmpDownloadItem.id = item.id
|
|
||||||
tmpDownloadItem.status = DownloadRepository.Status.Processing.toString()
|
|
||||||
repository.update(tmpDownloadItem)
|
|
||||||
list.add(tmpDownloadItem.id)
|
|
||||||
}catch (e: Exception){
|
|
||||||
val id = repository.insert(tmpDownloadItem)
|
|
||||||
list.add(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
result.postValue(list)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteCancelled() = viewModelScope.launch(Dispatchers.IO) {
|
fun deleteCancelled() = viewModelScope.launch(Dispatchers.IO) {
|
||||||
repository.deleteCancelled()
|
repository.deleteCancelled()
|
||||||
}
|
}
|
||||||
|
|
@ -292,15 +270,19 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
repository.deleteErrored()
|
repository.deleteErrored()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteQueued() = viewModelScope.launch(Dispatchers.IO) {
|
fun cancelQueued() = viewModelScope.launch(Dispatchers.IO) {
|
||||||
repository.deleteQueued()
|
repository.cancelQueued()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cloneFormat(item: Format) : Format {
|
private fun cloneFormat(item: Format) : Format {
|
||||||
val string = Gson().toJson(item, Format::class.java)
|
val string = Gson().toJson(item, Format::class.java)
|
||||||
return Gson().fromJson(string, Format::class.java)
|
return Gson().fromJson(string, Format::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getActiveDownloads() : List<DownloadItem>{
|
||||||
|
return repository.getActiveDownloads()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun queueDownloads(items: List<DownloadItem>) {
|
suspend fun queueDownloads(items: List<DownloadItem>) {
|
||||||
val context = getApplication<App>().applicationContext
|
val context = getApplication<App>().applicationContext
|
||||||
val allowMeteredNetworks = sharedPreferences.getBoolean("metered_networks", true)
|
val allowMeteredNetworks = sharedPreferences.getBoolean("metered_networks", true)
|
||||||
|
|
|
||||||
|
|
@ -138,10 +138,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
requireActivity()
|
requireActivity()
|
||||||
)
|
)
|
||||||
recyclerView = view.findViewById(R.id.recyclerViewHome)
|
recyclerView = view.findViewById(R.id.recyclerViewHome)
|
||||||
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)){
|
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)){
|
||||||
recyclerView?.layoutManager = GridLayoutManager(context, 2)
|
recyclerView?.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
recyclerView?.adapter = homeAdapter
|
recyclerView?.adapter = homeAdapter
|
||||||
|
|
||||||
|
|
@ -478,8 +476,10 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||||
showSingleDownloadSheet(item!!, type!!)
|
showSingleDownloadSheet(item!!, type!!)
|
||||||
} else {
|
} else {
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
lifecycleScope.launch{
|
||||||
val downloadItem = downloadViewModel.createDownloadItemFromResult(item!!, type!!)
|
val downloadItem = withContext(Dispatchers.IO){
|
||||||
|
downloadViewModel.createDownloadItemFromResult(item!!, type!!)
|
||||||
|
}
|
||||||
downloadViewModel.queueDownloads(listOf(downloadItem))
|
downloadViewModel.queueDownloads(listOf(downloadItem))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,13 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
|
|
||||||
val formatListener = object : OnFormatClickListener {
|
val formatListener = object : OnFormatClickListener {
|
||||||
override fun onFormatClick(allFormats: List<List<Format>>, selectedFormats: List<Format>) {
|
override fun onFormatClick(allFormats: List<List<Format>>, selectedFormats: List<Format>) {
|
||||||
|
val formatCollection = mutableListOf<List<Format>>()
|
||||||
|
allFormats.forEach {f ->
|
||||||
|
formatCollection.add(f.mapTo(mutableListOf()) {it.copy()})
|
||||||
|
}
|
||||||
items.forEachIndexed { index, it ->
|
items.forEachIndexed { index, it ->
|
||||||
it.allFormats.clear()
|
it.allFormats.clear()
|
||||||
it.allFormats.addAll(allFormats[index])
|
it.allFormats.addAll(formatCollection[index])
|
||||||
it.format = selectedFormats[index]
|
it.format = selectedFormats[index]
|
||||||
}
|
}
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
|
|
|
||||||
|
|
@ -70,25 +70,33 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
|
|
||||||
if (items.size > 1){
|
if (items.size > 1){
|
||||||
val hasGenericFormats = when(items.first()!!.type){
|
val hasGenericFormats = when(items.first()!!.type){
|
||||||
Type.audio -> formats.flatten().size == resources.getStringArray(R.array.audio_formats).size
|
Type.audio -> formats.first().size == resources.getStringArray(R.array.audio_formats).size
|
||||||
else -> formats.flatten().size == resources.getStringArray(R.array.video_formats).size
|
else -> formats.first().size == resources.getStringArray(R.array.video_formats).size
|
||||||
}
|
}
|
||||||
if (!hasGenericFormats){
|
if (!hasGenericFormats){
|
||||||
formatCollection.addAll(formats)
|
formatCollection.addAll(formats)
|
||||||
val flattenFormats = formats.flatten()
|
val flattenFormats = formats.flatten()
|
||||||
val commonFormats = flattenFormats.groupingBy { it.format_id }.eachCount().filter { it.value == items.size }.mapValues { flattenFormats.first { f -> f.format_id == it.key } }.map { it.value }
|
val commonFormats = flattenFormats.groupingBy { it.format_id }.eachCount().filter { it.value == items.size }.mapValues { flattenFormats.first { f -> f.format_id == it.key } }.map { it.value }
|
||||||
commonFormats.forEach {
|
chosenFormats = commonFormats.mapTo(mutableListOf()) {it.copy()}
|
||||||
|
chosenFormats = when(items.first()?.type){
|
||||||
|
Type.audio -> chosenFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
else -> chosenFormats.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
}
|
||||||
|
chosenFormats.forEach {
|
||||||
it.filesize =
|
it.filesize =
|
||||||
flattenFormats.filter { f -> f.format_id == it.format_id }
|
flattenFormats.filter { f -> f.format_id == it.format_id }
|
||||||
.sumOf { itt -> itt.filesize }
|
.sumOf { itt -> itt.filesize }
|
||||||
}
|
}
|
||||||
chosenFormats = commonFormats
|
|
||||||
}else{
|
}else{
|
||||||
chosenFormats = formats.flatten()
|
chosenFormats = formats.flatten()
|
||||||
}
|
}
|
||||||
addFormatsToView(linearLayout)
|
addFormatsToView(linearLayout)
|
||||||
}else{
|
}else{
|
||||||
chosenFormats = formats.flatten()
|
chosenFormats = formats.flatten()
|
||||||
|
chosenFormats = when(items.first()?.type){
|
||||||
|
Type.audio -> chosenFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
else -> chosenFormats.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
}
|
||||||
addFormatsToView(linearLayout)
|
addFormatsToView(linearLayout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +126,7 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
//playlist format filtering
|
//playlist format filtering
|
||||||
}else{
|
}else{
|
||||||
var progress = "0/${items.size}"
|
var progress = "0/${items.size}"
|
||||||
|
formatCollection.clear()
|
||||||
refreshBtn.text = progress
|
refreshBtn.text = progress
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
infoUtil.getFormatsMultiple(items.map { it!!.url }) {
|
infoUtil.getFormatsMultiple(items.map { it!!.url }) {
|
||||||
|
|
@ -167,7 +176,6 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
}
|
}
|
||||||
private fun addFormatsToView(linearLayout: LinearLayout){
|
private fun addFormatsToView(linearLayout: LinearLayout){
|
||||||
linearLayout.removeAllViews()
|
linearLayout.removeAllViews()
|
||||||
Log.e("aa", chosenFormats.toString())
|
|
||||||
for (i in chosenFormats.lastIndex downTo 0){
|
for (i in chosenFormats.lastIndex downTo 0){
|
||||||
val format = chosenFormats[i]
|
val format = chosenFormats[i]
|
||||||
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnClickListener
|
import android.view.View.OnClickListener
|
||||||
|
|
@ -65,12 +66,11 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL
|
||||||
activeRecyclerView = view.findViewById(R.id.download_recyclerview)
|
activeRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||||
activeRecyclerView.adapter = activeDownloads
|
activeRecyclerView.adapter = activeDownloads
|
||||||
|
|
||||||
val landScapeOrTablet = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)
|
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||||
if (landScapeOrTablet){
|
if (landScape){
|
||||||
activeRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
activeRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
activeRecyclerView.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
|
if (resources.getBoolean(R.bool.isTablet)) activeRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||||
|
|
||||||
downloadViewModel.activeDownloads.observe(viewLifecycleOwner) {
|
downloadViewModel.activeDownloads.observe(viewLifecycleOwner) {
|
||||||
activeDownloads.submitList(it)
|
activeDownloads.submitList(it)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
@ -69,12 +70,11 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
cancelledRecyclerView = view.findViewById(R.id.download_recyclerview)
|
cancelledRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||||
cancelledRecyclerView.adapter = cancelledDownloads
|
cancelledRecyclerView.adapter = cancelledDownloads
|
||||||
|
|
||||||
val landScapeOrTablet = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)
|
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||||
if (landScapeOrTablet){
|
if (landScape){
|
||||||
cancelledRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
cancelledRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
cancelledRecyclerView.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
|
if (resources.getBoolean(R.bool.isTablet)) cancelledRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||||
|
|
||||||
downloadViewModel.cancelledDownloads.observe(viewLifecycleOwner) {
|
downloadViewModel.cancelledDownloads.observe(viewLifecycleOwner) {
|
||||||
items = it
|
items = it
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,21 @@ import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import androidx.work.await
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
class DownloadQueueActivity : AppCompatActivity(){
|
class DownloadQueueActivity : AppCompatActivity(){
|
||||||
|
|
@ -85,7 +92,7 @@ class DownloadQueueActivity : AppCompatActivity(){
|
||||||
R.id.clear_queue -> {
|
R.id.clear_queue -> {
|
||||||
showDeleteDialog() {
|
showDeleteDialog() {
|
||||||
cancelAllDownloads()
|
cancelAllDownloads()
|
||||||
downloadViewModel.deleteQueued()
|
downloadViewModel.cancelQueued()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.clear_cancelled -> {
|
R.id.clear_cancelled -> {
|
||||||
|
|
@ -118,7 +125,20 @@ class DownloadQueueActivity : AppCompatActivity(){
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelAllDownloads() {
|
private fun cancelAllDownloads() {
|
||||||
workManager.cancelAllWork()
|
lifecycleScope.launch {
|
||||||
|
val notificationUtil = NotificationUtil(this@DownloadQueueActivity)
|
||||||
|
val activeDownloads = withContext(Dispatchers.IO){
|
||||||
|
downloadViewModel.getActiveDownloads()
|
||||||
|
}
|
||||||
|
val workManager = WorkManager.getInstance(this@DownloadQueueActivity)
|
||||||
|
activeDownloads.forEach {
|
||||||
|
val id = it.id.toInt()
|
||||||
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
|
workManager.cancelUniqueWork(id.toString())
|
||||||
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
|
}
|
||||||
|
workManager.cancelAllWorkByTag("download")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
@ -71,12 +72,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
erroredRecyclerView = view.findViewById(R.id.download_recyclerview)
|
erroredRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||||
erroredRecyclerView.adapter = erroredDownloads
|
erroredRecyclerView.adapter = erroredDownloads
|
||||||
|
|
||||||
val landScapeOrTablet = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)
|
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||||
if (landScapeOrTablet){
|
if (landScape){
|
||||||
erroredRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
erroredRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
erroredRecyclerView.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
|
if (resources.getBoolean(R.bool.isTablet)) erroredRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||||
|
|
||||||
downloadViewModel.erroredDownloads.observe(viewLifecycleOwner) {
|
downloadViewModel.erroredDownloads.observe(viewLifecycleOwner) {
|
||||||
items = it
|
items = it
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
|
|
@ -112,11 +113,11 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
requireActivity()
|
requireActivity()
|
||||||
)
|
)
|
||||||
recyclerView = view.findViewById(R.id.recyclerviewhistorys)
|
recyclerView = view.findViewById(R.id.recyclerviewhistorys)
|
||||||
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)){
|
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)){
|
||||||
recyclerView?.layoutManager = GridLayoutManager(context, 2)
|
recyclerView?.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
|
if (resources.getBoolean(R.bool.isTablet)) recyclerView?.layoutManager = GridLayoutManager(context, 3)
|
||||||
|
|
||||||
recyclerView?.adapter = historyAdapter
|
recyclerView?.adapter = historyAdapter
|
||||||
|
|
||||||
noResults?.visibility = GONE
|
noResults?.visibility = GONE
|
||||||
|
|
@ -483,7 +484,9 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
else redownload.visibility = GONE
|
else redownload.visibility = GONE
|
||||||
|
|
||||||
bottomSheet!!.show()
|
bottomSheet!!.show()
|
||||||
bottomSheet!!.behavior.peekHeight = 512
|
val displayMetrics = DisplayMetrics()
|
||||||
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
|
bottomSheet!!.behavior.peekHeight = displayMetrics.heightPixels
|
||||||
bottomSheet!!.window!!.setLayout(
|
bottomSheet!!.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
@ -79,12 +80,11 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
queuedRecyclerView = view.findViewById(R.id.download_recyclerview)
|
queuedRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||||
queuedRecyclerView.adapter = queuedDownloads
|
queuedRecyclerView.adapter = queuedDownloads
|
||||||
|
|
||||||
val landScapeOrTablet = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE || resources.getBoolean(R.bool.isTablet)
|
val landScape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && ! resources.getBoolean(R.bool.isTablet)
|
||||||
if (landScapeOrTablet){
|
if (landScape){
|
||||||
queuedRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
queuedRecyclerView.layoutManager = GridLayoutManager(context, 2)
|
||||||
}else{
|
|
||||||
queuedRecyclerView.layoutManager = LinearLayoutManager(context)
|
|
||||||
}
|
}
|
||||||
|
if (resources.getBoolean(R.bool.isTablet)) queuedRecyclerView.layoutManager = GridLayoutManager(context, 3)
|
||||||
|
|
||||||
downloadViewModel.queuedDownloads.observe(viewLifecycleOwner) {
|
downloadViewModel.queuedDownloads.observe(viewLifecycleOwner) {
|
||||||
items = it
|
items = it
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
|
@ -58,6 +59,7 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
private lateinit var observer: FileObserver
|
private lateinit var observer: FileObserver
|
||||||
private lateinit var imm : InputMethodManager
|
private lateinit var imm : InputMethodManager
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
|
private lateinit var fileUtil: FileUtil
|
||||||
var context: Context? = null
|
var context: Context? = null
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -68,7 +70,8 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
||||||
if (! downloadFile.exists()) downloadFile.createNewFile()
|
if (! downloadFile.exists()) downloadFile.createNewFile()
|
||||||
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
uiUtil = UiUtil(FileUtil())
|
fileUtil = FileUtil()
|
||||||
|
uiUtil = UiUtil(fileUtil)
|
||||||
|
|
||||||
context = baseContext
|
context = baseContext
|
||||||
scrollView = findViewById(R.id.custom_command_scrollview)
|
scrollView = findViewById(R.id.custom_command_scrollview)
|
||||||
|
|
@ -105,7 +108,13 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.shortcuts -> showShortcuts()
|
R.id.shortcuts -> showShortcuts()
|
||||||
else -> {}
|
R.id.folder -> {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||||
|
commandPathResultLauncher.launch(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -253,6 +262,21 @@ class TerminalActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var commandPathResultLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
result.data?.data?.let {
|
||||||
|
contentResolver?.takePersistableUriPermission(
|
||||||
|
it,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
input!!.text.insert(input!!.selectionStart, fileUtil.formatPath(result.data?.data.toString()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startDownload(command: String?) {
|
private fun startDownload(command: String?) {
|
||||||
val cmd = if (command!!.contains("yt-dlp")) command.replace("yt-dlp", "")
|
val cmd = if (command!!.contains("yt-dlp")) command.replace("yt-dlp", "")
|
||||||
else command
|
else command
|
||||||
|
|
|
||||||
|
|
@ -614,17 +614,19 @@ class InfoUtil(private val context: Context) {
|
||||||
var playlistTitle: String? = ""
|
var playlistTitle: String? = ""
|
||||||
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
||||||
if(playlistTitle.equals(query)) playlistTitle = ""
|
if(playlistTitle.equals(query)) playlistTitle = ""
|
||||||
val formatsInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JsonArray) jsonObject.getJSONArray("formats") else null
|
val formatsInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JSONArray) jsonObject.getJSONArray("formats") else null
|
||||||
val formats : ArrayList<Format> = ArrayList()
|
val formats : ArrayList<Format> = ArrayList()
|
||||||
if (formatsInJSON != null) {
|
if (formatsInJSON != null) {
|
||||||
for (f in 0 until formatsInJSON.length()){
|
for (f in 0 until formatsInJSON.length()){
|
||||||
val format = formatsInJSON.getJSONObject(f)
|
val format = formatsInJSON.getJSONObject(f)
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
if (formatProper.filesize > 0){
|
if (formatProper.filesize > 0){
|
||||||
if ( !formatProper.format_note.contains("audio only", true)) {
|
if (format.has("format_note")){
|
||||||
formatProper.format_note = format.getString("format_note")
|
if ( !formatProper.format_note.contains("audio only", true)) {
|
||||||
}else{
|
formatProper.format_note = format.getString("format_note")
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
}else{
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
formatProper.container = format.getString("ext")
|
formatProper.container = format.getString("ext")
|
||||||
formats.add(formatProper)
|
formats.add(formatProper)
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class TerminalDownloadWorker(
|
||||||
request.addOption("--cookies", cookiesFile.absolutePath)
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
request.addOption("-P", tempFileDir.absolutePath)
|
if (!command.contains("-P ")) request.addOption("-P", tempFileDir.absolutePath)
|
||||||
|
|
||||||
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
||||||
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/baseline_folder_24.xml
Normal file
5
app/src/main/res/drawable/baseline_folder_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector 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="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/>
|
||||||
|
</vector>
|
||||||
48
app/src/main/res/layout-sw800dp/activity_main.xml
Normal file
48
app/src/main/res/layout-sw800dp/activity_main.xml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?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"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/incognito_header"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Incognito"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:background="?colorPrimaryContainer"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/frame_layout"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:navGraph="@navigation/nav_graph"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/bottomNavigationView"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/incognito_header"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.google.android.material.navigationrail.NavigationRailView
|
||||||
|
android:id="@+id/bottomNavigationView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:labelVisibilityMode="unlabeled"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:menu="@menu/bottom_nav_menu" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
235
app/src/main/res/layout-sw800dp/fragment_home.xml
Normal file
235
app/src/main/res/layout-sw800dp/fragment_home.xml
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
<?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/homecoordinator"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<com.google.android.material.search.SearchView
|
||||||
|
android:id="@+id/search_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:hint="@string/search_hint"
|
||||||
|
app:layout_anchor="@id/search_bar">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/search_history_scroll_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/queries_constraint"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/queries"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/init_search_query"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="false" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/init_search_query"
|
||||||
|
style="?attr/materialIconButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:iconSize="20dp"
|
||||||
|
app:cornerRadius="10dp"
|
||||||
|
app:icon="@drawable/ic_search"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="-10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/link_you_copied"
|
||||||
|
layout="@layout/search_suggestion_item"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/search_history_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/search_suggestions_scroll_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/search_suggestions_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.search.SearchView>
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/home_appbarlayout"
|
||||||
|
app:liftOnScroll="true"
|
||||||
|
android:background="@null"
|
||||||
|
android:elevation="0dp"
|
||||||
|
app:elevation="0dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:layout_scrollFlags="scroll"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/home_toolbar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/Toolbar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:title="@string/app_name" />
|
||||||
|
|
||||||
|
<com.google.android.material.search.SearchBar
|
||||||
|
android:id="@+id/search_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
|
android:hint="@string/search_hint"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/home_toolbar"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:menu="@menu/main_menu" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/recyclerViewHome"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="100dp"
|
||||||
|
app:spanCount="3"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<com.facebook.shimmer.ShimmerFrameLayout
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/shimmer_results_framelayout"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/shimmer_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/home_fabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/download_all_coordinator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/download_all_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:text="@string/download_all"
|
||||||
|
app:icon="@drawable/ic_down"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/download_selected_coordinator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/download_selected_fab"
|
||||||
|
app:elevation="0dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
app:icon="@drawable/ic_down"
|
||||||
|
android:text="@string/download"
|
||||||
|
app:srcCompat="@drawable/ic_music"/>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
@ -50,17 +50,18 @@
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/download_type"
|
android:id="@+id/download_type"
|
||||||
style="?attr/materialIconButtonFilledTonalStyle"
|
style="?attr/materialIconButtonFilledTonalStyle"
|
||||||
app:backgroundTint="?attr/colorSurface"
|
android:layout_width="24dp"
|
||||||
android:layout_width="32dp"
|
android:layout_height="24dp"
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:insetLeft="0dp"
|
android:insetLeft="0dp"
|
||||||
android:insetTop="0dp"
|
android:insetTop="0dp"
|
||||||
android:insetRight="0dp"
|
android:insetRight="0dp"
|
||||||
android:insetBottom="0dp"
|
android:insetBottom="0dp"
|
||||||
|
app:backgroundTint="?attr/colorSurface"
|
||||||
app:icon="@drawable/ic_music"
|
app:icon="@drawable/ic_music"
|
||||||
|
app:iconGravity="textStart"
|
||||||
app:iconPadding="0dp"
|
app:iconPadding="0dp"
|
||||||
app:iconSize="13dp"
|
app:iconSize="11dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Full" />
|
app:shapeAppearanceOverlay="@style/ShapeAppearance.Material3.Corner.Full" />
|
||||||
|
|
@ -68,17 +69,19 @@
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:id="@+id/linearlayout2_horizontalscrollview"
|
android:id="@+id/linearlayout2_horizontalscrollview"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/title_author"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/download_type">
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/download_type"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/linearLayout2"
|
android:id="@+id/linearLayout2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="24dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="10dp"
|
android:paddingHorizontal="10dp"
|
||||||
|
|
@ -89,40 +92,43 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
app:chipStrokeWidth="0.5dp"
|
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.RoundedStart"
|
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
|
app:chipBackgroundColor="?attr/colorSurface"
|
||||||
app:chipMinTouchTargetSize="0dp"
|
app:chipMinTouchTargetSize="0dp"
|
||||||
|
app:chipStrokeWidth="0.5dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.RoundedStart" />
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/codec"
|
android:id="@+id/codec"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.Middle"
|
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
app:chipStrokeWidth="0.5dp"
|
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
|
app:chipBackgroundColor="?attr/colorSurface"
|
||||||
app:chipMinTouchTargetSize="0dp"
|
app:chipMinTouchTargetSize="0dp"
|
||||||
|
app:chipStrokeWidth="0.5dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.Middle" />
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.chip.Chip
|
||||||
android:id="@+id/file_size"
|
android:id="@+id/file_size"
|
||||||
app:chipStrokeWidth="0.5dp"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.RoundedEnd"
|
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
|
app:chipBackgroundColor="?attr/colorSurface"
|
||||||
app:chipMinTouchTargetSize="0dp"
|
app:chipMinTouchTargetSize="0dp"
|
||||||
|
app:chipStrokeWidth="0.5dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Chip.RoundedEnd" />
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
|
@ -131,13 +137,14 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/title_author"
|
android:id="@+id/title_author"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:dividerPadding="5dp"
|
android:dividerPadding="5dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/active_download_cancel"
|
app:layout_constraintEnd_toStartOf="@+id/active_download_cancel"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/download_type">
|
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
|
|
@ -177,10 +184,26 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/active_download_cancel"
|
||||||
|
style="?attr/materialIconButtonFilledStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:backgroundTint="?attr/colorSurface"
|
||||||
|
app:cornerRadius="10dp"
|
||||||
|
app:icon="@drawable/ic_cancel"
|
||||||
|
app:iconSize="30dp"
|
||||||
|
app:iconTint="?android:textColorPrimary"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||||
|
app:layout_constraintVertical_bias="0.51" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/output"
|
android:id="@+id/output"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
|
@ -197,20 +220,6 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/active_download_cancel"
|
|
||||||
style="?attr/materialIconButtonFilledStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
app:cornerRadius="10dp"
|
|
||||||
app:backgroundTint="?attr/colorSurface"
|
|
||||||
app:iconTint="?android:textColorPrimary"
|
|
||||||
app:icon="@drawable/ic_cancel"
|
|
||||||
app:iconSize="30dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/title_author" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
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"
|
||||||
android:fillViewport="true"
|
android:fillViewport="true"
|
||||||
android:scrollbars="none">
|
android:scrollbars="none">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/download_recyclerview"
|
android:id="@+id/download_recyclerview"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,9 @@
|
||||||
android:icon="@drawable/ic_shortcut"
|
android:icon="@drawable/ic_shortcut"
|
||||||
app:showAsAction="ifRoom"
|
app:showAsAction="ifRoom"
|
||||||
android:id="@+id/shortcuts"/>
|
android:id="@+id/shortcuts"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/folder"
|
||||||
|
android:title="@string/command_directory"
|
||||||
|
android:icon="@drawable/baseline_folder_24"
|
||||||
|
app:showAsAction="collapseActionView|ifRoom"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
@ -55,18 +55,18 @@
|
||||||
|
|
||||||
<style name="ShapeAppearanceOverlay.Chip.RoundedStart" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
<style name="ShapeAppearanceOverlay.Chip.RoundedStart" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
||||||
<item name="cornerFamily">rounded</item>
|
<item name="cornerFamily">rounded</item>
|
||||||
<item name="cornerSizeTopLeft">15dp</item>
|
<item name="cornerSizeTopLeft">12dp</item>
|
||||||
<item name="cornerSizeTopRight">0dp</item>
|
<item name="cornerSizeTopRight">0dp</item>
|
||||||
<item name="cornerSizeBottomLeft">15dp</item>
|
<item name="cornerSizeBottomLeft">12dp</item>
|
||||||
<item name="cornerSizeBottomRight">0dp</item>
|
<item name="cornerSizeBottomRight">0dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ShapeAppearanceOverlay.Chip.RoundedEnd" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
<style name="ShapeAppearanceOverlay.Chip.RoundedEnd" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
||||||
<item name="cornerFamily">rounded</item>
|
<item name="cornerFamily">rounded</item>
|
||||||
<item name="cornerSizeTopLeft">0dp</item>
|
<item name="cornerSizeTopLeft">0dp</item>
|
||||||
<item name="cornerSizeTopRight">15dp</item>
|
<item name="cornerSizeTopRight">12dp</item>
|
||||||
<item name="cornerSizeBottomLeft">0dp</item>
|
<item name="cornerSizeBottomLeft">0dp</item>
|
||||||
<item name="cornerSizeBottomRight">15dp</item>
|
<item name="cornerSizeBottomRight">12dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ShapeAppearanceOverlay.Chip.Middle" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
<style name="ShapeAppearanceOverlay.Chip.Middle" parent="ShapeAppearance.MaterialComponents.SmallComponent">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue