added search by author

pull/179/head
deniscerri 3 years ago
parent 6686868de0
commit 2630954136
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -64,10 +64,11 @@ android {
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
} }
dev { beta {
minifyEnabled false minifyEnabled true
versionNameSuffix "$project.betaVersionNameSuffix"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable true debuggable false
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
} }
@ -180,4 +181,5 @@ dependencies {
implementation 'it.xabaras.android:recyclerview-swipedecorator:1.4' implementation 'it.xabaras.android:recyclerview-swipedecorator:1.4'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1"
implementation "com.github.Irineu333:Highlight-KT:1.0.4" implementation "com.github.Irineu333:Highlight-KT:1.0.4"
implementation "com.anggrayudi:storage:1.5.4"
} }

@ -12,7 +12,6 @@ import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.PersistableBundle
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import android.view.View import android.view.View
@ -24,6 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
@ -39,7 +39,6 @@ import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.ui.BaseActivity import com.deniscerri.ytdlnis.ui.BaseActivity
import com.deniscerri.ytdlnis.ui.HomeFragment import com.deniscerri.ytdlnis.ui.HomeFragment
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdlnis.util.ThemeUtil
import com.deniscerri.ytdlnis.util.UpdateUtil import com.deniscerri.ytdlnis.util.UpdateUtil
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
@ -50,7 +49,6 @@ import com.google.android.material.navigation.NavigationView
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.BufferedReader import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader import java.io.InputStreamReader
import java.io.Reader import java.io.Reader
import java.nio.charset.Charset import java.nio.charset.Charset
@ -108,13 +106,7 @@ class MainActivity : BaseActivity() {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
val startDestination = sharedPreferences.getString("start_destination", "")
val graph = navController.navInflater.inflate(R.navigation.nav_graph) val graph = navController.navInflater.inflate(R.navigation.nav_graph)
when(startDestination) {
"History" -> graph.setStartDestination(R.id.historyFragment)
"More" -> if (navigationView is NavigationBarView) graph.setStartDestination(R.id.moreFragment) else graph.setStartDestination(R.id.homeFragment)
else -> graph.setStartDestination(R.id.homeFragment)
}
navController.graph = graph navController.graph = graph
if (navigationView is NavigationBarView){ if (navigationView is NavigationBarView){
@ -183,48 +175,78 @@ class MainActivity : BaseActivity() {
cookieViewModel.updateCookiesFile() cookieViewModel.updateCookiesFile()
val intent = intent val intent = intent
handleIntents(intent) handleIntents(intent)
navController.addOnDestinationChangedListener { _, destination, _ ->
if (navigationView is NavigationBarView){
when(destination.id){
R.id.homeFragment, R.id.historyFragment, R.id.moreFragment -> showBottomNavigation()
else -> hideBottomNavigation()
}
}
}
navigationView.visibilityChanged {
if (it.isVisible){
val curr = navController.currentDestination?.id
if (curr != R.id.homeFragment && curr != R.id.historyFragment && curr != R.id.moreFragment) hideBottomNavigation()
}
}
when(sharedPreferences.getString("start_destination", "")) {
"History" -> navController.navigate(R.id.historyFragment)
"Queue" -> navController.navigate(R.id.downloadQueueMainFragment)
"More" -> if (navigationView is NavigationBarView) graph.setStartDestination(R.id.moreFragment)
}
}
private fun View.visibilityChanged(action: (View) -> Unit) {
this.viewTreeObserver.addOnGlobalLayoutListener {
val newVis: Int = this.visibility
if (this.tag as Int? != newVis) {
this.tag = this.visibility
// visibility has changed
action(this)
}
}
} }
fun hideBottomNavigation(){ fun hideBottomNavigation(){
if(navigationView is NavigationBarView){ if (navigationView is BottomNavigationView){
if (navigationView is BottomNavigationView){ findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams<ConstraintLayout.LayoutParams> {
findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams<ConstraintLayout.LayoutParams> { bottomToTop = ConstraintLayout.LayoutParams.UNSET
bottomToTop = ConstraintLayout.LayoutParams.UNSET bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID }
} navigationView.animate()?.translationY(navigationView.height.toFloat())?.setDuration(300)?.withEndAction {
navigationView.animate()?.translationY(navigationView.height.toFloat())?.setDuration(300)?.withEndAction { navigationView.visibility = View.GONE
navigationView.visibility = View.GONE }?.start()
}?.start() }else{
}else{ findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams {
findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams { this.width = LayoutParams.MATCH_PARENT
this.width = LayoutParams.MATCH_PARENT
}
navigationView.animate()?.translationX(-navigationView.width.toFloat())?.setDuration(300)?.withEndAction {
navigationView.visibility = View.GONE
}?.start()
} }
navigationView.animate()?.translationX(-navigationView.width.toFloat())?.setDuration(300)?.withEndAction {
navigationView.visibility = View.GONE
}?.start()
} }
} }
fun showBottomNavigation(){ fun showBottomNavigation(){
if(navigationView is NavigationBarView){ if (navigationView is BottomNavigationView){
if (navigationView is BottomNavigationView){ findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams<ConstraintLayout.LayoutParams> {
findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams<ConstraintLayout.LayoutParams> { bottomToTop = R.id.bottomNavigationView
bottomToTop = R.id.bottomNavigationView bottomToBottom = ConstraintLayout.LayoutParams.UNSET
bottomToBottom = ConstraintLayout.LayoutParams.UNSET }
} navigationView.animate()?.translationY(0F)?.setDuration(300)?.withEndAction {
navigationView.animate()?.translationY(0F)?.setDuration(300)?.withEndAction { navigationView.visibility = View.VISIBLE
navigationView.visibility = View.VISIBLE }?.start()
}?.start() }else{
}else{ findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams {
findViewById<FragmentContainerView>(R.id.frame_layout).updateLayoutParams { this.width = 0
this.width = 0
}
navigationView.animate()?.translationX(0F)?.setDuration(300)?.withEndAction {
navigationView.visibility = View.VISIBLE
}?.start()
} }
navigationView.animate()?.translationX(0F)?.setDuration(300)?.withEndAction {
navigationView.visibility = View.VISIBLE
}?.start()
} }
} }

@ -49,6 +49,9 @@ interface DownloadDao {
@Query("SELECT id FROM downloads ORDER BY id DESC LIMIT 1") @Query("SELECT id FROM downloads ORDER BY id DESC LIMIT 1")
fun getLastDownloadId(): Long fun getLastDownloadId(): Long
@Query("SELECT status FROM downloads WHERE id=:id")
fun checkStatus(id: Long) : String
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(item: DownloadItem) : Long suspend fun insert(item: DownloadItem) : Long

@ -7,19 +7,19 @@ import com.deniscerri.ytdlnis.database.models.HistoryItem
@Dao @Dao
interface HistoryDao { interface HistoryDao {
@Query("SELECT * FROM history WHERE title LIKE '%'||:query||'%' AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " + @Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
"CASE WHEN :sort = 'ASC' THEN id END ASC," + "CASE WHEN :sort = 'ASC' THEN id END ASC," +
"CASE WHEN :sort = 'DESC' THEN id END DESC," + "CASE WHEN :sort = 'DESC' THEN id END DESC," +
"CASE WHEN :sort = '' THEN id END DESC ") "CASE WHEN :sort = '' THEN id END DESC ")
fun getHistorySortedByID(query : String, format : String, site : String, sort : String) : List<HistoryItem> fun getHistorySortedByID(query : String, format : String, site : String, sort : String) : List<HistoryItem>
@Query("SELECT * FROM history WHERE title LIKE '%'||:query||'%' AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " + @Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
"CASE WHEN :sort = 'ASC' THEN title END ASC," + "CASE WHEN :sort = 'ASC' THEN title END ASC," +
"CASE WHEN :sort = 'DESC' THEN title END DESC," + "CASE WHEN :sort = 'DESC' THEN title END DESC," +
"CASE WHEN :sort = '' THEN title END DESC ") "CASE WHEN :sort = '' THEN title END DESC ")
fun getHistorySortedByTitle(query : String, format : String, site : String, sort : String) : List<HistoryItem> fun getHistorySortedByTitle(query : String, format : String, site : String, sort : String) : List<HistoryItem>
@Query("SELECT * FROM history WHERE title LIKE '%'||:query||'%' AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " + @Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:format||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
"CASE WHEN :sort = 'ASC' THEN author END ASC," + "CASE WHEN :sort = 'ASC' THEN author END ASC," +
"CASE WHEN :sort = 'DESC' THEN author END DESC," + "CASE WHEN :sort = 'DESC' THEN author END DESC," +
"CASE WHEN :sort = '' THEN author END DESC ") "CASE WHEN :sort = '' THEN author END DESC ")

@ -6,10 +6,8 @@ import android.content.SharedPreferences
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.os.Environment
import android.os.Looper import android.os.Looper
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
@ -43,7 +41,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.File
import java.util.Locale import java.util.Locale
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -141,12 +138,16 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
return repository.getItemByID(id) return repository.getItemByID(id)
} }
fun createDownloadItemFromResult(resultItem: ResultItem, type: Type) : DownloadItem { fun createDownloadItemFromResult(resultItem: ResultItem, givenType: Type) : DownloadItem {
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false) val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
val saveSubs = sharedPreferences.getBoolean("write_subtitles", false) val saveSubs = sharedPreferences.getBoolean("write_subtitles", false)
val addChapters = sharedPreferences.getBoolean("add_chapters", false) val addChapters = sharedPreferences.getBoolean("add_chapters", false)
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false) val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false) val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
var type = givenType
if(type == Type.command && commandTemplateDao.getTotalNumber() == 0) type = Type.video
val customFileNameTemplate = when(type) { val customFileNameTemplate = when(type) {
Type.audio -> sharedPreferences.getString("file_name_template_audio", "%(uploader)s - %(title)s") Type.audio -> sharedPreferences.getString("file_name_template_audio", "%(uploader)s - %(title)s")
Type.video -> sharedPreferences.getString("file_name_template", "%(uploader)s - %(title)s") Type.video -> sharedPreferences.getString("file_name_template", "%(uploader)s - %(title)s")
@ -159,6 +160,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath()) else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
} }
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet()) val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
val audioPreferences = AudioPreferences(embedThumb, false, ArrayList(sponsorblock!!)) val audioPreferences = AudioPreferences(embedThumb, false, ArrayList(sponsorblock!!))
@ -272,7 +274,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
val audioPreferences = AudioPreferences(embedThumb, false, ArrayList(sponsorblock!!)) val audioPreferences = AudioPreferences(embedThumb, false, ArrayList(sponsorblock!!))
val videoPreferences = VideoPreferences(embedSubs, addChapters, false, ArrayList(sponsorblock), saveSubs) val videoPreferences = VideoPreferences(embedSubs, addChapters, false, ArrayList(sponsorblock), saveSubs)
return DownloadItem(historyItem.downloadId, return DownloadItem(0,
historyItem.url, historyItem.url,
historyItem.title, historyItem.title,
historyItem.author, historyItem.author,

@ -102,7 +102,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
fragmentView = inflater.inflate(R.layout.fragment_home, container, false) fragmentView = inflater.inflate(R.layout.fragment_home, container, false)
activity = getActivity() activity = getActivity()
mainActivity = activity as MainActivity? mainActivity = activity as MainActivity?
mainActivity?.showBottomNavigation()
quickLaunchSheet = false quickLaunchSheet = false
return fragmentView return fragmentView
} }

