stuff
fixed korean fixed please wait card not showing up fixed audio format using mp4 containers added portugese added greek fixed container not updating in multi select card fixed queued swipe to delete bug
This commit is contained in:
parent
f82d49c021
commit
3fe3de940b
10 changed files with 53 additions and 40 deletions
|
|
@ -10,7 +10,12 @@ def properties = new Properties()
|
||||||
def versionMajor = 1
|
def versionMajor = 1
|
||||||
def versionMinor = 6
|
def versionMinor = 6
|
||||||
def versionPatch = 3
|
def versionPatch = 3
|
||||||
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
|
def versionBuild = 1 // bump for dogfood builds, public betas, etc.
|
||||||
|
def versionExt = ""
|
||||||
|
|
||||||
|
if (versionBuild > 0){
|
||||||
|
versionExt = ".${versionBuild}-beta"
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'com.deniscerri.ytdlnis'
|
namespace 'com.deniscerri.ytdlnis'
|
||||||
|
|
@ -37,7 +42,7 @@ android {
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 33
|
targetSdk 33
|
||||||
versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild
|
versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild
|
||||||
versionName "${versionMajor}.${versionMinor}.${versionPatch}"
|
versionName "${versionMajor}.${versionMinor}.${versionPatch}${versionExt}"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
archivesBaseName = "YTDLnis-$versionName"
|
archivesBaseName = "YTDLnis-$versionName"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|
@ -181,10 +186,8 @@ dependencies {
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVer"
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVer"
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVer"
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVer"
|
||||||
|
|
||||||
implementation "com.squareup.retrofit2:retrofit:$retrofitVer"
|
implementation 'com.google.code.gson:gson:2.9.1'
|
||||||
implementation "com.squareup.retrofit2:converter-gson:$retrofitVer"
|
|
||||||
implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.10"
|
implementation "com.squareup.okhttp3:okhttp:5.0.0-alpha.10"
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.11'
|
|
||||||
|
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
|
||||||
implementation "com.google.android.exoplayer:exoplayer:2.18.5"
|
implementation "com.google.android.exoplayer:exoplayer:2.18.5"
|
||||||
|
|
|
||||||
5
app/proguard-rules.pro
vendored
5
app/proguard-rules.pro
vendored
|
|
@ -24,7 +24,7 @@
|
||||||
-keep class com.google.gson.** { *; }
|
-keep class com.google.gson.** { *; }
|
||||||
-keep class com.deniscerri.ytdlnis.database.models.AudioPreferences
|
-keep class com.deniscerri.ytdlnis.database.models.AudioPreferences
|
||||||
-keep class com.deniscerri.ytdlnis.database.models.VideoPreferences
|
-keep class com.deniscerri.ytdlnis.database.models.VideoPreferences
|
||||||
-keepclassmembers class * {
|
-keepclassmembers,allowobfuscation class * {
|
||||||
@com.google.gson.annotations.SerializedName <fields>;
|
@com.google.gson.annotations.SerializedName <fields>;
|
||||||
}
|
}
|
||||||
-keepclassmembers class <1> {
|
-keepclassmembers class <1> {
|
||||||
|
|
@ -67,6 +67,9 @@
|
||||||
-keepclassmembers class * extends androidx.work.Worker {
|
-keepclassmembers class * extends androidx.work.Worker {
|
||||||
public <init>(android.content.Context,androidx.work.WorkerParameters);
|
public <init>(android.content.Context,androidx.work.WorkerParameters);
|
||||||
}
|
}
|
||||||
|
-keep @androidx.room.Entity class *
|
||||||
|
-keep class * extends androidx.room.RoomDatabase
|
||||||
|
-dontwarn androidx.room.paging.**
|
||||||
|
|
||||||
-dontwarn com.google.android.exoplayer2.**
|
-dontwarn com.google.android.exoplayer2.**
|
||||||
# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
|
# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
|
||||||
|
|
|
||||||
|
|
@ -50,17 +50,18 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
|
||||||
|
|
||||||
suspend fun getOne(inputQuery: String, resetResults: Boolean) : ArrayList<ResultItem?>{
|
suspend fun getOne(inputQuery: String, resetResults: Boolean) : ArrayList<ResultItem?>{
|
||||||
val infoUtil = InfoUtil(context)
|
val infoUtil = InfoUtil(context)
|
||||||
val query = infoUtil.getIDFromYoutubeURL(inputQuery)
|
|
||||||
try {
|
try {
|
||||||
val v = infoUtil.getVideo(query)
|
val v = infoUtil.getVideo(inputQuery)
|
||||||
if (resetResults) {
|
if (resetResults) {
|
||||||
deleteAll()
|
deleteAll()
|
||||||
itemCount.value = 1
|
itemCount.value = v.size
|
||||||
}else{
|
}else{
|
||||||
v!!.playlistTitle = "ytdlnis-Search"
|
v.forEach { it?.playlistTitle = "ytdlnis-Search" }
|
||||||
}
|
}
|
||||||
resultDao.insert(v!!)
|
v.forEach {
|
||||||
return arrayListOf(v)
|
resultDao.insert(it!!)
|
||||||
|
}
|
||||||
|
return ArrayList(v)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(tag, e.toString())
|
Log.e(tag, e.toString())
|
||||||
}
|
}
|
||||||
|
|
@ -82,10 +83,10 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
|
||||||
if (tmpToken == nextPageToken) break
|
if (tmpToken == nextPageToken) break
|
||||||
nextPageToken = tmpToken
|
nextPageToken = tmpToken
|
||||||
} while (true)
|
} while (true)
|
||||||
|
itemCount.value = items.size
|
||||||
items.forEach {
|
items.forEach {
|
||||||
resultDao.insert(it!!)
|
resultDao.insert(it!!)
|
||||||
}
|
}
|
||||||
itemCount.value = items.size
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,10 +123,6 @@ class ResultRepository(private val resultDao: ResultDao, private val commandTemp
|
||||||
resultDao.update(item)
|
resultDao.update(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTemplates() : List<CommandTemplate> {
|
|
||||||
return commandTemplateDao.getAllTemplates()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getItemByURL(url: String): ResultItem {
|
fun getItemByURL(url: String): ResultItem {
|
||||||
return resultDao.getResultByURL(url)
|
return resultDao.getResultByURL(url)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,10 +85,10 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
"Search" -> {
|
"Search" -> {
|
||||||
res = repository.search(inputQuery, resetResults)
|
res = repository.search(inputQuery, resetResults)
|
||||||
}
|
}
|
||||||
"Video" -> {
|
"YT_Video" -> {
|
||||||
res = repository.getOne(inputQuery, resetResults)
|
res = repository.getOne(inputQuery, resetResults)
|
||||||
}
|
}
|
||||||
"Playlist" -> {
|
"YT_Playlist" -> {
|
||||||
res = repository.getPlaylist(inputQuery, resetResults)
|
res = repository.getPlaylist(inputQuery, resetResults)
|
||||||
}
|
}
|
||||||
"Default" -> {
|
"Default" -> {
|
||||||
|
|
@ -107,9 +107,9 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
val p = Pattern.compile("^(https?)://(www.)?(music.)?youtu(.be)?")
|
val p = Pattern.compile("^(https?)://(www.)?(music.)?youtu(.be)?")
|
||||||
val m = p.matcher(inputQuery)
|
val m = p.matcher(inputQuery)
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
type = "Video"
|
type = "YT_Video"
|
||||||
if (inputQuery.contains("playlist?list=")) {
|
if (inputQuery.contains("playlist?list=")) {
|
||||||
type = "Playlist"
|
type = "YT_Playlist"
|
||||||
}
|
}
|
||||||
} else if (inputQuery.contains("http")) {
|
} else if (inputQuery.contains("http")) {
|
||||||
type = "Default"
|
type = "Default"
|
||||||
|
|
|
||||||
|
|
@ -357,6 +357,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
when (direction) {
|
when (direction) {
|
||||||
ItemTouchHelper.LEFT -> {
|
ItemTouchHelper.LEFT -> {
|
||||||
val deletedItem = items[position]
|
val deletedItem = items[position]
|
||||||
|
queuedDownloads.notifyItemChanged(position)
|
||||||
removeItem(deletedItem.id)
|
removeItem(deletedItem.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import com.yausername.youtubedl_android.YoutubeDLRequest
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import retrofit2.Retrofit
|
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
|
@ -32,7 +32,6 @@ import java.util.regex.Pattern
|
||||||
class InfoUtil(private val context: Context) {
|
class InfoUtil(private val context: Context) {
|
||||||
private var items: ArrayList<ResultItem?>
|
private var items: ArrayList<ResultItem?>
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private lateinit var retrofit : Retrofit
|
|
||||||
private var key: String? = null
|
private var key: String? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -146,7 +145,9 @@ class InfoUtil(private val context: Context) {
|
||||||
var nextpage = res.getString("nextpage")
|
var nextpage = res.getString("nextpage")
|
||||||
for (i in 0 until dataArray.length()){
|
for (i in 0 until dataArray.length()){
|
||||||
val obj = dataArray.getJSONObject(i)
|
val obj = dataArray.getJSONObject(i)
|
||||||
items.add(createVideoFromPipedJSON(obj, obj.getString("url").removePrefix("/watch?v=")))
|
val itm = createVideoFromPipedJSON(obj, obj.getString("url").removePrefix("/watch?v="))
|
||||||
|
itm?.playlistTitle = "YTDLnis"
|
||||||
|
items.add(itm)
|
||||||
}
|
}
|
||||||
if (nextpage == "null") nextpage = ""
|
if (nextpage == "null") nextpage = ""
|
||||||
return PlaylistTuple(nextpage, items)
|
return PlaylistTuple(nextpage, items)
|
||||||
|
|
@ -211,20 +212,20 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(JSONException::class)
|
@Throws(JSONException::class)
|
||||||
fun getVideo(id: String): ResultItem? {
|
fun getVideo(url: String): List<ResultItem?> {
|
||||||
try {
|
try {
|
||||||
|
val id = getIDFromYoutubeURL(url)
|
||||||
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(url) else listOf(createVideoFromPipedJSON(
|
||||||
res, id
|
res, id
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
//short data
|
//short data
|
||||||
var res =
|
var res =
|
||||||
genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=$id&key=$key")
|
genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=$id&key=$key")
|
||||||
if (!res.has("items")) return getFromYTDL("https://www.youtube.com/watch?v=$id")[0]
|
if (!res.has("items")) return getFromYTDL(url)
|
||||||
var duration = res.getJSONArray("items").getJSONObject(0).getJSONObject("contentDetails")
|
var duration = res.getJSONArray("items").getJSONObject(0).getJSONObject("contentDetails")
|
||||||
.getString("duration")
|
.getString("duration")
|
||||||
duration = formatDuration(duration)
|
duration = formatDuration(duration)
|
||||||
|
|
@ -232,9 +233,9 @@ class InfoUtil(private val context: Context) {
|
||||||
res.put("videoID", id)
|
res.put("videoID", id)
|
||||||
res.put("duration", duration)
|
res.put("duration", duration)
|
||||||
fixThumbnail(res)
|
fixThumbnail(res)
|
||||||
return createVideofromJSON(res)
|
return listOf(createVideofromJSON(res))
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
return getFromYTDL("https://www.youtube.com/watch?v=$id")[0]
|
return getFromYTDL(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -697,9 +698,12 @@ class InfoUtil(private val context: Context) {
|
||||||
} else {
|
} else {
|
||||||
jsonObject.getString("webpage_url_basename")
|
jsonObject.getString("webpage_url_basename")
|
||||||
}
|
}
|
||||||
var author: String? = ""
|
var author: String = if (jsonObject.has("uploader")) jsonObject.getString("uploader") else ""
|
||||||
if (jsonObject.has("uploader")) {
|
if (author.isEmpty() || author == "null"){
|
||||||
author = jsonObject.getString("uploader")
|
author = if (jsonObject.has("channel")) jsonObject.getString("channel") else ""
|
||||||
|
if (author.isEmpty() || author == "null"){
|
||||||
|
author = if (jsonObject.has("playlist_uploader")) jsonObject.getString("playlist_uploader") else ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var duration = ""
|
var duration = ""
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|
@ -747,7 +751,7 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val chaptersInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JSONArray) jsonObject.getJSONArray("formats") else null
|
val chaptersInJSON = if (jsonObject.has("chapters") && jsonObject.get("chapters") is JSONArray) jsonObject.getJSONArray("chapters") else null
|
||||||
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
||||||
var chapters : ArrayList<ChapterItem> = arrayListOf()
|
var chapters : ArrayList<ChapterItem> = arrayListOf()
|
||||||
|
|
||||||
|
|
@ -803,9 +807,12 @@ class InfoUtil(private val context: Context) {
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
||||||
val jsonObject = JSONObject(youtubeDLResponse.out)
|
val jsonObject = JSONObject(youtubeDLResponse.out)
|
||||||
|
|
||||||
var author: String? = ""
|
var author: String = if (jsonObject.has("uploader")) jsonObject.getString("uploader") else ""
|
||||||
if (jsonObject.has("uploader")) {
|
if (author.isEmpty() || author == "null"){
|
||||||
author = jsonObject.getString("uploader")
|
author = if (jsonObject.has("channel")) jsonObject.getString("channel") else ""
|
||||||
|
if (author.isEmpty() || author == "null"){
|
||||||
|
author = if (jsonObject.has("playlist_uploader")) jsonObject.getString("playlist_uploader") else ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var duration = ""
|
var duration = ""
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class UpdateUtil(var context: Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val versionNameInt = version.split("v")[1].replace(".","").toInt()
|
val versionNameInt = version.split("v")[1].replace(".","").toInt()
|
||||||
val currentVersionNameInt = BuildConfig.VERSION_NAME.replace(".","").toInt()
|
val currentVersionNameInt = BuildConfig.VERSION_CODE.toString().replace("0", "").substring(0, versionNameInt.toString().length).toInt()
|
||||||
if (currentVersionNameInt >= versionNameInt) {
|
if (currentVersionNameInt >= versionNameInt) {
|
||||||
result(context.getString(R.string.you_are_in_latest_version))
|
result(context.getString(R.string.you_are_in_latest_version))
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/container"
|
android:id="@+id/codec"
|
||||||
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@
|
||||||
<item>bn</item>
|
<item>bn</item>
|
||||||
<item>bs</item>
|
<item>bs</item>
|
||||||
<item>de</item>
|
<item>de</item>
|
||||||
|
<item>el</item>
|
||||||
<item>es</item>
|
<item>es</item>
|
||||||
<item>fa</item>
|
<item>fa</item>
|
||||||
<item>fr</item>
|
<item>fr</item>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<locale android:name="bn"/>
|
<locale android:name="bn"/>
|
||||||
<locale android:name="bs"/>
|
<locale android:name="bs"/>
|
||||||
<locale android:name="de"/>
|
<locale android:name="de"/>
|
||||||
|
<locale android:name="el"/>
|
||||||
<locale android:name="es"/>
|
<locale android:name="es"/>
|
||||||
<locale android:name="fa-IR"/>
|
<locale android:name="fa-IR"/>
|
||||||
<locale android:name="fr"/>
|
<locale android:name="fr"/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue