diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index dd5b3b55..67e0dae6 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -320,7 +320,7 @@ @@ -330,7 +330,7 @@ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 25fb8dc4..a6979ba3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,8 +14,10 @@ @@ -46,6 +49,7 @@ @@ -62,6 +66,7 @@ @@ -71,6 +76,7 @@ { 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) } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/Converters.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/Converters.kt index 01ecc909..ac3b999c 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/Converters.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/Converters.kt @@ -38,7 +38,8 @@ class Converters { return when(string){ "audio" -> DownloadViewModel.Type.audio "video" -> DownloadViewModel.Type.video - else -> DownloadViewModel.Type.command + "command" -> DownloadViewModel.Type.command + else -> DownloadViewModel.Type.terminal } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt index abccc1f5..f0ea706a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt @@ -52,4 +52,7 @@ interface DownloadDao { @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 + + @Query("SELECT * FROM downloads WHERE type='terminal' ORDER BY id DESC LIMIT 1") + fun getTerminalDownload() : DownloadItem } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt index 5b6db42d..a73183f2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt @@ -64,4 +64,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) { 0L } } + + fun getTerminalDownload() : Long { + return downloadDao.getTerminalDownload().id + } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt index 8b318398..81e1d28f 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt @@ -37,7 +37,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application private var bestVideoFormat : Format private var bestAudioFormat : Format enum class Type { - audio, video, command + audio, video, command, terminal } init { @@ -92,7 +92,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val downloadPath = when(type){ Type.audio -> sharedPreferences.getString("music_path", getApplication().resources.getString(R.string.music_path)) Type.video -> sharedPreferences.getString("video_path", getApplication().resources.getString(R.string.video_path)) - Type.command -> sharedPreferences.getString("command_path", getApplication().resources.getString(R.string.command_path)) + else -> sharedPreferences.getString("command_path", getApplication().resources.getString(R.string.command_path)) } 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) { Type.audio -> { 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){ bestAudioFormat } } Type.video -> { 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){ 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().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() + .setInputData(Data.Builder().putLong("id", downloadItem.id).build()) + .addTag("terminal") + .build() + val context = getApplication().applicationContext + WorkManager.getInstance(context).beginUniqueWork( + downloadItem.id.toString(), + ExistingWorkPolicy.KEEP, + workRequest + ).enqueue() + } + + + fun getTerminalDownload(): Long { + return repository.getTerminalDownload(); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/CustomCommandActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/CustomCommandActivity.kt index 48d46993..3559aaa4 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/CustomCommandActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/CustomCommandActivity.kt @@ -6,19 +6,34 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import android.util.Log +import android.view.View import android.widget.EditText import android.widget.ScrollView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity 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.database.viewmodel.DownloadViewModel import com.deniscerri.ytdlnis.service.IDownloaderService import com.deniscerri.ytdlnis.util.NotificationUtil import com.google.android.material.appbar.MaterialToolbar 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() { 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 output: TextView? = null private var input: EditText? = null @@ -27,80 +42,6 @@ class CustomCommandActivity : AppCompatActivity() { private var iDownloaderService: IDownloaderService? = null private var scrollView: ScrollView? = 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() -// 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?) { super.onCreate(savedInstanceState) @@ -115,19 +56,18 @@ class CustomCommandActivity : AppCompatActivity() { input!!.requestFocus() fab = findViewById(R.id.command_fab) fab!!.setOnClickListener { - if (isStoragePermissionGranted) { - startDownloadService( - input!!.text.toString(), - NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID - ) - } + startDownload( + input!!.text.toString() + ) } cancelFab = findViewById(R.id.cancel_command_fab) cancelFab!!.setOnClickListener { - cancelDownloadService() - swapFabs() + cancelDownload() input!!.isEnabled = true } + downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] + notificationUtil = NotificationUtil(this) + workManager = WorkManager.getInstance(this) 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 startDownloadService(command: String?, id: Int) { + private fun startDownload(command: String?) { if (isDownloadServiceRunning) return - //val serviceIntent = Intent(context, DownloaderService::class.java) -// serviceIntent.putExtra("command", command) -// serviceIntent.putExtra("id", id) - //context!!.applicationContext.bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE) - } - - fun stopDownloadService() { -// if (!isDownloadServiceRunning) return -// iDownloaderService!!.removeActivity(this) -// context!!.applicationContext.unbindService(serviceConnection) -// downloaderService!!.stopForeground(true) -// downloaderService!!.stopSelf() -// isDownloadServiceRunning = false - } + downloadViewModel.startTerminalDownload(command!!) + output!!.text = "" + workManager.getWorkInfosByTagLiveData("terminal") + .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 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 + private fun cancelDownload() { + lifecycleScope.launch { + val id = withContext(Dispatchers.IO){ downloadViewModel.getTerminalDownload(); } + YoutubeDL.getInstance().destroyProcessById(id.toString()) + WorkManager.getInstance(this@CustomCommandActivity).cancelUniqueWork(id.toString()) + notificationUtil.cancelDownloadNotification(id.toInt()) } + } companion object { private const val TAG = "CustomCommandActivity" diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt index 076deca5..4df35d09 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt @@ -72,7 +72,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri tabLayout.selectTab(tabLayout.getTabAt(1)) viewPager2.setCurrentItem(1, false) } - Type.command -> { + else -> { tabLayout.selectTab(tabLayout.getTabAt(2)) viewPager2.setCurrentItem(2, false) } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt index 44f98bce..c892d0cc 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadBottomSheetDialog.kt @@ -73,7 +73,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val tabLayout.selectTab(tabLayout.getTabAt(1)) viewPager2.setCurrentItem(1, false) } - Type.command -> { + else -> { tabLayout.selectTab(tabLayout.getTabAt(2)) viewPager2.setCurrentItem(2, false) } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsActivity.kt index db19d870..0105d2c2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsActivity.kt @@ -1,12 +1,16 @@ package com.deniscerri.ytdlnis.ui.settings import android.content.Context +import android.content.res.Configuration +import android.os.Build import android.os.Bundle -import android.view.View +import android.os.LocaleList import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentManager import com.deniscerri.ytdlnis.R import com.google.android.material.appbar.MaterialToolbar +import java.util.* + class SettingsActivity : AppCompatActivity() { private var fm: FragmentManager? = null @@ -23,4 +27,34 @@ class SettingsActivity : AppCompatActivity() { .replace(R.id.settings_frame_layout, SettingsFragment()) .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() + + } + } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsFragment.kt index 01d0383b..a2627dde 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/settings/SettingsFragment.kt @@ -2,17 +2,23 @@ package com.deniscerri.ytdlnis.ui.settings import android.app.Activity import android.content.Intent +import android.content.res.Configuration +import android.os.Build import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat import androidx.preference.* import com.deniscerri.ytdlnis.BuildConfig import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.UpdateUtil +import java.util.* class SettingsFragment : PreferenceFragmentCompat() { + private var language: ListPreference? = null private var musicPath: Preference? = null private var videoPath: Preference? = null private var commandPath: Preference? = null @@ -51,6 +57,7 @@ class SettingsFragment : PreferenceFragmentCompat() { val preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) val editor = preferences.edit() + language = findPreference("app_language") musicPath = findPreference("music_path") videoPath = findPreference("video_path") commandPath = findPreference("command_path") @@ -76,6 +83,20 @@ class SettingsFragment : PreferenceFragmentCompat() { updateApp = findPreference("update_app") version = findPreference("version") 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() + 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()) { editor.putString("music_path", getString(R.string.music_path)) } @@ -111,6 +132,17 @@ class SettingsFragment : PreferenceFragmentCompat() { val preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) 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!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt index b37751dc..0a4abac1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -67,13 +67,13 @@ class DownloadWorker( val url = downloadItem.url - val request = YoutubeDLRequest(url) + var request = YoutubeDLRequest(url) val type = downloadItem.type 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}") - val tempFileDir = File(tempFolder.toString()) + var tempFileDir = File(tempFolder.toString()) tempFileDir.delete() 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 { diff --git a/app/src/main/res/drawable/ic_language.xml b/app/src/main/res/drawable/ic_language.xml new file mode 100644 index 00000000..3ab89594 --- /dev/null +++ b/app/src/main/res/drawable/ic_language.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_terminal.xml b/app/src/main/res/drawable/ic_terminal.xml new file mode 100644 index 00000000..8cdaf5ac --- /dev/null +++ b/app/src/main/res/drawable/ic_terminal.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_custom_command.xml b/app/src/main/res/layout/activity_custom_command.xml index 36a56ffb..ab3c1ad6 100644 --- a/app/src/main/res/layout/activity_custom_command.xml +++ b/app/src/main/res/layout/activity_custom_command.xml @@ -64,8 +64,7 @@ diff --git a/app/src/main/res/values-sq-rAL/strings.xml b/app/src/main/res/values-sq-rAL/strings.xml index 60f81317..95df2c12 100644 --- a/app/src/main/res/values-sq-rAL/strings.xml +++ b/app/src/main/res/values-sq-rAL/strings.xml @@ -142,4 +142,22 @@ Pjesë Shtesë Përkujtuesit e Abonimit Zgjidh Filtrimin e SponsorBlock + Direktoria + Shabllon i ri + Cakto Shabllonët + Redakto të zgjedhurin + Modifiko Videon + Planifiko + Shkarkimet e njëkohësishme + Numri i shkarkimeve qe do ekzekutohen në të njëjtën kohë + Siç është + Formati + Shablloni + Shënimet + Komandat + Data e shtuar + Shkarko versionin beta të yt-dlp + Modifiko Audion + Formati i Emrit të Skedarit + Gjuha \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9dc5fa78..72a4894e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -58,4 +58,16 @@ 0.0 100.0 + + + en + de + fr + ja + nb + pl + ru + sq + tr + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bcd0e529..ce2d061c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -155,7 +155,6 @@ Adjust templates Edit selected Adjust video - Remove Audio Schedule Concurrent Downloads Number of downloads executing at the same time @@ -168,4 +167,7 @@ Download Nightly Version of yt-dlp Adjust Audio Filename Template + Language + Command Templates + Terminal \ No newline at end of file diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml new file mode 100644 index 00000000..d1a106b9 --- /dev/null +++ b/app/src/main/res/xml/locales_config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/more_preferences.xml b/app/src/main/res/xml/more_preferences.xml index 854153fc..7e35c27f 100644 --- a/app/src/main/res/xml/more_preferences.xml +++ b/app/src/main/res/xml/more_preferences.xml @@ -17,10 +17,11 @@ android:data="https://github.com/deniscerri/ytdlnis" /> + + app:title="@string/terminal"> @@ -32,9 +33,18 @@ + + + + diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 914edbfe..53843853 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -1,6 +1,14 @@ + +