alot of stuff
This commit is contained in:
parent
e849b21e9b
commit
9a615777ad
19 changed files with 115 additions and 53 deletions
|
|
@ -156,7 +156,7 @@ class MainActivity : BaseActivity() {
|
|||
navController.navigate(R.id.downloadQueueMainFragment)
|
||||
}else{
|
||||
kotlin.runCatching {
|
||||
(navHostFragment.childFragmentManager.primaryNavigationFragment!! as HistoryFragment).scrollToTop()
|
||||
(navHostFragment.childFragmentManager.primaryNavigationFragment!! as HistoryFragment).openSearchView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ interface LogDao {
|
|||
fun getAllLogsFlow() : Flow<List<LogItem>>
|
||||
|
||||
@Query("SELECT * FROM logs WHERE id=:id LIMIT 1")
|
||||
fun getLogFlowByID(id: Long) : Flow<LogItem>
|
||||
fun getLogFlowByID(id: Long) : Flow<LogItem?>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(item: LogItem) : Long
|
||||
|
|
@ -56,5 +56,5 @@ interface LogDao {
|
|||
suspend fun update(item: LogItem)
|
||||
|
||||
@Query("SELECT * FROM logs WHERE id=:id LIMIT 1")
|
||||
fun getByID(id: Long) : LogItem
|
||||
fun getByID(id: Long) : LogItem?
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ class LogRepository(private val logDao: LogDao) {
|
|||
return logDao.getAllLogs()
|
||||
}
|
||||
|
||||
fun getLogFlowByID(id: Long) : Flow<LogItem> {
|
||||
fun getLogFlowByID(id: Long) : Flow<LogItem?> {
|
||||
return logDao.getLogFlowByID(id)
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ class LogRepository(private val logDao: LogDao) {
|
|||
logDao.deleteAll()
|
||||
}
|
||||
|
||||
fun getItem(id: Long) : LogItem{
|
||||
fun getItem(id: Long) : LogItem? {
|
||||
return logDao.getByID(id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,9 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
val saveSubs = sharedPreferences.getBoolean("write_subtitles", false)
|
||||
val saveAutoSubs = sharedPreferences.getBoolean("write_auto_subtitles", false)
|
||||
val recodeVideo = sharedPreferences.getBoolean("recode_video", false)
|
||||
val compatibilityMode = sharedPreferences.getBoolean("compatible_video", false)
|
||||
val removeAudio = sharedPreferences.getBoolean("remove_audio", false)
|
||||
val alsoDownloadAudio = sharedPreferences.getBoolean("also_download_audio", false)
|
||||
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||
|
|
@ -309,7 +312,10 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
subsLanguages,
|
||||
audioFormatIDs = preferredAudioFormats,
|
||||
recodeVideo = recodeVideo,
|
||||
embedThumbnail = videoEmbedThumb
|
||||
compatibilityMode = compatibilityMode,
|
||||
embedThumbnail = videoEmbedThumb,
|
||||
removeAudio = removeAudio,
|
||||
alsoDownloadAsAudio = alsoDownloadAudio
|
||||
)
|
||||
|
||||
val extraCommands = when(type){
|
||||
|
|
@ -448,6 +454,9 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
val saveSubs = sharedPreferences.getBoolean("write_subtitles", false)
|
||||
val saveAutoSubs = sharedPreferences.getBoolean("write_auto_subtitles", false)
|
||||
val recodeVideo = sharedPreferences.getBoolean("recode_video", false)
|
||||
val removeAudio = sharedPreferences.getBoolean("remove_audio", false)
|
||||
val compatibilityMode = sharedPreferences.getBoolean("compatible_video", false)
|
||||
val alsoDownloadAudio = sharedPreferences.getBoolean("also_download_audio", false)
|
||||
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||
|
|
@ -486,8 +495,25 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
|||
}
|
||||
}.joinToString(" ") { it.content }
|
||||
|
||||
val audioPreferences = AudioPreferences(embedThumb, cropThumb,false, ArrayList(sponsorblock!!), audioBitrate!!)
|
||||
val videoPreferences = VideoPreferences(embedSubs, addChapters, false, ArrayList(sponsorblock), saveSubs, saveAutoSubs, subsLanguages, recodeVideo = recodeVideo)
|
||||
val audioPreferences = AudioPreferences(
|
||||
embedThumb = embedThumb,
|
||||
cropThumb = cropThumb,
|
||||
splitByChapters = false,
|
||||
sponsorBlockFilters = ArrayList(sponsorblock!!),
|
||||
bitrate = audioBitrate!!
|
||||
)
|
||||
val videoPreferences = VideoPreferences(
|
||||
embedSubs = embedSubs,
|
||||
addChapters = addChapters,
|
||||
splitByChapters = false,
|
||||
sponsorBlockFilters = ArrayList(sponsorblock),
|
||||
writeSubs = saveSubs,
|
||||
writeAutoSubs = saveAutoSubs,
|
||||
subsLanguages = subsLanguages,
|
||||
recodeVideo = recodeVideo,
|
||||
compatibilityMode = compatibilityMode,
|
||||
removeAudio = removeAudio,
|
||||
alsoDownloadAsAudio = alsoDownloadAudio)
|
||||
var path = defaultPath
|
||||
historyItem.downloadPath.first().apply {
|
||||
File(this).parent?.apply {
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ class LogViewModel(private val application: Application) : AndroidViewModel(appl
|
|||
}
|
||||
|
||||
|
||||
fun getLogFlowByID(id: Long) : LiveData<LogItem> {
|
||||
fun getLogFlowByID(id: Long) : LiveData<LogItem?> {
|
||||
return repository.getLogFlowByID(id).asLiveData()
|
||||
}
|
||||
|
||||
fun getItemById(id: Long): LogItem{
|
||||
fun getItemById(id: Long): LogItem? {
|
||||
return repository.getItem(id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,10 +218,17 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
|
|||
}
|
||||
}
|
||||
|
||||
fun openSearchView() {
|
||||
topAppBar.menu.performIdentifierAction(R.id.search_history, 0)
|
||||
}
|
||||
|
||||
private fun initMenu() {
|
||||
val searchView = topAppBar.menu.findItem(R.id.search_history).actionView as SearchView?
|
||||
|
||||
val onActionExpandListener: MenuItem.OnActionExpandListener =
|
||||
object : MenuItem.OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(menuItem: MenuItem): Boolean {
|
||||
searchView?.requestFocus()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +238,7 @@ class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
|
|||
}
|
||||
topAppBar.menu.findItem(R.id.search_history)
|
||||
.setOnActionExpandListener(onActionExpandListener)
|
||||
val searchView = topAppBar.menu.findItem(R.id.search_history).actionView as SearchView?
|
||||
|
||||
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
||||
searchView.queryHint = getString(R.string.search_history_hint)
|
||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
|||
}
|
||||
|
||||
private fun initMenu() {
|
||||
topAppBar.menu.getItem(1).isChecked = preferences.getBoolean("use_header", false)
|
||||
topAppBar.setOnMenuItemClickListener { m: MenuItem ->
|
||||
when (m.itemId) {
|
||||
R.id.delete_cookies -> {
|
||||
|
|
@ -143,10 +142,6 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
|||
}
|
||||
deleteDialog.show()
|
||||
}
|
||||
R.id.use_header -> {
|
||||
m.isChecked = !m.isChecked
|
||||
preferences.edit().putBoolean("use_header", m.isChecked).apply()
|
||||
}
|
||||
R.id.import_clipboard -> {
|
||||
lifecycleScope.launch(Dispatchers.IO){
|
||||
cookiesViewModel.importFromClipboard()
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class DownloadLogFragment : Fragment() {
|
|||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
runCatching {
|
||||
val logItem = logViewModel.getItemById(logID!!)
|
||||
val logItem = logViewModel.getItemById(logID!!) ?: throw Exception()
|
||||
withContext(Dispatchers.Main){
|
||||
topAppBar.title = logItem.title
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,16 +236,19 @@ class DownloadLogListFragment : Fragment(), DownloadLogsAdapter.OnItemClickListe
|
|||
when (direction) {
|
||||
ItemTouchHelper.LEFT -> {
|
||||
lifecycleScope.launch {
|
||||
val deletedItem = withContext(Dispatchers.IO){
|
||||
val toDelete = withContext(Dispatchers.IO){
|
||||
logViewModel.getItemById(items[position].id)
|
||||
}
|
||||
logViewModel.delete(deletedItem)
|
||||
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
lifecycleScope.launch(Dispatchers.IO){
|
||||
logViewModel.insert(deletedItem)
|
||||
}
|
||||
}.show()
|
||||
|
||||
toDelete?.apply {
|
||||
logViewModel.delete(this)
|
||||
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + this.title, Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(getString(R.string.undo)) {
|
||||
lifecycleScope.launch(Dispatchers.IO){
|
||||
logViewModel.insert(this@apply)
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ class GenerateYoutubePoTokensFragment : Fragment() {
|
|||
regenerateBtn.isEnabled = false
|
||||
|
||||
editText.doOnTextChanged { text, start, before, count ->
|
||||
regenerateBtn.isEnabled = editText.text.toString().getIDFromYoutubeURL() != null
|
||||
regenerateBtn.isEnabled = editText.text.toString().isYoutubeURL()
|
||||
}
|
||||
|
||||
regenerateBtn.setOnClickListener {
|
||||
|
|
@ -224,7 +224,7 @@ class GenerateYoutubePoTokensFragment : Fragment() {
|
|||
|
||||
val intent = Intent(requireContext(), PoTokenWebViewLoginActivity::class.java)
|
||||
intent.putExtra("url", "https://www.youtube.com")
|
||||
intent.putExtra("redirect_url", "https://www.youtube.com/embed/${editText.text.toString().getIDFromYoutubeURL()}")
|
||||
//intent.putExtra("redirect_url", "https://www.youtube.com/embed/${editText.text.toString().getIDFromYoutubeURL()}")
|
||||
intent.putExtra("no_auth", true)
|
||||
webPoTokenResultLauncher.launch(intent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,6 +472,19 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
}
|
||||
if (!request.hasOption("--no-check-certificates")) request.addOption("--no-check-certificates")
|
||||
|
||||
val canUseWriteInfoJson =
|
||||
!sharedPreferences.getBoolean("disable_write_info_json", false) &&
|
||||
!request.toString().contains("--download-sections")
|
||||
if (canUseWriteInfoJson) {
|
||||
val infoJsonFile = getInfoJsonFile(url)
|
||||
//ignore info file if its older than 5 hours. puny measure to prevent expired formats in some cases
|
||||
if (infoJsonFile != null && System.currentTimeMillis() - infoJsonFile.lastModified() <= (1000 * 60 * 60 * 5)) {
|
||||
request.addOption("--load-info-json", infoJsonFile.absolutePath)
|
||||
}else {
|
||||
request.addWriteInfoJson(url)
|
||||
}
|
||||
}
|
||||
|
||||
val res = YoutubeDL.getInstance().execute(request)
|
||||
val results: Array<String?> = try {
|
||||
res.out.split(System.lineSeparator()).toTypedArray()
|
||||
|
|
@ -610,6 +623,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
val infoJsonName = hash(id)
|
||||
//yt-dlp doesnt overwrite info json, so delete manually
|
||||
File("${cachePath}/${infoJsonName}video.info.json").delete()
|
||||
this.addOption("--no-clean-info-json")
|
||||
this.addCommands(listOf("--print-to-file", "video:%()j", "${cachePath}/${infoJsonName}${System.currentTimeMillis()}video.info.json"))
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +659,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
request.addOption("--print", "%(filename)s")
|
||||
request.addOption("--skip-download")
|
||||
request.addOption("--simulate")
|
||||
request.addOption("--no-check-certificates")
|
||||
request.addOption("--no-check-formats")
|
||||
request.addOption("--quiet")
|
||||
|
||||
|
|
@ -1161,8 +1174,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
|
||||
|
||||
metadataCommands.addOption("--parse-metadata", "%(album_artist,first_artist|)s:%(album_artist)s")
|
||||
metadataCommands.addOption("--parse-metadata", "description:(?:.+?Released\\ on\\s*:\\s*(?P<dscrptn_year>\\d{4}))?")
|
||||
metadataCommands.addOption("--parse-metadata", "%(dscrptn_year,release_year,release_date>%Y,upload_date>%Y)s:(?P<meta_date>\\d+)")
|
||||
metadataCommands.addOption("--parse-metadata", "%(release_year,release_date>%Y,upload_date>%Y)s:(?P<meta_date>\\d+)")
|
||||
|
||||
if (isPlaylistItem) {
|
||||
metadataCommands.addOption("--parse-metadata", "%(track_number,playlist_index)d:(?P<track_number>\\d+)")
|
||||
|
|
@ -1214,6 +1226,12 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
|
||||
var cont = ""
|
||||
val outputContainer = downloadItem.container
|
||||
if (downloadItem.videoPreferences.compatibilityMode) {
|
||||
request.addOption("--recode-video", "mp4")
|
||||
request.addOption("--merge-output-format", "mp4/mkv")
|
||||
request.addOption("--ppa", "VideoConvertor+ffmpeg_o:-c:v libx264 -c:a aac -profile:v baseline")
|
||||
}
|
||||
|
||||
if(outputContainer.isNotEmpty() && outputContainer != "Default" && outputContainer != context.getString(
|
||||
R.string.defaultValue) && supportedContainers.contains(outputContainer)){
|
||||
cont = outputContainer
|
||||
|
|
@ -1221,14 +1239,8 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
val cantRecode = listOf("avi")
|
||||
if (downloadItem.videoPreferences.recodeVideo && !cantRecode.contains(cont)) {
|
||||
request.addOption("--recode-video", outputContainer.lowercase())
|
||||
}else{
|
||||
if (downloadItem.videoPreferences.compatibilityMode) {
|
||||
request.addOption("--recode-video", "mp4")
|
||||
request.addOption("--merge-output-format", "mp4/mkv")
|
||||
}
|
||||
else {
|
||||
request.addOption("--merge-output-format", outputContainer.lowercase())
|
||||
}
|
||||
}else if (!downloadItem.videoPreferences.compatibilityMode){
|
||||
request.addOption("--merge-output-format", outputContainer.lowercase())
|
||||
}
|
||||
|
||||
if (!listOf("webm", "avi", "flv", "gif").contains(outputContainer.lowercase())) {
|
||||
|
|
@ -1258,6 +1270,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
} ?: f
|
||||
}.ifBlank { "ba" }
|
||||
val preferredAudioLanguage = sharedPreferences.getString("audio_language", "")!!
|
||||
val preferDRCAudio = sharedPreferences.getBoolean("prefer_drc_audio", false)
|
||||
if (downloadItem.videoPreferences.removeAudio) audioF = ""
|
||||
|
||||
var abrSort = ""
|
||||
|
|
@ -1293,6 +1306,8 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
if (!f.contains("$videoF+ba")) {
|
||||
if (preferredAudioLanguage.isNotEmpty()) {
|
||||
f.append("$videoF+ba[language^=$preferredAudioLanguage]/")
|
||||
} else if (preferDRCAudio) {
|
||||
f.append("$videoF+ba[format_id$=-drc]/")
|
||||
}else {
|
||||
f.append("$videoF+ba/")
|
||||
}
|
||||
|
|
@ -1328,6 +1343,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
.filter { it.isNotBlank() }
|
||||
.ifEmpty {
|
||||
val list = mutableListOf<String>()
|
||||
if (preferDRCAudio) list.add("ba[format_id$=-drc]")
|
||||
if (preferredAudioLanguage.isNotEmpty() && !downloadItem.videoPreferences.removeAudio) list.add("ba[language^=$preferredAudioLanguage]")
|
||||
list.add(audioF)
|
||||
list
|
||||
|
|
|
|||
5
app/src/main/res/drawable/outline_arrow_forward_24.xml
Normal file
5
app/src/main/res/drawable/outline_arrow_forward_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="960" android:viewportWidth="960" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M647,520L160,520L160,440L647,440L423,216L480,160L800,480L480,800L423,744L647,520Z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -276,8 +276,7 @@
|
|||
android:checked="true"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Use Visitor Data"
|
||||
tools:ignore="HardcodedText" />
|
||||
android:text="@string/visitor_data" />
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@
|
|||
android:title="@string/delete_all_cookies"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/use_header"
|
||||
android:title="@string/user_agent_header"
|
||||
android:checkable="true"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/import_clipboard"
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@
|
|||
|
||||
|
||||
<string-array name="language_entries">
|
||||
<item>System</item>
|
||||
<item>@string/system</item>
|
||||
<item>English</item>
|
||||
<item>العربية</item>
|
||||
<item>Azərbaycanca</item>
|
||||
|
|
@ -1591,6 +1591,4 @@
|
|||
<item>smallest</item>
|
||||
<item>largest</item>
|
||||
</string-array>
|
||||
|
||||
<string name="sponsorblock_hook">Hook</string>
|
||||
</resources>
|
||||
|
|
@ -509,4 +509,5 @@
|
|||
<string name="app_icon">App Icon</string>
|
||||
<string name="show_quick_download_share_menu">Show option to download immediately in the share menu</string>
|
||||
<string name="quick_download_title">Don\'t fetch data</string>
|
||||
<string name="sponsorblock_hook">Hook</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -84,6 +84,14 @@
|
|||
android:icon="@drawable/baseline_note_24"
|
||||
android:key="no_check_certificates"
|
||||
app:title="@string/no_check_certificates" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="false"
|
||||
android:icon="@drawable/if_file_rename"
|
||||
android:key="use_header"
|
||||
app:title="@string/user_agent_header" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/misc">
|
||||
|
|
|
|||
|
|
@ -211,11 +211,6 @@
|
|||
/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
app:defaultValue=""
|
||||
android:key="use_header"
|
||||
app:isPreferenceVisible="false" />
|
||||
|
||||
<Preference
|
||||
app:defaultValue=""
|
||||
android:key="useragent_header"
|
||||
|
|
|
|||
|
|
@ -294,6 +294,20 @@
|
|||
app:summary="@string/preferred_format_id_summary"
|
||||
app:title="@string/preferred_format_id" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="false"
|
||||
app:icon="@drawable/baseline_delete_24"
|
||||
app:key="remove_audio"
|
||||
app:title="@string/remove_audio" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="false"
|
||||
app:icon="@drawable/ic_plus"
|
||||
app:key="also_download_audio"
|
||||
app:title="@string/also_download_audio" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/format">
|
||||
|
|
|
|||
Loading…
Reference in a new issue