fixed terminal mode somewhat & implemented language preference

This commit is contained in:
Denis Çerri 2023-02-18 21:59:15 +01:00
parent 7783b2846d
commit 5482105a18
No known key found for this signature in database
GPG key ID: 95C43D517D830350
24 changed files with 291 additions and 144 deletions

View file

@ -320,7 +320,7 @@
<PersistentState> <PersistentState>
<option name="values"> <option name="values">
<map> <map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/text_format/baseline_text_format_24.xml" /> <entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/terminal/baseline_terminal_24.xml" />
</map> </map>
</option> </option>
</PersistentState> </PersistentState>
@ -330,7 +330,7 @@
</option> </option>
<option name="values"> <option name="values">
<map> <map>
<entry key="outputName" value="ic_textformat" /> <entry key="outputName" value="ic_terminal" />
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" /> <entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
</map> </map>
</option> </option>

View file

@ -14,8 +14,10 @@
<application <application
android:name=".App" android:name=".App"
android:allowBackup="false" android:allowBackup="false"
android:localeConfig="@xml/locales_config"
android:extractNativeLibs="true" android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:configChanges="layoutDirection|locale"
android:label="@string/app_name" android:label="@string/app_name"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
@ -27,6 +29,7 @@
tools:ignore="DataExtractionRules"> tools:ignore="DataExtractionRules">
<activity android:name=".MainActivity" <activity android:name=".MainActivity"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:configChanges="layoutDirection|locale"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -46,6 +49,7 @@
</activity> </activity>
<activity android:name=".receiver.ShareActivity" <activity android:name=".receiver.ShareActivity"
android:configChanges="layoutDirection|locale"
android:exported="true"> android:exported="true">
<!-- <intent-filter>--> <!-- <intent-filter>-->
@ -62,6 +66,7 @@
</activity> </activity>
<activity <activity
android:name=".ui.settings.SettingsActivity" android:name=".ui.settings.SettingsActivity"
android:configChanges="layoutDirection|locale"
android:parentActivityName=".MainActivity" android:parentActivityName=".MainActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
@ -71,6 +76,7 @@
</activity> </activity>
<activity <activity
android:name=".ui.CustomCommandActivity" android:name=".ui.CustomCommandActivity"
android:configChanges="layoutDirection|locale"
android:theme="@style/AppDefaultTheme" android:theme="@style/AppDefaultTheme"
android:parentActivityName=".MainActivity" android:parentActivityName=".MainActivity"
android:label="@string/run_command" android:label="@string/run_command"

View file

@ -2,6 +2,8 @@ package com.deniscerri.ytdlnis
import android.app.Application import android.app.Application
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.work.Configuration import androidx.work.Configuration
import androidx.work.WorkManager import androidx.work.WorkManager
@ -11,9 +13,11 @@ import com.yausername.aria2c.Aria2c
import com.yausername.ffmpeg.FFmpeg import com.yausername.ffmpeg.FFmpeg
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLException import com.yausername.youtubedl_android.YoutubeDLException
import java.util.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
class App : Application() { class App : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
DynamicColors.applyToActivitiesIfAvailable(this) DynamicColors.applyToActivitiesIfAvailable(this)
@ -40,6 +44,9 @@ class App : Application() {
Toast.makeText(this@App, e.message, Toast.LENGTH_SHORT).show() Toast.makeText(this@App, e.message, Toast.LENGTH_SHORT).show()
e.printStackTrace() e.printStackTrace()
} }
val locale = getSharedPreferences("root_preferences", MODE_PRIVATE)
.getString("app_language", Locale.getDefault().language)!!
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(locale))
} }
@Throws(YoutubeDLException::class) @Throws(YoutubeDLException::class)
private fun initLibraries() { private fun initLibraries() {

View file

@ -5,6 +5,7 @@ import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Build.VERSION_CODES import android.os.Build.VERSION_CODES
@ -15,7 +16,9 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.WindowInsets import android.view.WindowInsets
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.os.LocaleListCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
@ -49,6 +52,7 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setContentView(binding.root) setContentView(binding.root)
context = baseContext context = baseContext
@ -253,6 +257,10 @@ class MainActivity : AppCompatActivity() {
} }
dialog.show() dialog.show()
} }
override fun onConfigurationChanged(newConfig: Configuration) {
startActivity(Intent(this, MainActivity::class.java))
super.onConfigurationChanged(newConfig)
}
companion object { companion object {
private const val TAG = "MainActivity" private const val TAG = "MainActivity"

View file

@ -103,7 +103,7 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
DownloadViewModel.Type.video -> { DownloadViewModel.Type.video -> {
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video)
} }
DownloadViewModel.Type.command -> { else -> {
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_baseline_keyboard_arrow_right_24) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_baseline_keyboard_arrow_right_24)
} }
} }