@ -26,7 +26,6 @@ import com.yausername.youtubedl_android.YoutubeDL
class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener { class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null private var fragmentView: View? = null
private var activity: Activity? = null private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel private lateinit var downloadViewModel : DownloadViewModel
@ -42,7 +41,6 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
activity = getActivity() activity = getActivity()
notificationUtil = NotificationUtil(requireContext()) notificationUtil = NotificationUtil(requireContext())

@ -43,7 +43,6 @@ import kotlinx.coroutines.runBlocking
class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener { class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null private var fragmentView: View? = null
private var activity: Activity? = null private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel private lateinit var downloadViewModel : DownloadViewModel
@ -58,7 +57,6 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
activity = getActivity() activity = getActivity()
selectedObjects = arrayListOf() selectedObjects = arrayListOf()

@ -18,9 +18,11 @@ import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdlnis.util.NotificationUtil
import com.deniscerri.ytdlnis.work.DownloadWorker
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.google.android.material.tabs.TabLayoutMediator
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -72,6 +74,15 @@ class DownloadQueueMainFragment : Fragment(){
viewPager2.adapter = fragmentAdapter viewPager2.adapter = fragmentAdapter
viewPager2.isSaveFromParentEnabled = false viewPager2.isSaveFromParentEnabled = false
TabLayoutMediator(tabLayout, viewPager2) { tab, position ->
when (position) {
0 -> tab.text = getString(R.string.running)
1 -> tab.text = getString(R.string.in_queue)
2 -> tab.text = getString(R.string.cancelled)
3 -> tab.text = getString(R.string.errored)
}
}.attach()
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) { override fun onTabSelected(tab: TabLayout.Tab?) {
viewPager2.setCurrentItem(tab!!.position, true) viewPager2.setCurrentItem(tab!!.position, true)

@ -46,7 +46,6 @@ import java.io.File
class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener { class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null private var fragmentView: View? = null
private var activity: Activity? = null private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel private lateinit var downloadViewModel : DownloadViewModel
@ -60,7 +59,6 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
activity = getActivity() activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]

@ -98,7 +98,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
fragmentView = inflater.inflate(R.layout.fragment_history, container, false) fragmentView = inflater.inflate(R.layout.fragment_history, container, false)
activity = getActivity() activity = getActivity()
mainActivity = activity as MainActivity? mainActivity = activity as MainActivity?
mainActivity?.showBottomNavigation()
return fragmentView return fragmentView
} }

@ -53,7 +53,6 @@ import java.util.Locale
class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener { class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener {
private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null private var fragmentView: View? = null
private var activity: Activity? = null private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel private lateinit var downloadViewModel : DownloadViewModel
@ -69,7 +68,6 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
activity = getActivity() activity = getActivity()
notificationUtil = NotificationUtil(requireContext()) notificationUtil = NotificationUtil(requireContext())

@ -48,7 +48,6 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
mainActivity = activity as MainActivity mainActivity = activity as MainActivity
mainActivity.hideBottomNavigation()
return inflater.inflate(R.layout.fragment_command_templates, container, false) return inflater.inflate(R.layout.fragment_command_templates, container, false)
} }

@ -54,7 +54,6 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
mainActivity = activity as MainActivity mainActivity = activity as MainActivity
mainActivity.hideBottomNavigation()
return inflater.inflate(R.layout.fragment_cookies, container, false) return inflater.inflate(R.layout.fragment_cookies, container, false)
} }

