Merge branch 'libre-tube:master' into master

This commit is contained in:
ձռօռყ_սռĸռօառ 2022-06-26 15:26:13 +05:30 committed by GitHub
commit 2f09157df2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 412 additions and 115 deletions

View File

@ -55,35 +55,34 @@ android {
} }
dependencies { dependencies {
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1' //debugImplementation libs.square.leakcanary
implementation 'androidx.appcompat:appcompat:1.4.1' implementation libs.androidx.appcompat
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation libs.androidx.constraintlayout
implementation 'com.google.android.material:material:1.6.0' implementation libs.androidx.legacySupport
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' implementation libs.androidx.multidex
implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' implementation libs.androidx.navigation.fragment
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation libs.androidx.navigation.ui
implementation 'androidx.preference:preference-ktx:1.2.0' implementation libs.androidx.preference
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation libs.androidx.test.junit
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation libs.androidx.test.espressoCore
implementation 'com.squareup.picasso:picasso:2.8' implementation libs.circleimageview
implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'com.google.android.exoplayer:exoplayer:2.17.1'
implementation 'com.google.android.exoplayer:extension-mediasession:2.17.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation libs.material
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0' implementation libs.exoplayer
//do not update jackson annotations! it does not supports <api26 implementation(libs.exoplayer.extension.cronet) { exclude group: 'com.google.android.gms' }
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.3' implementation libs.exoplayer.extension.mediasession
implementation 'com.arthenica:ffmpeg-kit-min:4.5.1.LTS' implementation libs.square.picasso
implementation libs.square.retrofit
implementation libs.square.retrofit.converterJackson
// Do not update jackson annotations! It does not supports < API 26.
implementation libs.jacksonAnnotations
implementation libs.mobileffmpeg
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' coreLibraryDesugaring libs.desugaring
implementation('com.google.android.exoplayer:extension-cronet:2.17.1') { exclude group: 'com.google.android.gms' } implementation libs.cronet.embedded
implementation 'org.chromium.net:cronet-embedded:101.4951.41'
} }

View File

@ -17,8 +17,8 @@ import android.os.IBinder
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.preference.PreferenceManager
import com.arthenica.ffmpegkit.FFmpegKit import com.arthenica.ffmpegkit.FFmpegKit
import com.github.libretube.util.PreferenceHelper
import java.io.File import java.io.File
var IS_DOWNLOAD_RUNNING = false var IS_DOWNLOAD_RUNNING = false
@ -48,8 +48,7 @@ class DownloadService : Service() {
videoUrl = intent.getStringExtra("videoUrl")!! videoUrl = intent.getStringExtra("videoUrl")!!
audioUrl = intent.getStringExtra("audioUrl")!! audioUrl = intent.getStringExtra("audioUrl")!!
duration = intent.getIntExtra("duration", 1) duration = intent.getIntExtra("duration", 1)
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) extension = PreferenceHelper.getString(this, "video_format", ".mp4")!!
extension = sharedPreferences.getString("video_format", ".mp4")!!
downloadType = if (audioUrl != "" && videoUrl != "") "mux" downloadType = if (audioUrl != "" && videoUrl != "") "mux"
else if (audioUrl != "") "audio" else if (audioUrl != "") "audio"
else if (videoUrl != "") "video" else if (videoUrl != "") "video"
@ -83,9 +82,8 @@ class DownloadService : Service() {
Log.e(TAG, "Directory already have") Log.e(TAG, "Directory already have")
} }
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) val downloadLocationPref = PreferenceHelper.getString(this, "download_location", "")
val downloadLocationPref = sharedPreferences.getString("download_location", "") val folderName = PreferenceHelper.getString(this, "download_folder", "LibreTube")
val folderName = sharedPreferences.getString("download_folder", "")
val location = when (downloadLocationPref) { val location = when (downloadLocationPref) {
"downloads" -> Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS) "downloads" -> Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS)

View File