View file

@ -38,7 +38,8 @@ class Converters {
return when(string){ return when(string){
"audio" -> DownloadViewModel.Type.audio "audio" -> DownloadViewModel.Type.audio
"video" -> DownloadViewModel.Type.video "video" -> DownloadViewModel.Type.video
else -> DownloadViewModel.Type.command "command" -> DownloadViewModel.Type.command
else -> DownloadViewModel.Type.terminal
} }
} }

View file

@ -52,4 +52,7 @@ interface DownloadDao {
@Query("SELECT * FROM downloads WHERE url=:url AND format=:format AND (status='Error' OR status='Cancelled') LIMIT 1") @Query("SELECT * FROM downloads WHERE url=:url AND format=:format AND (status='Error' OR status='Cancelled') LIMIT 1")
fun getUnfinishedByURLAndFormat(url: String, format: String) : DownloadItem fun getUnfinishedByURLAndFormat(url: String, format: String) : DownloadItem
@Query("SELECT * FROM downloads WHERE type='terminal' ORDER BY id DESC LIMIT 1")
fun getTerminalDownload() : DownloadItem
} }

View file

@ -64,4 +64,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
0L 0L
} }
} }
fun getTerminalDownload() : Long {
return downloadDao.getTerminalDownload().id
}
} }

View file

@ -37,7 +37,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
private var bestVideoFormat : Format private var bestVideoFormat : Format
private var bestAudioFormat : Format private var bestAudioFormat : Format
enum class Type { enum class Type {
audio, video, command audio, video, command, terminal
} }
init { init {
@ -92,7 +92,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
val downloadPath = when(type){ val downloadPath = when(type){
Type.audio -> sharedPreferences.getString("music_path", getApplication<App>().resources.getString(R.string.music_path)) Type.audio -> sharedPreferences.getString("music_path", getApplication<App>().resources.getString(R.string.music_path))
Type.video -> sharedPreferences.getString("video_path", getApplication<App>().resources.getString(R.string.video_path)) Type.video -> sharedPreferences.getString("video_path", getApplication<App>().resources.getString(R.string.video_path))
Type.command -> sharedPreferences.getString("command_path", getApplication<App>().resources.getString(R.string.command_path)) else -> sharedPreferences.getString("command_path", getApplication<App>().resources.getString(R.string.command_path))
} }
val audioPreferences = AudioPreferences(embedThumb) val audioPreferences = AudioPreferences(embedThumb)
@ -111,18 +111,19 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
} }
private fun getFormat(resultItem: ResultItem, type: Type) : Format {
private fun getFormat(resultItem: ResultItem?, type: Type) : Format {
when(type) { when(type) {
Type.audio -> { Type.audio -> {
return try { return try {
resultItem.formats.last { it.format_note.contains("audio", ignoreCase = true) } resultItem!!.formats.last { it.format_note.contains("audio", ignoreCase = true) }
}catch (e: Exception){ }catch (e: Exception){
bestAudioFormat bestAudioFormat
} }
} }
Type.video -> { Type.video -> {
return try { return try {
resultItem.formats.last { !it.format_note.contains("audio", ignoreCase = true) } resultItem!!.formats.last { !it.format_note.contains("audio", ignoreCase = true) }
}catch (e: Exception){ }catch (e: Exception){
bestVideoFormat bestVideoFormat
} }
@ -203,4 +204,39 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
} }
} }
fun startTerminalDownload(command: String) = viewModelScope.launch(Dispatchers.IO) {
val downloadPath = sharedPreferences.getString("command_path", getApplication<App>().resources.getString(R.string.command_path))
val downloadItem = DownloadItem(0,
"",
"",
"",
"",
"",
Type.terminal,
Format("", "", 0, command),
downloadPath!!, "", "", "", AudioPreferences(), VideoPreferences(), "", false, DownloadRepository.Status.Processing.toString(), 0
)
downloadItem.status = DownloadRepository.Status.Queued.toString()
Log.e("aaaaaaaa", downloadItem.toString())
val id = repository.insert(downloadItem)
downloadItem.id = id
val workRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
.setInputData(Data.Builder().putLong("id", downloadItem.id).build())
.addTag("terminal")
.build()
val context = getApplication<App>().applicationContext
WorkManager.getInstance(context).beginUniqueWork(
downloadItem.id.toString(),
ExistingWorkPolicy.KEEP,
workRequest
).enqueue()
}
fun getTerminalDownload(): Long {
return repository.getTerminalDownload();
}
} }

