more features

This commit is contained in:
deniscerri 2024-11-23 19:40:08 +01:00
parent e1c99e2647
commit 0df5a9e194
No known key found for this signature in database
GPG key ID: 95C43D517D830350
13 changed files with 127 additions and 82 deletions

View file

@ -3,8 +3,9 @@ plugins {
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' version '2.0.1'
id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp'
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10"
id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10"
id "org.jetbrains.kotlin.plugin.serialization" version "2.0.21"
id "org.jetbrains.kotlin.plugin.parcelize" version "2.0.21"
id "org.jetbrains.kotlin.plugin.compose" version "2.0.21"
}
def properties = new Properties()
@ -101,6 +102,7 @@ android {
buildFeatures {
viewBinding true
buildConfig true
compose true
}
@ -195,7 +197,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
implementation 'it.xabaras.android:recyclerview-swipedecorator:1.4'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.6"
implementation "com.github.Irineu333:Highlight-KT:1.0.4"
implementation "com.neoutils.highlight:highlight-view:2.2.0"
// For media playback using ExoPlayer
implementation("androidx.media3:media3-exoplayer:$media3_version")

View file

@ -228,6 +228,9 @@ interface DownloadDao {
@Query("UPDATE downloads set status=:status where id=:id")
suspend fun setStatus(id: Long, status: String)
@Query("UPDATE downloads set status=:status where id IN (:ids)")
suspend fun setStatusMultiple(ids: List<Long>, status: String)
@Update
suspend fun updateWithoutUpsert(item: DownloadItem)

View file

@ -123,6 +123,10 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
downloadDao.setStatus(id, status.toString())
}
suspend fun setDownloadStatusMultiple(ids: List<Long>, status: Status) {
downloadDao.setStatusMultiple(ids, status.toString())
}
fun getItemByID(id: Long) : DownloadItem {
return downloadDao.getDownloadById(id)
}

View file

@ -1268,9 +1268,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
}
delay(1000)
isPausingResuming = false
activeDownloadsList.forEach {
repository.setDownloadStatus(it.id, DownloadRepository.Status.Paused)
}
repository.setDownloadStatusMultiple(activeDownloadsList.map { it.id }, DownloadRepository.Status.Paused)
pausedAllDownloads.value = PausedAllDownloadsState.RESUME
}

View file

@ -71,6 +71,10 @@ class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activ
text = finalText
}
card.findViewById<TextView>(R.id.dataFetchingExtraCommands).apply {
isVisible = item.useAsExtraCommandDataFetching
}
card.findViewById<TextView>(R.id.preferredTemplate).apply {
val preferred = sharedPreferences.getString("preferred_command_template", "")
isVisible = preferred == item.content
@ -165,7 +169,8 @@ class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activ
oldItem.content == newItem.content &&
oldItem.useAsExtraCommand == newItem.useAsExtraCommand &&
oldItem.useAsExtraCommandAudio == newItem.useAsExtraCommandAudio &&
oldItem.useAsExtraCommandVideo == newItem.useAsExtraCommandVideo
oldItem.useAsExtraCommandVideo == newItem.useAsExtraCommandVideo &&
oldItem.useAsExtraCommandDataFetching == newItem.useAsExtraCommandDataFetching
}
}
}

View file