@ -35,7 +35,6 @@ class MoreFragment : Fragment() {
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
mainActivity = activity as MainActivity mainActivity = activity as MainActivity
mainActivity.showBottomNavigation()
return inflater.inflate(R.layout.fragment_more, container, false) return inflater.inflate(R.layout.fragment_more, container, false)
} }

@ -7,10 +7,12 @@ import android.content.SharedPreferences
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.util.LayoutDirection
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.os.LocaleListCompat import androidx.core.os.LocaleListCompat
import androidx.core.text.layoutDirection
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
@ -47,6 +49,7 @@ import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader import java.io.InputStreamReader
import java.util.Calendar import java.util.Calendar
import java.util.Locale
class MainSettingsFragment : PreferenceFragmentCompat() { class MainSettingsFragment : PreferenceFragmentCompat() {
@ -67,36 +70,38 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey) setPreferencesFromResource(R.xml.root_preferences, rootKey)
val navController = findNavController() val navController = findNavController()
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val appearance = findPreference<Preference>("appearance") val appearance = findPreference<Preference>("appearance")
appearance?.summary = "${if (Build.VERSION.SDK_INT < 33) getString(R.string.language) + ", " else ""}${getString(R.string.Theme)}, ${getString(R.string.accents)}, ${getString(R.string.preferred_search_engine)}" val separator = if (Locale(preferences.getString("app_language", "en")!!).layoutDirection == LayoutDirection.RTL) "،" else ","
appearance?.summary = "${if (Build.VERSION.SDK_INT < 33) getString(R.string.language) + "$separator " else ""}${getString(R.string.Theme)}$separator ${getString(R.string.accents)}$separator ${getString(R.string.preferred_search_engine)}"
appearance?.setOnPreferenceClickListener { appearance?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_appearanceSettingsFragment) navController.navigate(R.id.action_mainSettingsFragment_to_appearanceSettingsFragment)
true true
} }
val folders = findPreference<Preference>("folders") val folders = findPreference<Preference>("folders")
folders?.summary = "${getString(R.string.music_directory)}, ${getString(R.string.video_directory)}, ${getString(R.string.command_directory)}" folders?.summary = "${getString(R.string.music_directory)}$separator ${getString(R.string.video_directory)}$separator ${getString(R.string.command_directory)}"
folders?.setOnPreferenceClickListener { folders?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_folderSettingsFragment) navController.navigate(R.id.action_mainSettingsFragment_to_folderSettingsFragment)
true true
} }
val downloading = findPreference<Preference>("downloading") val downloading = findPreference<Preference>("downloading")
downloading?.summary = "${getString(R.string.quick_download)}, ${getString(R.string.concurrent_downloads)}, ${getString(R.string.limit_rate)}" downloading?.summary = "${getString(R.string.quick_download)}$separator ${getString(R.string.concurrent_downloads)}$separator ${getString(R.string.limit_rate)}"
downloading?.setOnPreferenceClickListener { downloading?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_downloadSettingsFragment) navController.navigate(R.id.action_mainSettingsFragment_to_downloadSettingsFragment)
true true
} }
val processing = findPreference<Preference>("processing") val processing = findPreference<Preference>("processing")
processing?.summary = "${getString(R.string.sponsorblock)}, ${getString(R.string.embed_subtitles)}, ${getString(R.string.add_chapters)}" processing?.summary = "${getString(R.string.sponsorblock)}$separator ${getString(R.string.embed_subtitles)}$separator ${getString(R.string.add_chapters)}"
processing?.setOnPreferenceClickListener { processing?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_processingSettingsFragment) navController.navigate(R.id.action_mainSettingsFragment_to_processingSettingsFragment)
true true
} }
val updating = findPreference<Preference>("updating") val updating = findPreference<Preference>("updating")
updating?.summary = "${getString(R.string.update_ytdl)}, ${getString(R.string.format_source)}, ${getString(R.string.update_app)}" updating?.summary = "${getString(R.string.update_ytdl)}$separator ${getString(R.string.format_source)}$separator ${getString(R.string.update_app)}"
updating?.setOnPreferenceClickListener { updating?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_updateSettingsFragment) navController.navigate(R.id.action_mainSettingsFragment_to_updateSettingsFragment)
true true
@ -118,7 +123,6 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
cookieViewModel = ViewModelProvider(this)[CookieViewModel::class.java] cookieViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java] commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
backup = findPreference("backup") backup = findPreference("backup")
restore = findPreference("restore") restore = findPreference("restore")