View file

@ -6,19 +6,34 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View
import android.widget.EditText import android.widget.EditText
import android.widget.ScrollView import android.widget.ScrollView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.service.IDownloaderService import com.deniscerri.ytdlnis.service.IDownloaderService
import com.deniscerri.ytdlnis.util.NotificationUtil import com.deniscerri.ytdlnis.util.NotificationUtil
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
class CustomCommandActivity : AppCompatActivity() { class CustomCommandActivity : AppCompatActivity() {
private var topAppBar: MaterialToolbar? = null private var topAppBar: MaterialToolbar? = null
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var notificationUtil: NotificationUtil
private lateinit var workManager: WorkManager
private var isDownloadServiceRunning = false private var isDownloadServiceRunning = false
private var output: TextView? = null private var output: TextView? = null
private var input: EditText? = null private var input: EditText? = null
@ -27,80 +42,6 @@ class CustomCommandActivity : AppCompatActivity() {
private var iDownloaderService: IDownloaderService? = null private var iDownloaderService: IDownloaderService? = null
private var scrollView: ScrollView? = null private var scrollView: ScrollView? = null
var context: Context? = null var context: Context? = null
// private val serviceConnection: ServiceConnection = object : ServiceConnection {
// override fun onServiceConnected(className: ComponentName, service: IBinder) {
// downloaderService = (service as LocalBinder).service
// iDownloaderService = service
// isDownloadServiceRunning = true
// try {
// val listeners = ArrayList<IDownloaderListener>()
// listeners.add(listener)
// iDownloaderService!!.addActivity(this@CustomCommandActivity, listeners)
// listener.onDownloadStart(iDownloaderService!!.info)
// } catch (e: Exception) {
// e.printStackTrace()
// }
// }
//
// override fun onServiceDisconnected(componentName: ComponentName) {
// downloaderService = null
// iDownloaderService = null
// isDownloadServiceRunning = false
// }
// }
// var listener: IDownloaderListener = object : IDownloaderListener {
// override fun onDownloadStart(info: DownloadInfo) {
// input!!.isEnabled = false
// output!!.text = ""
// swapFabs()
// }
//
// override fun onDownloadProgress(info: DownloadInfo) {
// val newInfo = info.outputLine
// if (newInfo.contains("[download]")) {
// val temp = output!!.text.toString()
// output!!.text =
// temp.substring(0, temp.lastIndexOf(System.getProperty("line.separator")!!) - 2)
// }
// output!!.append(
// """${info.outputLine}
//"""
// )
// output!!.scrollTo(0, output!!.height)
// scrollView!!.fullScroll(View.FOCUS_DOWN)
// }
//
// @SuppressLint("SetTextI18n")
// override fun onDownloadError(info: DownloadInfo) {
// output!!.append(
// """
//
// ${info.outputLine}
// """.trimIndent()
// )
// scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount)
// input!!.setText("yt-dlp ")
// input!!.isEnabled = true
// swapFabs()
// }
//
// @SuppressLint("SetTextI18n")
// override fun onDownloadEnd(info: DownloadInfo) {
// output!!.append(info.outputLine)
// scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount)
// // MEDIA SCAN
// MediaScannerConnection.scanFile(context, arrayOf("/storage"), null, null)
// input!!.setText("yt-dlp ")
// input!!.isEnabled = true
// swapFabs()
// }
//
// override fun onDownloadCancel(downloadInfo: DownloadInfo) {}
// override fun onDownloadCancelAll(downloadInfo: DownloadInfo) {}
// override fun onDownloadServiceEnd() {
// stopDownloadService()
// }
// }
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -115,19 +56,18 @@ class CustomCommandActivity : AppCompatActivity() {
input!!.requestFocus() input!!.requestFocus()
fab = findViewById(R.id.command_fab) fab = findViewById(R.id.command_fab)
fab!!.setOnClickListener { fab!!.setOnClickListener {
if (isStoragePermissionGranted) { startDownload(
startDownloadService( input!!.text.toString()
input!!.text.toString(), )
NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID
)
}
} }
cancelFab = findViewById(R.id.cancel_command_fab) cancelFab = findViewById(R.id.cancel_command_fab)
cancelFab!!.setOnClickListener { cancelFab!!.setOnClickListener {
cancelDownloadService() cancelDownload()
swapFabs()
input!!.isEnabled = true input!!.isEnabled = true
} }
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
notificationUtil = NotificationUtil(this)
workManager = WorkManager.getInstance(this)
handleIntent(intent) handleIntent(intent)
} }
@ -147,53 +87,32 @@ class CustomCommandActivity : AppCompatActivity() {
} }
} }
private fun swapFabs() {
val cancel = cancelFab!!.visibility
val start = fab!!.visibility
cancelFab!!.visibility = start
fab!!.visibility = cancel
}
private fun startDownload(command: String?) {
private fun startDownloadService(command: String?, id: Int) {
if (isDownloadServiceRunning) return if (isDownloadServiceRunning) return
//val serviceIntent = Intent(context, DownloaderService::class.java) downloadViewModel.startTerminalDownload(command!!)
// serviceIntent.putExtra("command", command) output!!.text = ""
// serviceIntent.putExtra("id", id) workManager.getWorkInfosByTagLiveData("terminal")
//context!!.applicationContext.bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE) .observe(this){ list ->
list.forEach {
if(it.progress.getString("output") != null){
output?.append("\n" + it.progress.getString("output") + "\n")
output?.scrollTo(0, output!!.height)
scrollView?.fullScroll(View.FOCUS_DOWN)
}
}
}
} }
fun stopDownloadService() { private fun cancelDownload() {
// if (!isDownloadServiceRunning) return lifecycleScope.launch {
// iDownloaderService!!.removeActivity(this) val id = withContext(Dispatchers.IO){ downloadViewModel.getTerminalDownload(); }
// context!!.applicationContext.unbindService(serviceConnection) YoutubeDL.getInstance().destroyProcessById(id.toString())
// downloaderService!!.stopForeground(true) WorkManager.getInstance(this@CustomCommandActivity).cancelUniqueWork(id.toString())
// downloaderService!!.stopSelf() notificationUtil.cancelDownloadNotification(id.toInt())
// isDownloadServiceRunning = false
}
fun cancelDownloadService() {
if (!isDownloadServiceRunning) return
iDownloaderService!!.cancelDownload(false)
stopDownloadService()
}
private val isStoragePermissionGranted: Boolean
get() = if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
== PackageManager.PERMISSION_GRANTED
) {
true
} else {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
1
)
false
} }
}
companion object { companion object {
private const val TAG = "CustomCommandActivity" private const val TAG = "CustomCommandActivity"

View file

@ -72,7 +72,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
tabLayout.selectTab(tabLayout.getTabAt(1)) tabLayout.selectTab(tabLayout.getTabAt(1))
viewPager2.setCurrentItem(1, false) viewPager2.setCurrentItem(1, false)
} }
Type.command -> { else -> {
tabLayout.selectTab(tabLayout.getTabAt(2)) tabLayout.selectTab(tabLayout.getTabAt(2))
viewPager2.setCurrentItem(2, false) viewPager2.setCurrentItem(2, false)
} }