@ -0,0 +1,90 @@
package com.github.libretube.dialogs
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
import com.github.libretube.obj.DeleteUserRequest
import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.RetrofitInstance
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class DeleteAccountDialog : DialogFragment() {
private val TAG = "DeleteAccountDialog"
lateinit var username: EditText
lateinit var password: EditText
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = MaterialAlertDialogBuilder(it)
val inflater = requireActivity().layoutInflater
val view = inflater.inflate(R.layout.dialog_delete_account, null)
view.findViewById<Button>(R.id.cancel_button).setOnClickListener {
dialog?.dismiss()
}
password = view.findViewById(R.id.delete_password)
view.findViewById<Button>(R.id.delete_account_confirm).setOnClickListener {
if (password.text.toString() != "") {
deleteAccount(password.text.toString())
} else {
Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show()
}
}
val typedValue = TypedValue()
this.requireActivity().theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true)
val hexColor = String.format("#%06X", (0xFFFFFF and typedValue.data))
val appName = HtmlCompat.fromHtml(
"Libre<span style='color:$hexColor';>Tube</span>",
HtmlCompat.FROM_HTML_MODE_COMPACT
)
view.findViewById<TextView>(R.id.title).text = appName
builder.setView(view)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
private fun deleteAccount(password: String) {
fun run() {
lifecycleScope.launchWhenCreated {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")!!
try {
RetrofitInstance.api.deleteAccount(token, DeleteUserRequest(password))
} catch (e: Exception) {
Log.e(TAG, e.toString())
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
return@launchWhenCreated
}
requireMainActivityRestart = true
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
logout()
dialog?.dismiss()
}
}
run()
}
private fun logout() {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")
if (token != "") {
with(sharedPref!!.edit()) {
putString("token", "")
apply()
}
}
}
}

View File