@ -8,12 +8,12 @@ import android.os.Environment
import android.provider.DocumentsContract import android.provider.DocumentsContract
import android.util.Log import android.util.Log
import android.webkit.MimeTypeMap import android.webkit.MimeTypeMap
import androidx.core.net.toUri import com.anggrayudi.storage.callback.FileCallback
import com.anggrayudi.storage.file.moveTo
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.DownloadItem
import okhttp3.internal.closeQuietly import okhttp3.internal.closeQuietly
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.net.URLDecoder import java.net.URLDecoder
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.Files import java.nio.file.Files
@ -91,7 +91,7 @@ object FileUtil {
if(it.name.contains(".part-Frag")) return@forEach if(it.name.contains(".part-Frag")) return@forEach
//sending to main or SD CARD //sending to main or SD CARD
if (currentDirectory.exists()){ if (currentDirectory.exists() && Build.VERSION.SDK_INT >= 26){
if (Build.VERSION.SDK_INT >= 26 ){ if (Build.VERSION.SDK_INT >= 26 ){
Files.move(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) Files.move(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}else{ }else{
@ -134,7 +134,7 @@ object FileUtil {
if (Build.VERSION.SDK_INT >= 26 ){ if (Build.VERSION.SDK_INT >= 26 ){
Files.move(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) Files.move(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}else{ }else{
it.renameTo(destFile) it.moveTo(context, destFile.parent!!, destFile.name, FileCallback.ConflictResolution.REPLACE)
} }
fileList.add(destFile) fileList.add(destFile)
} }
@ -170,8 +170,12 @@ object FileUtil {
} }
fun checkLogFileExists(context: Context, item: DownloadItem) : File? { fun checkLogFileExists(context: Context, item: DownloadItem) : File? {
val dir = File(context.filesDir.absolutePath + "/logs/") return try {
return dir.listFiles()?.toList()?.first { it.name.startsWith(item.id.toString()) } val dir = File(context.filesDir.absolutePath + "/logs/")
dir.listFiles()?.toList()?.first { it.name.startsWith(item.id.toString()) }
}catch (e: Exception){
null
}
} }
fun getLogFileForTerminal(context: Context, command: String) : File { fun getLogFileForTerminal(context: Context, command: String) : File {

@ -122,7 +122,7 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class) @Throws(JSONException::class)
fun searchFromPiped(query: String): ArrayList<ResultItem?> { fun searchFromPiped(query: String): ArrayList<ResultItem?> {
val data = genericRequest(pipedURL + "search?q=" + query + "?filter=videos") val data = genericRequest(pipedURL + "/search?q=" + query + "?filter=videos")
val dataArray = data.getJSONArray("items") val dataArray = data.getJSONArray("items")
if (dataArray.length() == 0) return getFromYTDL(query) if (dataArray.length() == 0) return getFromYTDL(query)
for (i in 0 until dataArray.length()) { for (i in 0 until dataArray.length()) {
@ -233,7 +233,7 @@ class InfoUtil(private val context: Context) {
try { try {
init() init()
if (key!!.isEmpty()) { if (key!!.isEmpty()) {
val res = genericRequest(pipedURL + "streams/" + id) val res = genericRequest(pipedURL + "/streams/" + id)
return if (res.length() == 0) getFromYTDL("https://www.youtube.com/watch?v=$id")[0] else createVideoFromPipedJSON( return if (res.length() == 0) getFromYTDL("https://www.youtube.com/watch?v=$id")[0] else createVideoFromPipedJSON(
res, id res, id
) )
@ -544,7 +544,7 @@ class InfoUtil(private val context: Context) {
} }
private fun getTrendingFromPiped(): ArrayList<ResultItem?> { private fun getTrendingFromPiped(): ArrayList<ResultItem?> {
val url = pipedURL + "trending?region=" + countryCODE val url = pipedURL + "/trending?region=" + countryCODE
val res = genericArrayRequest(url) val res = genericArrayRequest(url)
try { try {
for (i in 0 until res.length()) { for (i in 0 until res.length()) {
@ -586,7 +586,7 @@ class InfoUtil(private val context: Context) {
val formatSource = sharedPreferences.getString("formats_source", "yt-dlp") val formatSource = sharedPreferences.getString("formats_source", "yt-dlp")
return if(m.find() && formatSource == "piped"){ return if(m.find() && formatSource == "piped"){
val id = getIDFromYoutubeURL(url) val id = getIDFromYoutubeURL(url)
val res = genericRequest(pipedURL + "streams/" + id) val res = genericRequest(pipedURL + "/streams/" + id)
if (res.length() == 0) getFromYTDL(url)[0]!! if (res.length() == 0) getFromYTDL(url)[0]!!
val item = createVideoFromPipedJSON(res, id) val item = createVideoFromPipedJSON(res, id)
item!!.formats item!!.formats
@ -719,7 +719,7 @@ class InfoUtil(private val context: Context) {
}else{ }else{
urls.forEach { urls.forEach {
val id = getIDFromYoutubeURL(it) val id = getIDFromYoutubeURL(it)
val res = genericRequest(pipedURL + "streams/" + id) val res = genericRequest(pipedURL + "/streams/" + id)
val vid = createVideoFromPipedJSON(res, id) val vid = createVideoFromPipedJSON(res, id)
progress(vid!!.formats) progress(vid!!.formats)
} }
@ -1028,6 +1028,8 @@ class InfoUtil(private val context: Context) {
} }
} }
private val pipedURL = sharedPreferences.getString("piped_instance", defaultPipedURL)?.ifEmpty { defaultPipedURL }?.removeSuffix("/")
class PlaylistTuple internal constructor( class PlaylistTuple internal constructor(
var nextPageToken: String, var nextPageToken: String,
var videos: ArrayList<ResultItem?> var videos: ArrayList<ResultItem?>
@ -1036,7 +1038,7 @@ class InfoUtil(private val context: Context) {
companion object { companion object {
private const val TAG = "API MANAGER" private const val TAG = "API MANAGER"
private const val invidousURL = "https://invidious.baczek.me/api/v1/" private const val invidousURL = "https://invidious.baczek.me/api/v1/"
private const val pipedURL = "https://pipedapi.kavin.rocks/" private const val defaultPipedURL = "https://pipedapi.kavin.rocks/"
private var countryCODE: String = "" private var countryCODE: String = ""
} }
} }

@ -1,8 +1,6 @@
package com.deniscerri.ytdlnis.work package com.deniscerri.ytdlnis.work
import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
@ -14,7 +12,6 @@ import androidx.work.ForegroundInfo
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import androidx.work.workDataOf import androidx.work.workDataOf
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdlnis.database.dao.DownloadDao
@ -61,6 +58,8 @@ class DownloadWorker(
return Result.failure() return Result.failure()
} }
if (downloadItem.status != DownloadRepository.Status.Queued.toString()) return Result.failure()
Log.e(TAG, downloadItem.toString()) Log.e(TAG, downloadItem.toString())
runBlocking{ runBlocking{
@ -208,6 +207,8 @@ class DownloadWorker(
request.addOption("--parse-metadata", "%(album,title)s:%(meta_album)s") request.addOption("--parse-metadata", "%(album,title)s:%(meta_album)s")
} }
request.addOption("--audio-quality", sharedPreferences.getInt("audio_quality", 5))
if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){ if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
request.addOption("--split-chapters") request.addOption("--split-chapters")
request.addOption("-P", tempFileDir.absolutePath) request.addOption("-P", tempFileDir.absolutePath)

@ -1,5 +1,5 @@
<vector android:height="24dp" <vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M14,2H6C4.9,2 4.01,2.9 4.01,4L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8L14,2zM16,13h-3v3.75c0,1.24 -1.01,2.25 -2.25,2.25S8.5,17.99 8.5,16.75c0,-1.24 1.01,-2.25 2.25,-2.25c0.46,0 0.89,0.14 1.25,0.38V11h4V13zM13,9V3.5L18.5,9H13z"/> <path android:fillColor="?android:colorAccent" android:pathData="M14,2H6C4.9,2 4.01,2.9 4.01,4L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8L14,2zM16,13h-3v3.75c0,1.24 -1.01,2.25 -2.25,2.25S8.5,17.99 8.5,16.75c0,-1.24 1.01,-2.25 2.25,-2.25c0.46,0 0.89,0.14 1.25,0.38V11h4V13zM13,9V3.5L18.5,9H13z"/>
</vector> </vector>

@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp" <vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/> <path android:fillColor="?android:colorAccent" android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/>
</vector> </vector>

@ -1,5 +1,5 @@
<vector android:height="24dp" <vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24" android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M14,2H6.01c-1.1,0 -2,0.89 -2,2L4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V8L14,2zM13,9V3.5L18.5,9H13zM14,14l2,-1.06v4.12L14,16v1c0,0.55 -0.45,1 -1,1H9c-0.55,0 -1,-0.45 -1,-1v-4c0,-0.55 0.45,-1 1,-1h4c0.55,0 1,0.45 1,1V14z"/> <path android:fillColor="?android:colorAccent" android:pathData="M14,2H6.01c-1.1,0 -2,0.89 -2,2L4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V8L14,2zM13,9V3.5L18.5,9H13zM14,14l2,-1.06v4.12L14,16v1c0,0.55 -0.45,1 -1,1H9c-0.55,0 -1,-0.45 -1,-1v-4c0,-0.55 0.45,-1 1,-1h4c0.55,0 1,0.45 1,1V14z"/>
</vector> </vector>

@ -47,7 +47,6 @@
android:id="@+id/bottomNavigationView" android:id="@+id/bottomNavigationView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"

@ -22,12 +22,6 @@
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:menu="@menu/download_multiple_menu" /> app:menu="@menu/download_multiple_menu" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:srcCompat="@drawable/ic_edit" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -3,8 +3,7 @@
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" 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">
tools:context="com.deniscerri.ytdlnis.ui.more.TerminalActivity">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -38,30 +37,7 @@
android:layout_margin="10dp" android:layout_margin="10dp"
android:backgroundTint="@android:color/transparent" android:backgroundTint="@android:color/transparent"
app:tabGravity="fill" app:tabGravity="fill"
app:tabMode="scrollable"> app:tabMode="scrollable" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/running" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/in_queue" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/cancelled" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/errored" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/download_viewpager" android:id="@+id/download_viewpager"

@ -1,19 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.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="match_parent" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:fillViewport="true" xmlns:android="http://schemas.android.com/apk/res/android">
android:scrollbars="none">
<androidx.recyclerview.widget.RecyclerView </androidx.recyclerview.widget.RecyclerView>
android:id="@+id/download_recyclerview"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</androidx.core.widget.NestedScrollView>

@ -8,25 +8,25 @@
android:id="@+id/preferred_download_type" android:id="@+id/preferred_download_type"
android:title="@string/preferred_download_type" android:title="@string/preferred_download_type"
android:icon="@drawable/baseline_insert_drive_file_24" android:icon="@drawable/baseline_insert_drive_file_24"
app:showAsAction="ifRoom"/> app:showAsAction="always"/>
<item <item
android:id="@+id/format" android:id="@+id/format"
android:title="@string/format" android:title="@string/format"
android:icon="@drawable/baseline_high_quality_24" android:icon="@drawable/ic_format"
app:showAsAction="ifRoom"/> app:showAsAction="always"/>
<item <item
android:id="@+id/filename_template" android:id="@+id/filename_template"
android:title="@string/file_name_template" android:title="@string/file_name_template"
android:icon="@drawable/if_file_rename" android:icon="@drawable/if_file_rename"
app:showAsAction="collapseActionView|ifRoom"/> app:showAsAction="always"/>
<item <item
android:id="@+id/folder" android:id="@+id/folder"
android:title="@string/directories" android:title="@string/directories"
android:icon="@drawable/ic_folders" android:icon="@drawable/baseline_folder_24"
app:showAsAction="ifRoom"/> app:showAsAction="always"/>
</menu> </menu>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:label="@string/more"
app:startDestination="@id/activeDownloadsFragment">
<fragment
android:id="@+id/activeDownloadsFragment"
android:name="com.deniscerri.ytdlnis.ui.downloads.ActiveDownloadsFragment"
android:label="ActiveDownloadsFragment" />
<fragment
android:id="@+id/queuedDownloadsFragment"
android:name="com.deniscerri.ytdlnis.ui.downloads.QueuedDownloadsFragment"
android:label="QueuedDownloadsFragment" />
<fragment
android:id="@+id/cancelledDownloadsFragment"
android:name="com.deniscerri.ytdlnis.ui.downloads.CancelledDownloadsFragment"
android:label="CancelledDownloadsFragment" />
<fragment
android:id="@+id/erroredDownloadsFragment"
android:name="com.deniscerri.ytdlnis.ui.downloads.ErroredDownloadsFragment"
android:label="ErroredDownloadsFragment" />
</navigation>

@ -93,6 +93,7 @@
<item>ar</item> <item>ar</item>
<item>az</item> <item>az</item>
<item>bn</item> <item>bn</item>
<item>bs</item>
<item>de</item> <item>de</item>
<item>es</item> <item>es</item>
<item>fa</item> <item>fa</item>
@ -173,12 +174,14 @@
<array name="start_destination"> <array name="start_destination">
<item>@string/home</item> <item>@string/home</item>
<item>@string/downloads</item> <item>@string/downloads</item>
<item>@string/download_queue</item>
<item>@string/more</item> <item>@string/more</item>
</array> </array>
<array name="start_destination_values"> <array name="start_destination_values">
<item>Home</item> <item>Home</item>
<item>History</item> <item>History</item>
<item>Queue</item>
<item>More</item> <item>More</item>
</array> </array>

@ -276,4 +276,6 @@
<string name="move_temporary_files">Move Temporary Files</string> <string name="move_temporary_files">Move Temporary Files</string>
<string name="move_temporary_files_summary">Transfer cached files to the downloads folder</string> <string name="move_temporary_files_summary">Transfer cached files to the downloads folder</string>
<string name="format_filtering_hint_2">All items must either be audio or video to use this option</string> <string name="format_filtering_hint_2">All items must either be audio or video to use this option</string>
<string name="piped_instance">Piped Instance</string>
<string name="piped_instance_summary">Write a PIPED API Server, the app can use for youtube queries and formats</string>
</resources> </resources>

@ -4,6 +4,7 @@
<locale android:name="ar"/> <locale android:name="ar"/>
<locale android:name="az"/> <locale android:name="az"/>
<locale android:name="bn"/> <locale android:name="bn"/>
<locale android:name="bs"/>
<locale android:name="de"/> <locale android:name="de"/>
<locale android:name="es"/> <locale android:name="es"/>
<locale android:name="fa-IR"/> <locale android:name="fa-IR"/>

@ -38,6 +38,12 @@
app:useSimpleSummaryProvider="true" app:useSimpleSummaryProvider="true"
app:title="@string/format_source" /> app:title="@string/format_source" />
<EditTextPreference
app:key="piped_instance"
app:defaultValue="https://pipedapi.kavin.rocks"
android:summary="@string/piped_instance_summary"
app:title="@string/piped_instance" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch" android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="true" app:defaultValue="true"

@ -6,11 +6,12 @@ buildscript {
def versionMajor = 1 def versionMajor = 1
def versionMinor = 6 def versionMinor = 6
def versionPatch = 2 def versionPatch = 2
def versionBuild = 0 // bump for dogfood builds, public betas, etc. def versionBuild = 1 // bump for dogfood builds, public betas, etc.
ext { ext {
versionCode = versionMajor * 100000 + versionMinor * 1000 + versionPatch * 100 + versionBuild versionCode = versionMajor * 100000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
versionName = "${versionMajor}.${versionMinor}.${versionPatch}" versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
betaVersionNameSuffix = ".${versionBuild}-beta"
// dependency versions // dependency versions
appCompatVer = '1.6.1' appCompatVer = '1.6.1'
junitVer = '4.13.2' junitVer = '4.13.2'

Loading…
Cancel
Save