View file

@ -73,7 +73,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
tabLayout.selectTab(tabLayout.getTabAt(1)) tabLayout.selectTab(tabLayout.getTabAt(1))
viewPager2.setCurrentItem(1, false) viewPager2.setCurrentItem(1, false)
} }
Type.command -> { else -> {
tabLayout.selectTab(tabLayout.getTabAt(2)) tabLayout.selectTab(tabLayout.getTabAt(2))
viewPager2.setCurrentItem(2, false) viewPager2.setCurrentItem(2, false)
} }

View file

@ -1,12 +1,16 @@
package com.deniscerri.ytdlnis.ui.settings package com.deniscerri.ytdlnis.ui.settings
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.os.LocaleList
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.appbar.MaterialToolbar
import java.util.*
class SettingsActivity : AppCompatActivity() { class SettingsActivity : AppCompatActivity() {
private var fm: FragmentManager? = null private var fm: FragmentManager? = null
@ -23,4 +27,34 @@ class SettingsActivity : AppCompatActivity() {
.replace(R.id.settings_frame_layout, SettingsFragment()) .replace(R.id.settings_frame_layout, SettingsFragment())
.commit() .commit()
} }
fun setLocale(l: String){
val locale = Locale(l)
Locale.setDefault(locale)
val config: Configuration = this.resources.configuration
if (Build.VERSION.SDK_INT >= 24){
Locale.setDefault(locale)
config.setLocales(LocaleList(locale))
this.resources.updateConfiguration(config, this.resources.displayMetrics)
onConfigurationChanged(config)
}else{
Locale.setDefault(locale)
config.locale = locale
config.setLayoutDirection(locale)
this.resources.updateConfiguration(config, this.resources.displayMetrics)
onConfigurationChanged(config)
}
restartActivity()
}
private fun restartActivity() {
// val intent = intent
// finish()
// startActivity(Intent(this, MainActivity::class.java))
recreate()
}
} }

