added navigation component & command chip in history fragment

This commit is contained in:
deniscerri 2023-03-25 11:13:18 +01:00
parent 1eca31ab5d
commit 660cab7702
No known key found for this signature in database
GPG key ID: 95C43D517D830350
19 changed files with 285 additions and 178 deletions

View file

@ -125,8 +125,9 @@ dependencies {
implementation 'androidx.core:core:1.9.0' implementation 'androidx.core:core:1.9.0'
implementation 'androidx.recyclerview:recyclerview:1.3.0' implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'androidx.preference:preference:1.2.0' implementation 'androidx.preference:preference:1.2.0'
implementation "androidx.navigation:navigation-fragment-ktx:2.5.3" implementation "androidx.navigation:navigation-fragment-ktx:$navVer"
implementation "androidx.navigation:navigation-ui-ktx:2.5.3" implementation "androidx.navigation:navigation-ui-ktx:$navVer"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$navVer"
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.test.ext:junit-ktx:1.1.5' implementation 'androidx.test.ext:junit-ktx:1.1.5'
@ -139,6 +140,7 @@ dependencies {
androidTestImplementation "androidx.test:runner:1.5.2" androidTestImplementation "androidx.test:runner:1.5.2"
androidTestImplementation "androidx.test:core:1.5.0" androidTestImplementation "androidx.test:core:1.5.0"
androidTestImplementation "androidx.test:rules:1.5.0" androidTestImplementation "androidx.test:rules:1.5.0"
androidTestImplementation "androidx.navigation:navigation-testing:$navVer"
implementation "io.reactivex.rxjava2:rxandroid:2.1.0" implementation "io.reactivex.rxjava2:rxandroid:2.1.0"
implementation "com.devbrackets.android:exomedia:4.3.0" implementation "com.devbrackets.android:exomedia:4.3.0"

View file

@ -25,6 +25,12 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
import com.deniscerri.ytdlnis.ui.HomeFragment import com.deniscerri.ytdlnis.ui.HomeFragment
@ -33,6 +39,8 @@ import com.deniscerri.ytdlnis.ui.downloads.HistoryFragment
import com.deniscerri.ytdlnis.ui.more.MoreFragment import com.deniscerri.ytdlnis.ui.more.MoreFragment
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
import com.deniscerri.ytdlnis.util.UpdateUtil import com.deniscerri.ytdlnis.util.UpdateUtil
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -48,20 +56,17 @@ import kotlin.system.exitProcess
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
lateinit var context: Context lateinit var context: Context
private lateinit var homeFragment: HomeFragment
private lateinit var historyFragment: HistoryFragment
private lateinit var preferences: SharedPreferences private lateinit var preferences: SharedPreferences
private lateinit var resultViewModel: ResultViewModel private lateinit var resultViewModel: ResultViewModel
private lateinit var bottomNav: BottomNavigationView
private lateinit var navHostFragment : NavHostFragment
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setContentView(binding.root)
context = baseContext context = baseContext
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
preferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE) preferences = context.getSharedPreferences("root_preferences", MODE_PRIVATE)
@ -72,56 +77,50 @@ class MainActivity : AppCompatActivity() {
askPermissions() askPermissions()
checkUpdate() checkUpdate()
fm = supportFragmentManager
homeFragment = HomeFragment() navHostFragment = supportFragmentManager.findFragmentById(R.id.frame_layout) as NavHostFragment
historyFragment = HistoryFragment() val navController = navHostFragment.findNavController()
moreFragment = MoreFragment() bottomNav = findViewById(R.id.bottomNavigationView)
initFragments()
binding.bottomNavigationView.setOnItemSelectedListener { item: MenuItem ->
when (item.itemId) {
R.id.home -> {
if (lastFragment === homeFragment) {
homeFragment.scrollToTop()
} else {
this.setTitle(R.string.app_name)
}
replaceFragment(homeFragment)
}
R.id.history -> {
if (lastFragment === historyFragment) {
val intent = Intent(context, DownloadQueueActivity::class.java)
startActivity(intent)
} else {
this.title = getString(R.string.downloads)
}
replaceFragment(historyFragment)
}
R.id.more -> {
if (lastFragment === moreFragment) {
val intent = Intent(context, SettingsActivity::class.java)
startActivity(intent)
} else {
this.title = getString(R.string.more)
}
replaceFragment(moreFragment)
}
}
true
}
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())
binding.bottomNavigationView.visibility = bottomNav.visibility =
if (isImeVisible) View.GONE else View.VISIBLE if (isImeVisible) View.GONE else View.VISIBLE
view.onApplyWindowInsets(windowInsets) view.onApplyWindowInsets(windowInsets)
} }
bottomNav.setupWithNavController(navController)
bottomNav.setOnItemReselectedListener {
when (it.itemId) {
R.id.homeFragment -> {
(navHostFragment.childFragmentManager.primaryNavigationFragment!! as HomeFragment).scrollToTop()
}
R.id.historyFragment -> {
val intent = Intent(context, DownloadQueueActivity::class.java)
startActivity(intent)
}
R.id.moreFragment -> {
val intent = Intent(context, SettingsActivity::class.java)
startActivity(intent)
}
}
}
val intent = intent val intent = intent
handleIntents(intent) handleIntents(intent)
} }
fun hideNav() {
bottomNav.visibility = View.GONE
}
fun showNav() {
bottomNav.visibility = View.VISIBLE
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
val incognitoHeader = findViewById<TextView>(R.id.incognito_header) val incognitoHeader = findViewById<TextView>(R.id.incognito_header)
@ -144,9 +143,6 @@ class MainActivity : AppCompatActivity() {
val type = intent.type val type = intent.type
if (Intent.ACTION_SEND == action && type != null) { if (Intent.ACTION_SEND == action && type != null) {
Log.e(TAG, action) Log.e(TAG, action)
homeFragment = HomeFragment()
historyFragment = HistoryFragment()
moreFragment = MoreFragment()
if (type.equals("application/txt", ignoreCase = true)) { if (type.equals("application/txt", ignoreCase = true)) {
try { try {
val uri = if (Build.VERSION.SDK_INT >= 33){ val uri = if (Build.VERSION.SDK_INT >= 33){
@ -169,33 +165,16 @@ class MainActivity : AppCompatActivity() {
} }
val l = listOf(*textBuilder.toString().split("\n").toTypedArray()) val l = listOf(*textBuilder.toString().split("\n").toTypedArray())
val lines = LinkedList(l) val lines = LinkedList(l)
homeFragment.handleFileIntent(lines) (navHostFragment.childFragmentManager.primaryNavigationFragment!! as HomeFragment).handleFileIntent(lines)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
} else { } else {
homeFragment.handleIntent(intent) (navHostFragment.childFragmentManager.primaryNavigationFragment!! as HomeFragment).handleIntent(intent)
} }
initFragments()
} }
} }
private fun initFragments() {
fm.beginTransaction()
.replace(R.id.frame_layout, homeFragment)
.add(R.id.frame_layout, historyFragment)
.add(R.id.frame_layout, moreFragment)
.hide(historyFragment)
.hide(moreFragment)
.commit()
lastFragment = homeFragment
}
private fun replaceFragment(f: Fragment) {
fm.beginTransaction().hide(lastFragment).show(f).commit()
lastFragment = f
}
private fun checkUpdate() { private fun checkUpdate() {
if (preferences.getBoolean("update_app", false)) { if (preferences.getBoolean("update_app", false)) {
@ -301,8 +280,5 @@ class MainActivity : AppCompatActivity() {
companion object { companion object {
private const val TAG = "MainActivity" private const val TAG = "MainActivity"
private lateinit var moreFragment: MoreFragment
private lateinit var lastFragment: Fragment
private lateinit var fm: FragmentManager
} }
} }

View file

@ -37,7 +37,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
suspend fun setDownloadStatus(item: DownloadItem, status: Status){ suspend fun setDownloadStatus(item: DownloadItem, status: Status){
item.status = status.toString() item.status = status.toString()
update(item); update(item)
} }
fun getItemByID(id: Long) : DownloadItem { fun getItemByID(id: Long) : DownloadItem {
@ -56,14 +56,6 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
downloadDao.deleteQueued() downloadDao.deleteQueued()
} }
suspend fun deleteSingleProcessing(item: DownloadItem){
downloadDao.deleteSingleProcessing(item.id)
}
suspend fun queueAllProcessing(){
downloadDao.queueAllProcessing()
}
fun checkIfPresentForProcessing(item: ResultItem): DownloadItem{ fun checkIfPresentForProcessing(item: ResultItem): DownloadItem{
return downloadDao.checkIfErrorOrCancelled(item.url) return downloadDao.checkIfErrorOrCancelled(item.url)
} }

View file

@ -63,7 +63,4 @@ class HistoryRepository(private val historyDao: HistoryDao) {
} }
} }
suspend fun checkDownloaded(){
}
} }

View file

@ -109,7 +109,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
} }
fun update(item: ResultItem) = viewModelScope.launch(Dispatchers.IO){ fun update(item: ResultItem) = viewModelScope.launch(Dispatchers.IO){
repository.update(item); repository.update(item)
} }
fun getItemByURL(url: String) : ResultItem { fun getItemByURL(url: String) : ResultItem {

View file

@ -12,6 +12,7 @@ import android.util.Log
import android.view.* import android.view.*
import android.widget.Button import android.widget.Button
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
@ -32,11 +33,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.DateValidatorPointForward
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -149,9 +145,9 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
bottomSheet.setContentView(R.layout.download_type_sheet) bottomSheet.setContentView(R.layout.download_type_sheet)
// BUTTON ---------------------------------- // BUTTON ----------------------------------
val audio = bottomSheet.findViewById<LinearLayout>(R.id.audio) val audio = bottomSheet.findViewById<TextView>(R.id.audio)
val video = bottomSheet.findViewById<LinearLayout>(R.id.video) val video = bottomSheet.findViewById<TextView>(R.id.video)
val command = bottomSheet.findViewById<LinearLayout>(R.id.command) val command = bottomSheet.findViewById<TextView>(R.id.command)
withContext(Dispatchers.IO){ withContext(Dispatchers.IO){

View file

@ -12,12 +12,10 @@ import android.view.Window
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener import android.widget.AdapterView.OnItemClickListener
import android.widget.Button import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -33,12 +31,11 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.io.File import java.io.File
class ErroredDownloadsFragment() : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener { class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener {
private var _binding : FragmentHomeBinding? = null 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
@ -195,7 +192,7 @@ class ErroredDownloadsFragment() : Fragment(), GenericDownloadAdapter.OnItemClic
private fun removeItem(item: DownloadItem, bottomSheet: BottomSheetDialog?){ private fun removeItem(item: DownloadItem, bottomSheet: BottomSheetDialog?){
bottomSheet?.hide() bottomSheet?.hide()
val deleteDialog = MaterialAlertDialogBuilder(requireContext()!!) val deleteDialog = MaterialAlertDialogBuilder(requireContext())
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + item.title + "\"!") deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + item.title + "\"!")
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() } deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int -> deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->

View file

@ -3,22 +3,20 @@ package com.deniscerri.ytdlnis.ui.downloads
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Bundle 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.text.format.DateUtils
import android.util.Log import android.util.Log
import android.view.* import android.view.*
import android.view.View.* import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.* import android.widget.*
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -42,13 +40,10 @@ import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.io.File import java.io.File
import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlin.collections.ArrayList
/** /**
* A fragment representing a list of Items. * A fragment representing a list of Items.
@ -130,7 +125,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
recyclerView?.adapter = historyAdapter recyclerView?.adapter = historyAdapter
noResults?.visibility = GONE noResults?.visibility = GONE
selectionChips?.visibility = VISIBLE
shimmerCards?.visibility = GONE shimmerCards?.visibility = GONE
@ -325,6 +319,16 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
video.isChecked = false video.isChecked = false
} }
} }
val command = fragmentView!!.findViewById<Chip>(R.id.command_chip)
command.setOnClickListener {
if (command.isChecked) {
historyViewModel.setFormatFilter("command")
command.isChecked = true
} else {
historyViewModel.setFormatFilter("")
command.isChecked = false
}
}
} }
private fun updateWebsiteChips(list : List<HistoryItem>) { private fun updateWebsiteChips(list : List<HistoryItem>) {
@ -419,7 +423,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
} }
if (isPresent){ if (isPresent){
btn!!.setOnClickListener { btn.setOnClickListener {
uiUtil!!.shareFileIntent(requireContext(),item.downloadPath) uiUtil!!.shareFileIntent(requireContext(),item.downloadPath)
} }
} }
@ -439,7 +443,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
else formatNote!!.text = item.format.format_note else formatNote!!.text = item.format.format_note
if (item.format.container != "") container!!.text = item.format.container.uppercase() if (item.format.container != "") container!!.text = item.format.container.uppercase()
else container!!.visibility = View.GONE else container!!.visibility = GONE
val codecText = val codecText =
if (item.format.encoding != "") { if (item.format.encoding != "") {

View file

@ -1,17 +1,78 @@
package com.deniscerri.ytdlnis.ui.more package com.deniscerri.ytdlnis.ui.more
import android.app.Activity import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogListActivity
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
class MoreFragment : PreferenceFragmentCompat() { class MoreFragment : Fragment() {
private lateinit var mainSharedPreferences: SharedPreferences private lateinit var mainSharedPreferences: SharedPreferences
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { private lateinit var terminal: TextView
setPreferencesFromResource(R.xml.more_preferences, rootKey) private lateinit var logs: TextView
private lateinit var commandTemplates: TextView
private lateinit var downloadQueue: TextView
private lateinit var settings: TextView
private lateinit var mainActivity: MainActivity
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
mainActivity = activity as MainActivity
return inflater.inflate(R.layout.fragment_more, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainSharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) mainSharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
terminal = view.findViewById(R.id.terminal)
logs = view.findViewById(R.id.logs)
commandTemplates = view.findViewById(R.id.command_templates)
downloadQueue = view.findViewById(R.id.download_queue)
settings = view.findViewById(R.id.settings)
val navHostFragment = parentFragmentManager.findFragmentById(R.id.frame_layout)
terminal.setOnClickListener {
val intent = Intent(context, TerminalActivity::class.java)
startActivity(intent)
}
logs.setOnClickListener {
val intent = Intent(context, DownloadLogListActivity::class.java)
startActivity(intent)
}
commandTemplates.setOnClickListener {
val intent = Intent(context, CommandTemplatesActivity::class.java)
startActivity(intent)
}
downloadQueue.setOnClickListener {
val intent = Intent(context, DownloadQueueActivity::class.java)
startActivity(intent)
}
settings.setOnClickListener {
val intent = Intent(context, SettingsActivity::class.java)
startActivity(intent)
}
} }
companion object { companion object {
@ -20,7 +81,11 @@ class MoreFragment : PreferenceFragmentCompat() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
findPreference<Preference>("download_logs")!!.isVisible = if (mainSharedPreferences.getBoolean("log_downloads", false)) {
mainSharedPreferences.getBoolean("log_downloads", false) logs.visibility = View.VISIBLE
}else {
logs.visibility = View.GONE
}
} }
} }

View file

@ -58,7 +58,7 @@ class TerminalActivity : AppCompatActivity() {
fab = findViewById(R.id.command_fab) fab = findViewById(R.id.command_fab)
fab!!.setOnClickListener { fab!!.setOnClickListener {
input!!.visibility = View.GONE input!!.visibility = View.GONE
output!!.text = "${output!!.text}\n~ $ ${input!!.text}\n"; output!!.text = "${output!!.text}\n~ $ ${input!!.text}\n"
swapFabs() swapFabs()
startDownload( startDownload(
input!!.text.toString() input!!.text.toString()

View file

@ -16,10 +16,7 @@ import com.deniscerri.ytdlnis.R
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDL.UpdateStatus import com.yausername.youtubedl_android.YoutubeDL.UpdateStatus
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.json.JSONException import org.json.JSONException
@ -28,12 +25,10 @@ import java.io.BufferedReader
import java.io.InputStreamReader import java.io.InputStreamReader
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import java.util.concurrent.atomic.AtomicReference
class UpdateUtil(var context: Context) { class UpdateUtil(var context: Context) {
private val tag = "UpdateUtil" private val tag = "UpdateUtil"
private val downloadManager: DownloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager private val downloadManager: DownloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
private val compositeDisposable = CompositeDisposable()
private val ytdlpNightly = "https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest" private val ytdlpNightly = "https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest"
fun updateApp(): Boolean { fun updateApp(): Boolean {

View file

@ -20,14 +20,18 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<FrameLayout <androidx.fragment.app.FragmentContainerView
android:id="@+id/frame_layout" android:id="@+id/frame_layout"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView" app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/incognito_header" /> app:layout_constraintTop_toBottomOf="@+id/incognito_header"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView" android:id="@+id/bottomNavigationView"

View file

@ -21,70 +21,46 @@
android:paddingBottom="20dp" android:paddingBottom="20dp"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
<LinearLayout <TextView
android:id="@+id/audio" android:id="@+id/audio"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:paddingVertical="10dp"
android:drawablePadding="30dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="20dp" android:textSize="15sp"
android:orientation="horizontal"> android:text="@string/audio"
app:drawableLeftCompat="@drawable/ic_music" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:paddingEnd="20dp"
android:src="@drawable/ic_music"/>
<TextView <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@string/audio" />
</LinearLayout>
<LinearLayout
android:id="@+id/video" android:id="@+id/video"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:paddingVertical="10dp"
android:drawablePadding="30dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="20dp" android:textSize="15sp"
android:orientation="horizontal"> android:text="@string/video"
app:drawableLeftCompat="@drawable/ic_video" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:paddingEnd="20dp"
android:src="@drawable/ic_video"/>
<TextView <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@string/video" />
</LinearLayout>
<LinearLayout
android:id="@+id/command" android:id="@+id/command"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:paddingVertical="10dp"
android:drawablePadding="30dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="20dp" android:textSize="15sp"
android:orientation="horizontal"> android:text="@string/command"
app:drawableLeftCompat="@drawable/ic_terminal" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:paddingEnd="20dp"
android:src="@drawable/ic_terminal"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:text="@string/command" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/historycoordinator" android:id="@+id/historycoordinator"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
@ -41,6 +41,7 @@
<LinearLayout <LinearLayout
android:id="@+id/history_selection_chips" android:id="@+id/history_selection_chips"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
@ -54,7 +55,6 @@
style="@style/Widget.Material3.Chip.Assist" style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="sortBy"
android:text="@string/sort_by" android:text="@string/sort_by"
app:chipIcon="@drawable/ic_down" /> app:chipIcon="@drawable/ic_down" />
@ -83,6 +83,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/video"/> android:text="@string/video"/>
<com.google.android.material.chip.Chip
android:id="@+id/command_chip"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/command"/>
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
<View style="@style/Divider.Vertical"/> <View style="@style/Divider.Vertical"/>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/history_no_results" android:id="@+id/history_no_results"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -8,7 +8,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="wrap_content"
android:gravity="top" android:gravity="top"
android:orientation="vertical" android:orientation="vertical"
tools:ignore="MissingConstraints"> tools:ignore="MissingConstraints">
@ -19,6 +19,70 @@
android:layout_gravity="center" android:layout_gravity="center"
android:background="@drawable/ic_app_icon" android:background="@drawable/ic_app_icon"
android:scaleType="center" /> android:scaleType="center" />
<TextView
android:id="@+id/terminal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/terminal"
android:textStyle="bold"
android:paddingHorizontal="15dp"
android:paddingVertical="15dp"
android:drawablePadding="35dp"
android:textSize="16sp"
app:drawableLeftCompat="@drawable/ic_terminal" />
<TextView
android:id="@+id/logs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/logs"
android:textStyle="bold"
android:paddingHorizontal="15dp"
android:paddingVertical="15dp"
android:drawablePadding="35dp"
android:textSize="16sp"
app:drawableLeftCompat="@drawable/ic_baseline_file_open_24" />
<TextView
android:id="@+id/command_templates"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="35dp"
android:textSize="16sp"
android:paddingVertical="15dp"
android:text="@string/command_templates"
android:textStyle="bold"
android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_baseline_keyboard_arrow_right_24" />
<TextView
android:id="@+id/download_queue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="35dp"
android:textSize="16sp"
android:paddingVertical="15dp"
android:text="@string/download_queue"
android:textStyle="bold"
android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_concurrent_downloads" />
<View style="@style/Divider.Horizontal" />
<TextView
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="35dp"
android:textSize="16sp"
android:paddingVertical="15dp"
android:text="@string/settings"
android:textStyle="bold"
android:paddingHorizontal="15dp"
app:drawableLeftCompat="@drawable/ic_settings" />
</LinearLayout> </LinearLayout>

View file

@ -3,11 +3,11 @@
<item android:title="@string/home" <item android:title="@string/home"
android:icon="@drawable/ic_home" android:icon="@drawable/ic_home"
android:id="@+id/home"/> android:id="@+id/homeFragment"/>
<item android:title="@string/downloads" <item android:title="@string/downloads"
android:icon="@drawable/ic_downloads" android:icon="@drawable/ic_downloads"
android:id="@+id/history"/> android:id="@+id/historyFragment"/>
<item android:title="@string/more" <item android:title="@string/more"
android:icon="@drawable/ic_more" android:icon="@drawable/ic_more"
android:id="@+id/more"/> android:id="@+id/moreFragment"/>
</menu> </menu>

View file

@ -0,0 +1,32 @@
<?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:id="@+id/nav_graph"
android:label="@string/more"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.deniscerri.ytdlnis.ui.HomeFragment"
android:label="@string/app_name"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/historyFragment"
android:name="com.deniscerri.ytdlnis.ui.downloads.HistoryFragment"
android:label="@string/downloads"
tools:layout="@layout/fragment_history" />
<fragment
android:id="@+id/moreFragment"
android:name="com.deniscerri.ytdlnis.ui.more.MoreFragment"
android:label="More"
tools:layout="@layout/fragment_more" >
<action
android:id="@+id/action_moreFragment_to_settingsFragment"
app:destination="@id/settingsFragment" />
</fragment>
<fragment
android:id="@+id/settingsFragment"
android:name="com.deniscerri.ytdlnis.ui.more.settings.SettingsFragment"
android:label="SettingsFragment" />
</navigation>

View file

@ -1,6 +1,5 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<ListPreference <ListPreference
android:entries="@array/language_values" android:entries="@array/language_values"
android:entryValues="@array/language_values" android:entryValues="@array/language_values"

View file

@ -28,6 +28,7 @@ buildscript {
coroutineVer = "1.6.4" coroutineVer = "1.6.4"
retrofitVer = "2.9.0" retrofitVer = "2.9.0"
kodeinVer = "7.16.0" kodeinVer = "7.16.0"
navVer = "2.5.3"
} }
repositories { repositories {
mavenCentral() mavenCentral()