@ -9,12 +9,12 @@ import android.widget.ProgressBar
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.util.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
@ -41,8 +41,8 @@ class Home : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerView = view.findViewById<RecyclerView>(R.id.recview) val recyclerView = view.findViewById<RecyclerView>(R.id.recview)
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) val grid = PreferenceHelper.getString(
val grid = sharedPreferences.getString( requireContext(),
"grid", "grid",
resources.getInteger(R.integer.grid_items).toString() resources.getInteger(R.integer.grid_items).toString()
)!! )!!
@ -61,9 +61,8 @@ class Home : Fragment() {
fun run() { fun run() {
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
val sharedPreferences = val region = PreferenceHelper.getString(requireContext(), "region", "US")
PreferenceManager.getDefaultSharedPreferences(requireContext()) RetrofitInstance.api.getTrending(region!!)
RetrofitInstance.api.getTrending(sharedPreferences.getString("region", "US")!!)
} catch (e: IOException) { } catch (e: IOException) {
println(e) println(e)
Log.e(TAG, "IOException, you might not have internet connection") Log.e(TAG, "IOException, you might not have internet connection")

View File

@ -58,6 +58,7 @@ import com.github.libretube.obj.Subscribe
import com.github.libretube.preferences.SponsorBlockSettings import com.github.libretube.preferences.SponsorBlockSettings
import com.github.libretube.util.CronetHelper import com.github.libretube.util.CronetHelper
import com.github.libretube.util.DescriptionAdapter import com.github.libretube.util.DescriptionAdapter
import com.github.libretube.util.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.formatShort import com.github.libretube.util.formatShort
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
@ -347,9 +348,11 @@ class PlayerFragment : Fragment() {
override fun onPause() { override fun onPause() {
// pause the player if the screen is turned off // pause the player if the screen is turned off
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) val pausePlayerOnScreenOffEnabled = PreferenceHelper.getBoolean(
val pausePlayerOnScreenOffEnabled = sharedPreferences requireContext(),
.getBoolean("pause_screen_off", false) "pause_screen_off",
false
)
// check whether the screen is on // check whether the screen is on
val pm = context?.getSystemService(Context.POWER_SERVICE) as PowerManager val pm = context?.getSystemService(Context.POWER_SERVICE) as PowerManager
@ -717,11 +720,8 @@ class PlayerFragment : Fragment() {
} }
private fun setResolutionAndSubtitles(view: View, response: Streams) { private fun setResolutionAndSubtitles(view: View, response: Streams) {
val sharedPreferences = val videoFormatPreference = PreferenceHelper.getString(requireContext(), "player_video_format", "WEBM")
PreferenceManager.getDefaultSharedPreferences(requireContext()) val defres = PreferenceHelper.getString(requireContext(), "default_res", "")!!
val videoFormatPreference = sharedPreferences.getString("player_video_format", "WEBM")
val defres = sharedPreferences.getString("default_res", "")!!
val qualityText = view.findViewById<TextView>(R.id.quality_text) val qualityText = view.findViewById<TextView>(R.id.quality_text)
val qualitySelect = view.findViewById<ImageButton>(R.id.quality_select) val qualitySelect = view.findViewById<ImageButton>(R.id.quality_select)

View File

@ -27,6 +27,7 @@ import com.github.libretube.adapters.SearchAdapter
import com.github.libretube.adapters.SearchHistoryAdapter import com.github.libretube.adapters.SearchHistoryAdapter
import com.github.libretube.adapters.SearchSuggestionsAdapter import com.github.libretube.adapters.SearchSuggestionsAdapter
import com.github.libretube.hideKeyboard import com.github.libretube.hideKeyboard
import com.github.libretube.util.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -276,7 +277,7 @@ class SearchFragment : Fragment() {
private fun addToHistory(query: String) { private fun addToHistory(query: String) {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val searchHistoryEnabled = sharedPreferences.getBoolean("search_history_toggle", true) val searchHistoryEnabled = PreferenceHelper.getBoolean(requireContext(), "search_history_toggle", true)
if (searchHistoryEnabled) { if (searchHistoryEnabled) {
var historyList = getHistory() var historyList = getHistory()

View File

@ -0,0 +1,5 @@
package com.github.libretube.obj
data class DeleteUserRequest(
var password: String? = null
)

View File

@ -5,9 +5,9 @@ import android.os.Bundle
import android.widget.TextView import android.widget.TextView
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.requireMainActivityRestart import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.PreferenceHelper
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
class AdvancedSettings : PreferenceFragmentCompat() { class AdvancedSettings : PreferenceFragmentCompat() {
@ -21,9 +21,7 @@ class AdvancedSettings : PreferenceFragmentCompat() {
val clearHistory = findPreference<Preference>("clear_history") val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener { clearHistory?.setOnPreferenceClickListener {
val sharedPreferences = PreferenceHelper.removePreference(requireContext(), "search_history")
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().remove("search_history").commit()
true true
} }
@ -38,9 +36,7 @@ class AdvancedSettings : PreferenceFragmentCompat() {
MaterialAlertDialogBuilder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setPositiveButton(R.string.reset) { _, _ -> .setPositiveButton(R.string.reset) { _, _ ->
// clear default preferences // clear default preferences
val sharedPreferences = PreferenceHelper.clearPreferences(requireContext())
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().clear().commit()
// clear login token // clear login token
val sharedPrefToken = val sharedPrefToken =

View File

@ -22,8 +22,10 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.dialogs.CustomInstanceDialog import com.github.libretube.dialogs.CustomInstanceDialog
import com.github.libretube.dialogs.DeleteAccountDialog
import com.github.libretube.dialogs.LoginDialog import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.requireMainActivityRestart import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.PreferenceHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import org.json.JSONObject import org.json.JSONObject
import org.json.JSONTokener import org.json.JSONTokener
@ -133,11 +135,9 @@ class InstanceSettings : PreferenceFragmentCompat() {
val clearCustomInstances = findPreference<Preference>("clearCustomInstances") val clearCustomInstances = findPreference<Preference>("clearCustomInstances")
clearCustomInstances?.setOnPreferenceClickListener { clearCustomInstances?.setOnPreferenceClickListener {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) PreferenceHelper.removePreference(requireContext(), "custom_instances_name")
sharedPreferences.edit() PreferenceHelper.removePreference(requireContext(), "custom_instances_url")
.remove("custom_instances_name") PreferenceHelper.removePreference(requireContext(), "custom_instances_frontend_url")
.remove("custom_instances_url")
.commit()
activity?.recreate() activity?.recreate()
true true
} }
@ -150,10 +150,23 @@ class InstanceSettings : PreferenceFragmentCompat() {
true true
} }
val deleteAccount = findPreference<Preference>("delete_account")
deleteAccount?.setOnPreferenceClickListener {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")
if (token != "") {
val newFragment = DeleteAccountDialog()
newFragment.show(childFragmentManager, "DeleteAccountDialog")
} else {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
}
true
}
val importFromYt = findPreference<Preference>("import_from_yt") val importFromYt = findPreference<Preference>("import_from_yt")
importFromYt?.setOnPreferenceClickListener { importFromYt?.setOnPreferenceClickListener {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE) val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")!! val token = sharedPref?.getString("token", "")
// check StorageAccess // check StorageAccess
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Log.d("myz", "" + Build.VERSION.SDK_INT) Log.d("myz", "" + Build.VERSION.SDK_INT)

View File

@ -2,14 +2,12 @@ package com.github.libretube.util
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import androidx.preference.PreferenceManager
import java.util.* import java.util.*
class LocaleHelper { class LocaleHelper {
fun updateLanguage(context: Context) { fun updateLanguage(context: Context) {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) val languageName = PreferenceHelper.getString(context, "language", "en")
val languageName = sharedPreferences.getString("language", "sys")
if (languageName != "") { if (languageName != "") {
setLanguage(context, languageName!!) setLanguage(context, languageName!!)
} }

View File

@ -2,6 +2,7 @@ package com.github.libretube.util
import com.github.libretube.obj.Channel import com.github.libretube.obj.Channel
import com.github.libretube.obj.CommentsPage import com.github.libretube.obj.CommentsPage
import com.github.libretube.obj.DeleteUserRequest
import com.github.libretube.obj.Instances import com.github.libretube.obj.Instances
import com.github.libretube.obj.Login import com.github.libretube.obj.Login
import com.github.libretube.obj.Message import com.github.libretube.obj.Message
@ -86,6 +87,12 @@ interface PipedApi {
@POST("register") @POST("register")
suspend fun register(@Body login: Login): Token suspend fun register(@Body login: Login): Token
@POST("user/delete")
suspend fun deleteAccount(
@Header("Authorization") token: String,
@Body password: DeleteUserRequest
)
@GET("feed") @GET("feed")
suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem> suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem>

View File

@ -0,0 +1,70 @@
package com.github.libretube.util
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
object PreferenceHelper {
fun setString(context: Context, key: String?, value: String?) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.putString(key, value)
editor.apply()
}
fun setInt(context: Context, key: String?, value: Int) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.putInt(key, value)
editor.apply()
}
fun setLong(context: Context, key: String?, value: Long) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.putLong(key, value)
editor.apply()
}
fun setBoolean(context: Context, key: String?, value: Boolean) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.putBoolean(key, value)
editor.apply()
}
fun getString(context: Context, key: String?, defValue: String?): String? {
val settings: SharedPreferences = getDefaultSharedPreferences(context)
return settings.getString(key, defValue)
}
fun getInt(context: Context, key: String?, defValue: Int): Int {
val settings: SharedPreferences = getDefaultSharedPreferences(context)
return settings.getInt(key, defValue)
}
fun getLong(context: Context, key: String?, defValue: Long): Long {
val settings: SharedPreferences = getDefaultSharedPreferences(context)
return settings.getLong(key, defValue)
}
fun getBoolean(context: Context, key: String?, defValue: Boolean): Boolean {
val settings: SharedPreferences = getDefaultSharedPreferences(context)
return settings.getBoolean(key, defValue)
}
fun clearPreferences(context: Context) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.clear()
editor.commit()
}
fun removePreference(context: Context, value: String?) {
val editor = getDefaultSharedPreferencesEditor(context)
editor.remove(value)
editor.commit()
}
private fun getDefaultSharedPreferences(context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context)
}
private fun getDefaultSharedPreferencesEditor(context: Context): SharedPreferences.Editor {
return getDefaultSharedPreferences(context).edit()
}
}

View File

@ -7,7 +7,6 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import com.github.libretube.R import com.github.libretube.R
class ThemeHelper { class ThemeHelper {
@ -17,10 +16,8 @@ class ThemeHelper {
updateThemeMode(context) updateThemeMode(context)
} }
fun updateAccentColor(context: Context) { private fun updateAccentColor(context: Context) {
val colorAccent = when (PreferenceHelper.getString(context, "accent_color", "red")) {
PreferenceManager.getDefaultSharedPreferences(context).getString("accent_color", "red")
when (colorAccent) {
"my" -> context.setTheme(R.style.Theme_MY) "my" -> context.setTheme(R.style.Theme_MY)
"red" -> context.setTheme(R.style.Theme_Red) "red" -> context.setTheme(R.style.Theme_Red)
"blue" -> context.setTheme(R.style.Theme_Blue) "blue" -> context.setTheme(R.style.Theme_Blue)
@ -30,10 +27,8 @@ class ThemeHelper {
} }
} }
fun updateThemeMode(context: Context) { private fun updateThemeMode(context: Context) {
val themeMode = when (PreferenceHelper.getString(context, "theme_togglee", "A")) {
PreferenceManager.getDefaultSharedPreferences(context).getString("theme_togglee", "A")
when (themeMode) {
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) "A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) "L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) "D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)

View File

@ -5,15 +5,17 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:paddingVertical="5dp" >
<ImageButton <ImageButton
android:id="@+id/back_imageButton" android:id="@+id/back_imageButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="6dp" android:layout_marginLeft="15dp"
android:layout_marginVertical="10dp" android:layout_marginVertical="10dp"
android:backgroundTint="@android:color/transparent" android:backgroundTint="@android:color/transparent"
android:background="?android:selectableItemBackgroundBorderless"
android:src="@drawable/ic_arrow_back" /> android:src="@drawable/ic_arrow_back" />
<TextView <TextView
@ -21,7 +23,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/settings" android:text="@string/settings"
android:layout_marginLeft="14dp" android:layout_marginLeft="25dp"
android:textSize="20sp" android:textSize="20sp"
android:layout_gravity="center" /> android:layout_gravity="center" />

View File

@ -4,7 +4,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -24,6 +23,7 @@
<Button <Button
android:id="@+id/addToPlaylist" android:id="@+id/addToPlaylist"
android:text="@string/addToPlaylist" android:text="@string/addToPlaylist"
style="@style/CustomDialogButton" /> style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -40,7 +40,8 @@
<Button <Button
android:id="@+id/create_new_playlist" android:id="@+id/create_new_playlist"
android:text="@string/createPlaylist" android:text="@string/createPlaylist"
style="@style/CustomDialogButton" /> style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -61,7 +61,8 @@
<Button <Button
android:id="@+id/addInstance" android:id="@+id/addInstance"
android:text="@string/addInstance" android:text="@string/addInstance"
style="@style/CustomDialogButton" /> style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:gravity="center"
android:layout_margin="10dp"
android:textSize="20sp" />
<com.google.android.material.textfield.TextInputLayout style="@style/CustomDialogTextInputLayout">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/delete_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password"
android:inputType="textPassword"
android:padding="12dp" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="right">
<Button
android:id="@+id/cancel_button"
android:text="@string/cancel"
style="@style/CustomDialogButton" />
<Button
android:id="@+id/delete_account_confirm"
android:text="@string/deleteAccount"
style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout>
</LinearLayout>

View File

@ -29,6 +29,7 @@
<Button <Button
android:id="@+id/download" android:id="@+id/download"
android:text="@string/download" android:text="@string/download"
style="@style/CustomDialogButton" /> style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -51,7 +51,8 @@
<Button <Button
android:id="@+id/login" android:id="@+id/login"
android:text="@string/login" android:text="@string/login"
style="@style/CustomDialogButton" /> style="@style/CustomDialogButton"
android:layout_marginRight="16dp"/>
</LinearLayout> </LinearLayout>

View File

@ -26,8 +26,6 @@
android:textSize="27sp" android:textSize="27sp"
android:textStyle="bold" /> android:textStyle="bold" />
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/website" android:id="@+id/website"
style="@style/AboutItem"> style="@style/AboutItem">
@ -45,8 +43,6 @@
</LinearLayout> </LinearLayout>
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/contributing" android:id="@+id/contributing"
style="@style/AboutItem"> style="@style/AboutItem">
@ -64,8 +60,6 @@
</LinearLayout> </LinearLayout>
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/authors" android:id="@+id/authors"
style="@style/AboutItem"> style="@style/AboutItem">
@ -83,8 +77,6 @@
</LinearLayout> </LinearLayout>
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/piped" android:id="@+id/piped"
style="@style/AboutItem"> style="@style/AboutItem">
@ -102,8 +94,6 @@
</LinearLayout> </LinearLayout>
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/donate" android:id="@+id/donate"
style="@style/AboutItem"> style="@style/AboutItem">
@ -121,8 +111,6 @@
</LinearLayout> </LinearLayout>
<View style="@style/HorizontalLine" />
<LinearLayout <LinearLayout
android:id="@+id/license" android:id="@+id/license"
style="@style/AboutItem"> style="@style/AboutItem">

View File

@ -31,19 +31,19 @@
<string name="defres">Videon oletustarkkuus</string> <string name="defres">Videon oletustarkkuus</string>
<string name="grid">Valitse ruudukon sarakkeet</string> <string name="grid">Valitse ruudukon sarakkeet</string>
<string name="app_theme">Sovelluksen teema</string> <string name="app_theme">Sovelluksen teema</string>
<string name="success">Onnistui!</string> <string name="success">Onnistui.</string>
<string name="about">Tietoja</string> <string name="about">Tietoja</string>
<string name="choose_quality_dialog">Valitse laatu:</string> <string name="choose_quality_dialog">Valitse laatu:</string>
<string name="share">Jaa</string> <string name="share">Jaa</string>
<string name="customInstance">Lisää mukautettu instanssi</string> <string name="customInstance">Lisää mukautettu instanssi</string>
<string name="subscribeIsEmpty">Tilaa ensin joitakin kanavia.</string> <string name="subscribeIsEmpty">Tilaa ensin joitakin kanavia.</string>
<string name="dlisinprogress">Toinen lataus on jo käynnissä, odota kunnes se on valmis.</string> <string name="dlisinprogress">Odota kunnes kaikki lataukset ovat valmiita.</string>
<string name="cannotDownload">Ei voi ladata tätä videota.</string> <string name="cannotDownload">Ei voi ladata tätä videota.</string>
<string name="vlc">Avaa VLC:ssä</string> <string name="vlc">Avaa VLC:ssä</string>
<string name="unknown_error">Verkkovirhe.</string> <string name="unknown_error">Verkkovirhe.</string>
<string name="import_from_yt">Tuo tilaukset YouTubesta</string> <string name="import_from_yt">Tuo tilaukset YouTubesta</string>
<string name="error">Jokin meni pieleen.</string> <string name="error">Jokin meni pieleen.</string>
<string name="playlistCreated">Soittolista luotu!</string> <string name="playlistCreated">Soittolista luotu.</string>
<string name="emptyList">Täällä ei ole mitään.</string> <string name="emptyList">Täällä ei ole mitään.</string>
<string name="deletePlaylist">Poista soittolista</string> <string name="deletePlaylist">Poista soittolista</string>
<string name="areYouSure">Haluatko varmasti poistaa tämän soittolistan\?</string> <string name="areYouSure">Haluatko varmasti poistaa tämän soittolistan\?</string>
@ -57,11 +57,11 @@
<string name="subscriptions">Tilaukset</string> <string name="subscriptions">Tilaukset</string>
<string name="library">Kirjasto</string> <string name="library">Kirjasto</string>
<string name="videos">Videot</string> <string name="videos">Videot</string>
<string name="changeLanguage">Vaihda kieltä</string> <string name="changeLanguage">Kieli</string>
<string name="systemLanguage">Järjestelmän kieli</string> <string name="systemLanguage">Järjestelmän kieli</string>
<string name="darkTheme">Tumma teema</string> <string name="darkTheme">Tumma</string>
<string name="systemDefault">Järjestelmän oletusarvo</string> <string name="systemDefault">Järjestelmän oletusarvo</string>
<string name="lightTheme">Vaalea teema</string> <string name="lightTheme">Vaalea</string>
<string name="subscribers">%1$s tilaajaa</string> <string name="subscribers">%1$s tilaajaa</string>
<string name="comments">Kommentit</string> <string name="comments">Kommentit</string>
<string name="noInternet">Ei Internet-yhteyttä</string> <string name="noInternet">Ei Internet-yhteyttä</string>
@ -104,4 +104,13 @@
<string name="appearance_summary">Tee sovelluksesta haluamasi näköinen.</string> <string name="appearance_summary">Tee sovelluksesta haluamasi näköinen.</string>
<string name="advanced">Edistynyt</string> <string name="advanced">Edistynyt</string>
<string name="live">Live</string> <string name="live">Live</string>
<string name="music_playlists">YT Musiikki Soittolistat</string>
<string name="segment_skipped">Ohitettu segmentti</string>
<string name="category_sponsor">Sponsori</string>
<string name="category_selfpromo">Ei maksettu/itsensä mainostaminen</string>
<string name="category_segments">Segmentit</string>
<string name="category_intro">Väliaika/Intro animaatio</string>
<string name="sponsorblock_state">Päällä</string>
<string name="category_selfpromo_description">Samankaltainen kuin \"sponsori\" lukuunottamatta ei maksettua tai itsensä mainostamista. Tämä sisältää osiot, jotka sisältävät kauppatavaraa, lahjoituksia tai tietoa keiden kanssa he tekivät yhteistyötä.</string>
<string name="category_interaction">Vuorovaikutus muistutus (tykkäys ja tilaus)</string>
</resources> </resources>

View File

@ -142,7 +142,7 @@
<string name="playback_speed">기본 재생 속도</string> <string name="playback_speed">기본 재생 속도</string>
<string name="advanced">고급</string> <string name="advanced">고급</string>
<string name="player">오디오 및 비디오</string> <string name="player">오디오 및 비디오</string>
<string name="advanced_summary">플레이어, 다운로드, 기록</string> <string name="advanced_summary">다운로드, 기록</string>
<string name="live">실시간</string> <string name="live">실시간</string>
<string name="download_folder">이름</string> <string name="download_folder">이름</string>
<string name="sdcard">SD 카드</string> <string name="sdcard">SD 카드</string>
@ -175,7 +175,7 @@
<string name="buffering_goal_summary">최대 버퍼링할 비디오의 시간(초)입니다.</string> <string name="buffering_goal_summary">최대 버퍼링할 비디오의 시간(초)입니다.</string>
<string name="playerVideoFormat">플레이어의 비디오 형식</string> <string name="playerVideoFormat">플레이어의 비디오 형식</string>
<string name="buffering_goal">사전 로딩</string> <string name="buffering_goal">사전 로딩</string>
<string name="legacyIcon">레거시</string> <string name="legacyIcon">잃어버린 레거시</string>
<string name="torchIcon">세련된 등불</string> <string name="torchIcon">세련된 등불</string>
<string name="fireIcon">멋진 불</string> <string name="fireIcon">멋진 불</string>
<string name="category_filler">사족/농담</string> <string name="category_filler">사족/농담</string>
@ -199,4 +199,5 @@
<string name="pauseOnScreenOff">자동 일시중지</string> <string name="pauseOnScreenOff">자동 일시중지</string>
<string name="pauseOnScreenOff_summary">화면이 꺼질 경우 동영상 재생을 일시중지합니다.</string> <string name="pauseOnScreenOff_summary">화면이 꺼질 경우 동영상 재생을 일시중지합니다.</string>
<string name="clonePlaylist">재생목록 복제</string> <string name="clonePlaylist">재생목록 복제</string>
<string name="instance_frontend_url">인스턴스 프론트엔드에 대한 URL</string>
</resources> </resources>

View File

@ -43,7 +43,7 @@
<string name="unknown_error">Network error.</string> <string name="unknown_error">Network error.</string>
<string name="error">Something went wrong.</string> <string name="error">Something went wrong.</string>
<string name="empty">You have to enter a username and password.</string> <string name="empty">You have to enter a username and password.</string>
<string name="notgmail">This is for a LibreTube account.</string> <string name="notgmail">This is for a Piped account.</string>
<string name="defres">Default video resolution</string> <string name="defres">Default video resolution</string>
<string name="grid">Grid columns</string> <string name="grid">Grid columns</string>
<string name="emptyList">Nothing here.</string> <string name="emptyList">Nothing here.</string>
@ -203,4 +203,8 @@
<string name="clonePlaylist">Clone playlist</string> <string name="clonePlaylist">Clone playlist</string>
<string name="reset">Restore defaults</string> <string name="reset">Restore defaults</string>
<string name="reset_message">Are you sure? This will log you out and reset all your settings!</string> <string name="reset_message">Are you sure? This will log you out and reset all your settings!</string>
<string name="deleteAccount">Delete account</string>
<string name="deleteAccount_summary">Delete your Piped account</string>
<string name="account">Account</string>
<string name="restore">Restore</string>
</resources> </resources>

View File

@ -44,31 +44,31 @@
</style> </style>
<style name="CustomDialogButton"> <style name="CustomDialogButton" parent="@style/Widget.Material3.Button.TextButton">
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">right</item> <item name="android:layout_gravity">right</item>
<item name="android:layout_marginRight">16dp</item>
<item name="android:layout_marginBottom">8dp</item> <item name="android:layout_marginBottom">8dp</item>
<item name="android:padding">8dp</item> <item name="android:padding">8dp</item>
<item name="android:textSize">14sp</item>
<item name="android:backgroundTint">@android:color/transparent</item>
<item name="android:textColor">?attr/colorPrimary</item>
</style> </style>
<style name="CustomDialogTextInputLayout" parent="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"> <style name="CustomDialogTextInputLayout" parent="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="hintEnabled">false</item> <item name="hintEnabled">false</item>
<item name="android:layout_marginLeft">10dp</item> <item name="android:layout_marginLeft">15dp</item>
<item name="android:layout_marginRight">10dp</item> <item name="android:layout_marginRight">15dp</item>
<item name="android:layout_marginTop">16dp</item> <item name="android:layout_marginTop">10dp</item>
<item name="android:layout_marginBottom">4dp</item> <item name="android:layout_marginBottom">5dp</item>
<item name="boxCornerRadiusBottomStart">15dp</item> <item name="boxCornerRadiusBottomStart">15dp</item>
<item name="boxCornerRadiusBottomEnd">15dp</item> <item name="boxCornerRadiusBottomEnd">15dp</item>
<item name="boxCornerRadiusTopEnd">15dp</item> <item name="boxCornerRadiusTopEnd">15dp</item>
<item name="boxCornerRadiusTopStart">15dp</item> <item name="boxCornerRadiusTopStart">15dp</item>
</style> </style>
</resources> </resources>

View File

@ -13,15 +13,19 @@
app:title="@string/instances" /> app:title="@string/instances" />
<Preference <Preference
android:icon="@drawable/ic_add_instance"
app:key="customInstance" app:key="customInstance"
app:title="@string/customInstance"
app:summary="@string/customInstance_summary" app:summary="@string/customInstance_summary"
android:icon="@drawable/ic_add_instance" /> app:title="@string/customInstance" />
<Preference <Preference
android:icon="@drawable/ic_trash"
app:key="clearCustomInstances" app:key="clearCustomInstances"
app:title="@string/clear_customInstances" app:title="@string/clear_customInstances" />
android:icon="@drawable/ic_trash" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/account">
<Preference <Preference
android:icon="@drawable/ic_login_filled" android:icon="@drawable/ic_login_filled"
@ -29,6 +33,16 @@
app:key="login_register" app:key="login_register"
app:title="@string/login_register" /> app:title="@string/login_register" />
<Preference
android:icon="@drawable/ic_reset"
android:summary="@string/deleteAccount_summary"
app:key="delete_account"
app:title="@string/deleteAccount" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/restore">
<Preference <Preference
android:icon="@drawable/ic_upload" android:icon="@drawable/ic_upload"
android:summary="@string/import_from_yt_summary" android:summary="@string/import_from_yt_summary"

View File

@ -1,3 +1,8 @@
//plugins {
// id 'com.android.application' apply false version '7.2.1'
//id 'org.jetbrains.kotlin.android' apply false version '1.7.0'
//}
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
@ -15,4 +20,4 @@ buildscript {
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }

43
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,43 @@
[versions]
appcompat = "1.4.1"
constraintlayout = "2.1.3"
material = "1.6.0"
navigation = "2.4.2"
legacySupport = "1.0.0"
preference = "1.2.0"
extJunit = "1.1.3"
espresso = "3.4.0"
picasso = "2.8"
circleimageview = "3.1.0"
exoplayer = "2.17.1"
multidex = "2.0.1"
retrofit = "2.9.0"
jacksonAnnotations = "2.13.3"
mobileffmpeg = "4.5.1.LTS"
desugaring = "1.1.5"
cronetEmbedded = "101.4951.41"
leakcanary = "2.8.1"
[libraries]
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation" }
androidx-navigation-ui = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation" }
androidx-legacySupport = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupport" }
androidx-preference = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference" }
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "extJunit" }
androidx-test-espressoCore = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
square-picasso = { group = "com.squareup.picasso", name = "picasso", version.ref = "picasso" }
circleimageview = { group = "de.hdodenhof", name = "circleimageview", version.ref = "circleimageview" }
exoplayer = { group = "com.google.android.exoplayer", name = "exoplayer", version.ref = "exoplayer" }
exoplayer-extension-mediasession = { group = "com.google.android.exoplayer", name = "extension-mediasession", version.ref = "exoplayer" }
androidx-multidex = { group = "androidx.multidex", name = "multidex", version.ref = "multidex" }
square-retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
square-retrofit-converterJackson = { group = "com.squareup.retrofit2", name = "converter-jackson", version.ref = "retrofit" }
jacksonAnnotations = { group = "com.fasterxml.jackson.core", name = "jackson-annotations", version.ref = "jacksonAnnotations" }
mobileffmpeg = { group = "com.arthenica", name = "ffmpeg-kit-min", version.ref = "mobileffmpeg" }
desugaring = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugaring" }
exoplayer-extension-cronet = { group = "com.google.android.exoplayer", name = "extension-cronet", version.ref = "exoplayer" }
cronet-embedded = { group = "org.chromium.net", name = "cronet-embedded", version.ref = "cronetEmbedded" }
square-leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakcanary" }

View File

@ -1,6 +1,6 @@
#Thu Dec 09 16:25:51 GST 2021 #Thu Dec 09 16:25:51 GST 2021
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -1,3 +1,11 @@
//pluginManagement {
// repositories {
//gradlePluginPortal()
// google()
// mavenCentral()
// }
//}
dependencyResolutionManagement { dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { repositories {
@ -5,5 +13,6 @@ dependencyResolutionManagement {
mavenCentral() mavenCentral()
} }
} }
rootProject.name = "LibreTube" rootProject.name = "LibreTube"
include ':app' include ':app'