@ -46,11 +46,12 @@ import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository.EveryCat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.tabs.TabLayout
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.neo.highlight.core.Highlight
import com.neo.highlight.util.listener.HighlightTextWatcher
import com.neo.highlight.util.scheme.ColorScheme
import com.neoutils.highlight.core.Highlight
import com.neoutils.highlight.core.scheme.TextColorScheme
import com.neoutils.highlight.core.util.Match
import com.neoutils.highlight.core.util.UiColor
import com.neoutils.highlight.view.extension.toSpannedString
import com.neoutils.highlight.view.text.HighlightTextWatcher
import com.squareup.picasso.Picasso
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@ -72,28 +73,27 @@ object Extensions {
return (metrics.density * px).toInt()
}
private var textHighLightSchemes = listOf(
ColorScheme(Pattern.compile("([\"'])(?:\\\\1|.)*?\\1"), Color.parseColor("#FC8500")),
ColorScheme(Pattern.compile("yt-dlp"), Color.parseColor("#77eb09")),
ColorScheme(Pattern.compile("(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})"), Color.parseColor("#b5942f")),
ColorScheme(Pattern.compile("\\d+(\\.\\d)?%"), Color.parseColor("#43a564"))
private var textHighlightSchemes = listOf(
TextColorScheme(regex = "([\"'])(?:\\\\1|.)*?\\1".toRegex(), match = Match.fully(UiColor.Hex("#FC8500"))),
TextColorScheme(regex = "yt-dlp".toRegex(), match = Match.fully(UiColor.Hex("#77eb09"))),
TextColorScheme(regex = "(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})".toRegex(), match = Match.fully(UiColor.Hex("#b5942f"))),
TextColorScheme(regex = "\\d+(\\.\\d)?%".toRegex(), match = Match.fully(UiColor.Hex("#43a564"))),
)
fun View.enableTextHighlight(){
if (this is EditText || this is TextView){
//init syntax highlighter
val highlight = Highlight()
val highlightWatcher = HighlightTextWatcher()
val highlight = Highlight(textHighlightSchemes)
val highlightWatcher = HighlightTextWatcher(highlight)
highlight.addScheme(
*textHighLightSchemes.map { it }.toTypedArray()
)
highlightWatcher.addScheme(
*textHighLightSchemes.map { it }.toTypedArray()
)
highlight.setSpan(this as TextView)
this.addTextChangedListener(highlightWatcher)
if (this is EditText) {
this.addTextChangedListener(highlightWatcher)
this.setText(highlight.toSpannedString(this.text.toString()))
}else if (this is TextView) {
this.addTextChangedListener(highlightWatcher)
this.text = highlight.toSpannedString(this.text.toString())
}
}
}

View file

@ -108,7 +108,7 @@ object FileUtil {
if (it.isDirectory && it.absolutePath == originDir.absolutePath) return@forEach
var destFile: DocumentFile
try {
if (it.name.matches("(^config.*.\\.txt\$)|(rList)|(.*.part-Frag.*)|(.*.live_chat)|(.*.ytdl)".toRegex())){
if (it.name.matches("(^config.*.\\.txt\$)|(rList)|(.*.part-Frag.*)|(.*.live_chat)|(.*.ytdl)|(.*.info.json)".toRegex())){
return@forEach
}

View file

@ -725,6 +725,18 @@ class YTDLPUtil(private val context: Context) {
request.addOption("--download-archive", FileUtil.getDownloadArchivePath(context))
}
if (!sharedPreferences.getBoolean("disable_write_info_json", false)) {
val infoJsonFile = downDir.walkTopDown().firstOrNull { it.name == "${downloadItem.id}.info.json" }
//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("--write-info-json")
request.addOption("--no-clean-info-json")
request.addOption("-o", "infojson:${downloadItem.id}")
}else {
request.addOption("--load-info-json", infoJsonFile.absolutePath)
}
}
val preferredAudioCodec = sharedPreferences.getString("audio_codec", "")!!
val aCodecPrefIndex = context.getStringArray(R.array.audio_codec_values).indexOf(preferredAudioCodec)
val aCodecPref = runCatching { context.getStringArray(R.array.audio_codec_values_ytdlp)[aCodecPrefIndex] }.getOrElse { "" }

View file

@ -41,64 +41,75 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<HorizontalScrollView
android:layout_width="wrap_content"
android:scrollbars="none"
<com.google.android.material.chip.ChipGroup
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/content"
app:layout_constraintHorizontal_bias="0.0"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
<TextView
android:id="@+id/preferredTemplate"
style="@style/Widget.Material3.FloatingActionButton.Large.Primary"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:background="@drawable/rounded_corner"
android:backgroundTint="?attr/colorPrimaryContainer"
android:clickable="false"
android:gravity="center"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textSize="12sp"
android:textStyle="bold"
app:cornerRadius="10dp"
android:text="@string/preferred_command_template"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/preferredTemplate"
style="@style/Widget.Material3.FloatingActionButton.Large.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:background="@drawable/rounded_corner"
android:backgroundTint="?attr/colorPrimaryContainer"
android:clickable="false"
android:gravity="center"
android:visibility="gone"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textSize="12sp"
android:textStyle="bold"
app:cornerRadius="10dp"
android:text="@string/preferred_command_template"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/useInExtraCommands"
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/extra_command"
android:background="@drawable/rounded_corner"
android:backgroundTint="?attr/colorSecondaryContainer"
android:clickable="false"
android:gravity="center"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textSize="12sp"
android:textStyle="bold"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/useInExtraCommands"
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginEnd="5dp"
android:text="@string/extra_command"
android:background="@drawable/rounded_corner"
android:backgroundTint="?attr/colorSecondaryContainer"
android:clickable="false"
android:gravity="center"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textSize="12sp"
android:textStyle="bold"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/dataFetchingExtraCommands"
style="@style/Widget.Material3.FloatingActionButton.Large.Tertiary"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/data_fetching_extra_command"
android:background="@drawable/rounded_corner"
android:backgroundTint="?attr/colorTertiaryContainer"
android:clickable="false"
android:gravity="center"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textSize="12sp"
android:textStyle="bold"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</HorizontalScrollView>
</com.google.android.material.chip.ChipGroup>

View file

@ -437,4 +437,6 @@
<string name="data_fetching_extra_command">Data Fetching Extra Command</string>
<string name="thumbnail">Thumbnail</string>
<string name="data_fetching_extra_command_summary">Enable command templates to be used for data fetching as extra commands</string>
<string name="disable_write_info_json">Disable Write Info Json</string>
<string name="disable_write_info_json_summary">(Not Recommended) Every time you restart / resume the download, yt-dlp will re-download json data from the servers.</string>
</resources>

View file

@ -33,4 +33,12 @@
android:title="@string/data_fetching_extra_command" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/downloading">
<SwitchPreferenceCompat
android:icon="@drawable/if_file_rename"
android:key="disable_write_info_json"
android:summary="@string/disable_write_info_json_summary"
android:title="@string/disable_write_info_json" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -41,11 +41,11 @@ buildscript {
plugins {
id 'com.android.application' version '8.5.2' apply false
id 'com.android.library' version '8.5.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10" apply false
id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10" apply false
id 'org.jetbrains.kotlin.android' version '2.0.21' apply false
id "org.jetbrains.kotlin.plugin.serialization" version "2.0.21" apply false
id "org.jetbrains.kotlin.plugin.parcelize" version "2.0.21" apply false
id 'com.android.test' version '8.5.2' apply false
id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
id 'com.google.devtools.ksp' version '2.0.21-1.0.28' apply false
}
tasks.register('clean', Delete) {

View file

@ -11,9 +11,9 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sun Oct 08 20:53:48 CEST 2023
android.defaults.buildfeatures.buildconfig=true
android.enableJetifier=true
android.nonFinalResIds=false
android.nonTransitiveRClass=false
android.suppressUnsupportedCompileSdk=35
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1024M" -Dfile.encoding\=UTF-8