View file

@ -2,17 +2,23 @@ package com.deniscerri.ytdlnis.ui.settings
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.preference.* import androidx.preference.*
import com.deniscerri.ytdlnis.BuildConfig import com.deniscerri.ytdlnis.BuildConfig
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.UpdateUtil import com.deniscerri.ytdlnis.util.UpdateUtil
import java.util.*
class SettingsFragment : PreferenceFragmentCompat() { class SettingsFragment : PreferenceFragmentCompat() {
private var language: ListPreference? = null
private var musicPath: Preference? = null private var musicPath: Preference? = null
private var videoPath: Preference? = null private var videoPath: Preference? = null
private var commandPath: Preference? = null private var commandPath: Preference? = null
@ -51,6 +57,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
val preferences = val preferences =
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
val editor = preferences.edit() val editor = preferences.edit()
language = findPreference("app_language")
musicPath = findPreference("music_path") musicPath = findPreference("music_path")
videoPath = findPreference("video_path") videoPath = findPreference("video_path")
commandPath = findPreference("command_path") commandPath = findPreference("command_path")
@ -76,6 +83,20 @@ class SettingsFragment : PreferenceFragmentCompat() {
updateApp = findPreference("update_app") updateApp = findPreference("update_app")
version = findPreference("version") version = findPreference("version")
version!!.summary = BuildConfig.VERSION_NAME version!!.summary = BuildConfig.VERSION_NAME
val values = resources.getStringArray(R.array.language_values)
if (Build.VERSION.SDK_INT >= 34){
language!!.isVisible = false
}else{
val entries = mutableListOf<String>()
values.forEach {
entries.add(Locale(it).getDisplayName(Locale(it)))
}
language!!.entries = entries.toTypedArray()
}
val lang = if (values.contains(Locale.getDefault().language)) Locale.getDefault().language else "en"
editor.putString("app_language", lang)
if (preferences.getString("music_path", "")!!.isEmpty()) { if (preferences.getString("music_path", "")!!.isEmpty()) {
editor.putString("music_path", getString(R.string.music_path)) editor.putString("music_path", getString(R.string.music_path))
} }
@ -111,6 +132,17 @@ class SettingsFragment : PreferenceFragmentCompat() {
val preferences = val preferences =
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
val editor = preferences.edit() val editor = preferences.edit()
language!!.summary = Locale(preferences.getString("app_language", "")!!).getDisplayLanguage(Locale(preferences.getString("app_language", "")!!))
language!!.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
editor.putString("app_language", newValue.toString())
language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString()))
editor.apply()
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString()))
(requireActivity() as SettingsActivity).setLocale(newValue.toString())
true
}
musicPath!!.summary = fileUtil?.formatPath(preferences.getString("music_path", "")!!) musicPath!!.summary = fileUtil?.formatPath(preferences.getString("music_path", "")!!)
musicPath!!.onPreferenceClickListener = musicPath!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {

View file

@ -67,13 +67,13 @@ class DownloadWorker(
val url = downloadItem.url val url = downloadItem.url
val request = YoutubeDLRequest(url) var request = YoutubeDLRequest(url)
val type = downloadItem.type val type = downloadItem.type
val downloadLocation = downloadItem.downloadPath val downloadLocation = downloadItem.downloadPath
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""") var tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
tempFolder.append("##${downloadItem.format.format_id}") tempFolder.append("##${downloadItem.format.format_id}")
val tempFileDir = File(tempFolder.toString()) var tempFileDir = File(tempFolder.toString())
tempFileDir.delete() tempFileDir.delete()
tempFileDir.mkdir() tempFileDir.mkdir()
@ -190,6 +190,32 @@ class DownloadWorker(
} }
} }
} }
DownloadViewModel.Type.terminal -> {
if(downloadItem.format.format_note.startsWith("yt-dlp ")){
downloadItem.format.format_note = downloadItem.format.format_note.substring(6).trim();
}
val commandRegex = "\"([^\"]*)\"|(\\S+)"
request = YoutubeDLRequest(emptyList())
tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.format.format_id}##terminal""")
tempFileDir = File(tempFolder.toString())
tempFileDir.delete()
tempFileDir.mkdir()
val m = Pattern.compile(commandRegex).matcher(downloadItem.format.format_note)
while (m.find()) {
if (m.group(1) != null) {
request.addOption(m.group(1)!!)
} else {
request.addOption(m.group(2)!!)
}
}
request.addOption("-o", tempFileDir.absolutePath + "/${downloadItem.customFileNameTemplate}.%(ext)s")
}
} }
runCatching { runCatching {

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M20,4H4C2.89,4 2,4.9 2,6v12c0,1.1 0.89,2 2,2h16c1.1,0 2,-0.9 2,-2V6C22,4.9 21.11,4 20,4zM20,18H4V8h16V18zM18,17h-6v-2h6V17zM7.5,17l-1.41,-1.41L8.67,13l-2.59,-2.59L7.5,9l4,4L7.5,17z"/>
</vector>

View file

@ -64,8 +64,7 @@
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/custom_command_toolbar" android:id="@+id/custom_command_toolbar"
android:elevation="0dp" android:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap" app:title="@string/terminal"
app:title="@string/custom_command"
android:layout_width="match_parent" android:layout_width="match_parent"
app:navigationIcon="@drawable/ic_back" app:navigationIcon="@drawable/ic_back"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>

View file

@ -142,4 +142,22 @@
<string name="sponsorblock_fillers">Pjesë Shtesë</string> <string name="sponsorblock_fillers">Pjesë Shtesë</string>
<string name="sponsorblock_reminders">Përkujtuesit e Abonimit</string> <string name="sponsorblock_reminders">Përkujtuesit e Abonimit</string>
<string name="select_sponsorblock_filtering">Zgjidh Filtrimin e SponsorBlock</string> <string name="select_sponsorblock_filtering">Zgjidh Filtrimin e SponsorBlock</string>
<string name="save_dir">Direktoria</string>
<string name="new_template">Shabllon i ri</string>
<string name="adjust_templates">Cakto Shabllonët</string>
<string name="edit_selected">Redakto të zgjedhurin</string>
<string name="adjust_video">Modifiko Videon</string>
<string name="schedule">Planifiko</string>
<string name="concurrent_downloads">Shkarkimet e njëkohësishme</string>
<string name="concurrent_downloads_summary">Numri i shkarkimeve qe do ekzekutohen në të njëjtën kohë</string>
<string name="defaultValue">Siç është</string>
<string name="container">Formati</string>
<string name="template">Shablloni</string>
<string name="logs">Shënimet</string>
<string name="commands">Komandat</string>
<string name="date_added">Data e shtuar</string>
<string name="update_ytdl_nightly">Shkarko versionin beta të yt-dlp</string>
<string name="adjust_audio">Modifiko Audion</string>
<string name="file_name_template">Formati i Emrit të Skedarit</string>
<string name="language">Gjuha</string>
</resources> </resources>

View file

@ -58,4 +58,16 @@
<item>0.0</item> <item>0.0</item>
<item>100.0</item> <item>100.0</item>
</array> </array>
<string-array name="language_values">
<item>en</item>
<item>de</item>
<item>fr</item>
<item>ja</item>
<item>nb</item>
<item>pl</item>
<item>ru</item>
<item>sq</item>
<item>tr</item>
</string-array>
</resources> </resources>

View file

@ -155,7 +155,6 @@
<string name="adjust_templates">Adjust templates</string> <string name="adjust_templates">Adjust templates</string>
<string name="edit_selected">Edit selected</string> <string name="edit_selected">Edit selected</string>
<string name="adjust_video">Adjust video</string> <string name="adjust_video">Adjust video</string>
<string name="remove_audio">Remove Audio</string>
<string name="schedule">Schedule</string> <string name="schedule">Schedule</string>
<string name="concurrent_downloads">Concurrent Downloads</string> <string name="concurrent_downloads">Concurrent Downloads</string>
<string name="concurrent_downloads_summary">Number of downloads executing at the same time</string> <string name="concurrent_downloads_summary">Number of downloads executing at the same time</string>
@ -168,4 +167,7 @@
<string name="update_ytdl_nightly">Download Nightly Version of yt-dlp</string> <string name="update_ytdl_nightly">Download Nightly Version of yt-dlp</string>
<string name="adjust_audio">Adjust Audio</string> <string name="adjust_audio">Adjust Audio</string>
<string name="file_name_template">Filename Template</string> <string name="file_name_template">Filename Template</string>
<string name="language">Language</string>
<string name="command_templates">Command Templates</string>
<string name="terminal">Terminal</string>
</resources> </resources>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="en"/>
<locale android:name="de"/>
<locale android:name="fr"/>
<locale android:name="ja"/>
<locale android:name="nb-NO"/>
<locale android:name="pl"/>
<locale android:name="ru"/>
<locale android:name="sq-AL"/>
<locale android:name="tr-TR"/>
</locale-config>

View file

@ -17,10 +17,11 @@
android:data="https://github.com/deniscerri/ytdlnis" /> android:data="https://github.com/deniscerri/ytdlnis" />
</Preference> </Preference>
<Preference <Preference
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24" app:icon="@drawable/ic_terminal"
app:key="run_command" app:key="run_command"
app:title="@string/custom_command"> app:title="@string/terminal">
<intent android:action="ytdlnis.page.CustomCommandActivity" /> <intent android:action="ytdlnis.page.CustomCommandActivity" />
</Preference> </Preference>
@ -32,9 +33,18 @@
<intent android:action="ytdlnis.page.DownloadLogsActivity" /> <intent android:action="ytdlnis.page.DownloadLogsActivity" />
</Preference> </Preference>
<Preference
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
app:key="command_templates"
app:allowDividerBelow="true"
app:title="@string/command_templates">
<intent android:action="ytdlnis.page.DownloadLogsActivity" />
</Preference>
<Preference <Preference
app:icon="@drawable/ic_settings" app:icon="@drawable/ic_settings"
app:key="open_settings" app:key="open_settings"
app:allowDividerAbove="true"
app:title="@string/settings"> app:title="@string/settings">
<intent android:action="ytdlnis.settings.SettingsActivity" /> <intent android:action="ytdlnis.settings.SettingsActivity" />
</Preference> </Preference>

View file

@ -1,6 +1,14 @@
<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
android:entries="@array/language_values"
android:entryValues="@array/language_values"
android:icon="@drawable/ic_language"
app:key="app_language"
app:summary="en"
app:title="@string/language" />
<PreferenceCategory android:title="@string/directories"> <PreferenceCategory android:title="@string/directories">
<Preference <Preference
app:icon="@drawable/ic_music_downloaded" app:icon="@drawable/ic_music_downloaded"