settings refactor

This commit is contained in:
Bnyro 2022-06-07 08:52:11 +02:00
parent 60ea36c0db
commit 7ba9ecf7bd
34 changed files with 1225 additions and 1134 deletions

View File

@ -41,7 +41,7 @@ android {
abi { abi {
enable true enable true
reset() reset()
include "armeabi-v7a","arm64-v8a","x86","x86_64" include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
universalApk false universalApk false
} }
@ -83,7 +83,7 @@ dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation ('com.google.android.exoplayer:extension-cronet:2.17.1') { exclude group: 'com.google.android.gms' } implementation('com.google.android.exoplayer:extension-cronet:2.17.1') { exclude group: 'com.google.android.gms' }
implementation 'org.chromium.net:cronet-embedded:101.4951.41' implementation 'org.chromium.net:cronet-embedded:101.4951.41'
} }

View File

@ -6,8 +6,9 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
@ -18,14 +19,12 @@
android:name=".MyApp" android:name=".MyApp"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:largeHeap="true" android:largeHeap="true"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true">
>
<activity <activity
android:name=".Player" android:name=".Player"
android:exported="false" android:exported="false"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:configChanges="orientation|screenSize" android:configChanges="orientation|screenSize" />
/>
<activity <activity
android:name=".SettingsActivity" android:name=".SettingsActivity"
android:label="@string/settings" /> android:label="@string/settings" />
@ -35,8 +34,7 @@
android:supportsPictureInPicture="true" android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:screenOrientation="userPortrait" android:screenOrientation="userPortrait">
>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@ -165,18 +163,19 @@
<activity <activity
android:name=".RouterActivity" android:name=".RouterActivity"
android:exported="true" android:exported="true"
android:launchMode="singleInstance" android:launchMode="singleInstance">
>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" /> <data android:mimeType="text/plain" />
</intent-filter> </intent-filter>
<!-- youtube --> <!-- youtube -->
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" /> <data android:scheme="https" />
<data android:host="youtube.com" /> <data android:host="youtube.com" />
@ -254,8 +253,10 @@
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" /> <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" /> <action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" /> <data android:scheme="https" />
<data android:host="piped.tokhmi.xyz" /> <data android:host="piped.tokhmi.xyz" />

File diff suppressed because it is too large Load Diff

View File

@ -226,19 +226,20 @@ class DownloadService : Service() {
) { ) {
// CALLED WHEN SESSION GENERATES STATISTICS // CALLED WHEN SESSION GENERATES STATISTICS
Log.e(TAG + "stat", it.time.toString()) Log.e(TAG + "stat", it.time.toString())
/*val progress = it.time/(10*duration!!) /*val progress = it.time/(10*duration!!)
if (progress<1){ if (progress<1){
notification notification
.setProgress(progressMax, progress.toInt(), false) .setProgress(progressMax, progress.toInt(), false)
service.notify(1,notification.build()) service.notify(1,notification.build())
}*/ }*/
} }
} }
override fun onDestroy() { override fun onDestroy() {
try { try {
unregisterReceiver(onDownloadComplete) unregisterReceiver(onDownloadComplete)
} catch (e: Exception) { } } catch (e: Exception) {
}
IS_DOWNLOAD_RUNNING = false IS_DOWNLOAD_RUNNING = false
Log.d(TAG, "dl finished!") Log.d(TAG, "dl finished!")

View File

@ -16,8 +16,8 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class Home : Fragment() { class Home : Fragment() {

View File

@ -17,8 +17,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.PlaylistsAdapter import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.dialogs.CreatePlaylistDialog import com.github.libretube.dialogs.CreatePlaylistDialog
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class Library : Fragment() { class Library : Fragment() {

View File

@ -33,6 +33,7 @@ import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.libretube.fragments.PlayerFragment import com.github.libretube.fragments.PlayerFragment
import com.github.libretube.fragments.isFullScreen import com.github.libretube.fragments.isFullScreen
import com.github.libretube.preferences.SponsorBlockSettings
import com.github.libretube.util.CronetHelper import com.github.libretube.util.CronetHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.updateLanguage import com.github.libretube.util.updateLanguage

View File

@ -1,54 +1,20 @@
package com.github.libretube package com.github.libretube
import android.Manifest
import android.app.NotificationManager import android.app.NotificationManager
import android.content.ContentResolver
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.Html
import android.text.TextUtils
import android.util.Log
import android.view.View import android.view.View
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import com.github.libretube.preferences.SettingsFragment
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.changeIcon
import com.github.libretube.util.checkUpdate
import com.github.libretube.util.restartMainActivity import com.github.libretube.util.restartMainActivity
import com.github.libretube.util.updateTheme import com.github.libretube.util.updateTheme
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.io.IOException
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import org.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
private var isCurrentViewMainSettings = true var isCurrentViewMainSettings = true
private var requireMainActivityRestart = false var requireMainActivityRestart = false
class SettingsActivity : class SettingsActivity : AppCompatActivity() {
AppCompatActivity(),
SharedPreferences.OnSharedPreferenceChangeListener {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
DynamicColors.applyToActivityIfAvailable(this) DynamicColors.applyToActivityIfAvailable(this)
@ -69,355 +35,18 @@ class SettingsActivity :
.replace(R.id.settings, SettingsFragment()) .replace(R.id.settings, SettingsFragment())
.commit() .commit()
} }
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(
sharedPreferences: SharedPreferences?,
rootKey: String?
) {
}
class SettingsFragment : PreferenceFragmentCompat() {
val TAG = "Settings"
companion object {
lateinit var getContent: ActivityResultLauncher<String>
}
override fun onCreate(savedInstanceState: Bundle?) {
getContent =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if (uri != null) {
try {
// Open a specific media item using ParcelFileDescriptor.
val resolver: ContentResolver =
requireActivity()
.contentResolver
// "rw" for read-and-write;
// "rwt" for truncating or overwriting existing file contents.
// val readOnlyMode = "r"
// uri - I have got from onActivityResult
val type = resolver.getType(uri)
var inputStream: InputStream? = resolver.openInputStream(uri)
val channels = ArrayList<String>()
if (type == "application/json") {
val json = inputStream?.bufferedReader()?.readLines()?.get(0)
val jsonObject = JSONTokener(json).nextValue() as JSONObject
Log.e(TAG, jsonObject.getJSONArray("subscriptions").toString())
for (
i in 0 until jsonObject.getJSONArray("subscriptions")
.length()
) {
var url =
jsonObject.getJSONArray("subscriptions").getJSONObject(i)
.getString("url")
url = url.replace("https://www.youtube.com/channel/", "")
Log.e(TAG, url)
channels.add(url)
}
} else {
if (type == "application/zip") {
val zis = ZipInputStream(inputStream)
var entry: ZipEntry? = zis.nextEntry
while (entry != null) {
if (entry.name.endsWith(".csv")) {
inputStream = zis
break
}
entry = zis.nextEntry
}
}
inputStream?.bufferedReader()?.readLines()?.forEach {
if (it.isNotBlank()) {
val channelId = it.substringBefore(",")
if (channelId.length == 24)
channels.add(channelId)
}
}
}
inputStream?.close()
subscribe(channels)
} catch (e: Exception) {
Log.e(TAG, e.toString())
Toast.makeText(
context,
R.string.error,
Toast.LENGTH_SHORT
).show()
}
}
}
super.onCreate(savedInstanceState)
try {
checkUpdate(childFragmentManager)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings, rootKey)
val region = findPreference<Preference>("region")
region?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
true
}
val language = findPreference<ListPreference>("language")
language?.setOnPreferenceChangeListener { _, _ ->
restartMainActivity(requireContext())
true
}
val instance = findPreference<ListPreference>("instance")
fetchInstance()
instance?.setOnPreferenceChangeListener { _, newValue ->
RetrofitInstance.url = newValue.toString()
RetrofitInstance.lazyMgr.reset()
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
if (sharedPref?.getString("token", "") != "") {
with(sharedPref!!.edit()) {
putString("token", "")
apply()
}
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
}
true
}
val login = findPreference<Preference>("login_register")
login?.setOnPreferenceClickListener {
requireMainActivityRestart = true
val newFragment = LoginDialog()
newFragment.show(childFragmentManager, "Login")
true
}
val sponsorblock = findPreference<Preference>("sponsorblock")
sponsorblock?.setOnPreferenceClickListener {
isCurrentViewMainSettings = false
val newFragment = SponsorBlockSettings()
parentFragmentManager.beginTransaction()
.replace(R.id.settings, newFragment)
.commitNow()
true
}
val importFromYt = findPreference<Preference>("import_from_yt")
importFromYt?.setOnPreferenceClickListener {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")!!
// check StorageAccess
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Log.d("myz", "" + Build.VERSION.SDK_INT)
if (ContextCompat.checkSelfPermission(
this.requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this.requireActivity(),
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
),
1
) // permission request code is just an int
} else if (token != "") {
getContent.launch("*/*")
} else {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
}
} else {
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this.requireActivity(),
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
),
1
)
} else if (token != "") {
getContent.launch("*/*")
} else {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
}
}
true
}
val themeToggle = findPreference<ListPreference>("theme_togglee")
themeToggle?.setOnPreferenceChangeListener { _, _ ->
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
requireMainActivityRestart = true
true
}
val accentColor = findPreference<Preference>("accent_color")
accentColor?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
true
}
val iconChange = findPreference<ListPreference>("icon_change")
iconChange?.setOnPreferenceChangeListener { _, newValue ->
changeIcon(requireContext(), newValue.toString())
true
}
val gridColumns = findPreference<ListPreference>("grid")
gridColumns?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
true
}
val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener {
val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().remove("search_history").commit()
true
}
val about = findPreference<Preference>("about")
about?.setOnPreferenceClickListener {
val uri = Uri.parse("https://libre-tube.github.io/")
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)
true
}
val license = findPreference<Preference>("license")
license?.setOnPreferenceClickListener {
val licenseString = view?.context?.assets!!.open("gpl3.html").bufferedReader().use {
it.readText()
}
val licenseHtml = if (Build.VERSION.SDK_INT >= 24) {
Html.fromHtml(licenseString, 1)
} else {
Html.fromHtml(licenseString)
}
MaterialAlertDialogBuilder(view?.context!!)
.setPositiveButton(
getString(R.string.okay),
DialogInterface.OnClickListener { _, _ -> }
)
.setMessage(licenseHtml)
.create()
.show()
true
}
}
private fun fetchInstance() {
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getInstances("https://instances.tokhmi.xyz/")
} catch (e: IOException) {
println(e)
Log.e("settings", "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e("settings", "HttpException, unexpected response $e")
return@launchWhenCreated
} catch (e: Exception) {
Log.e("settings", e.toString())
return@launchWhenCreated
}
val listEntries: MutableList<String> = ArrayList()
val listEntryValues: MutableList<String> = ArrayList()
for (item in response) {
listEntries.add(item.name!!)
listEntryValues.add(item.api_url!!)
}
val entries = listEntries.toTypedArray<CharSequence>()
val entryValues = listEntryValues.toTypedArray<CharSequence>()
runOnUiThread {
val instance = findPreference<ListPreference>("instance")
instance?.entries = entries
instance?.entryValues = entryValues
instance?.summaryProvider =
Preference.SummaryProvider<ListPreference> { preference ->
val text = preference.entry
if (TextUtils.isEmpty(text)) {
"kavin.rocks (Official)"
} else {
text
}
}
}
}
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return
if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action)
}
private fun subscribe(channels: List<String>) {
fun run() {
lifecycleScope.launchWhenCreated {
val response = try {
val sharedPref =
context?.getSharedPreferences("token", Context.MODE_PRIVATE)
RetrofitInstance.api.importSubscriptions(
false,
sharedPref?.getString("token", "")!!,
channels
)
} catch (e: IOException) {
Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response$e")
return@launchWhenCreated
}
if (response.message == "ok") {
Toast.makeText(
context,
R.string.importsuccess,
Toast.LENGTH_SHORT
).show()
}
}
}
run()
}
} }
override fun onBackPressed() { override fun onBackPressed() {
if (isCurrentViewMainSettings) { if (isCurrentViewMainSettings) {
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this)
if (requireMainActivityRestart) { if (requireMainActivityRestart) {
requireMainActivityRestart = false requireMainActivityRestart = false
// kill player notification // kill player notification
val nManager = this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager val nManager =
this.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
nManager.cancelAll() nManager.cancelAll()
restartMainActivity(this) restartMainActivity(this)
finishAffinity() ActivityCompat.finishAffinity(this)
} else { } else {
super.onBackPressed() super.onBackPressed()
} }

View File

@ -26,8 +26,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.SubscriptionAdapter import com.github.libretube.adapters.SubscriptionAdapter
import com.github.libretube.adapters.SubscriptionChannelAdapter import com.github.libretube.adapters.SubscriptionChannelAdapter
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class Subscriptions : Fragment() { class Subscriptions : Fragment() {
val TAG = "SubFragment" val TAG = "SubFragment"

View File

@ -20,10 +20,10 @@ import com.github.libretube.obj.PlaylistId
import com.github.libretube.obj.StreamItem import com.github.libretube.obj.StreamItem
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class PlaylistAdapter( class PlaylistAdapter(
private val videoFeed: MutableList<StreamItem>, private val videoFeed: MutableList<StreamItem>,

View File

@ -17,10 +17,10 @@ import com.github.libretube.obj.Playlists
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 com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class PlaylistsAdapter( class PlaylistsAdapter(
private val playlists: MutableList<Playlists>, private val playlists: MutableList<Playlists>,

View File

@ -15,11 +15,11 @@ import com.github.libretube.obj.Subscribe
import com.github.libretube.obj.Subscription import com.github.libretube.obj.Subscription
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscription>) : class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscription>) :
RecyclerView.Adapter<SubscriptionChannelViewHolder>() { RecyclerView.Adapter<SubscriptionChannelViewHolder>() {

View File

@ -19,8 +19,8 @@ import com.github.libretube.R
import com.github.libretube.obj.PlaylistId import com.github.libretube.obj.PlaylistId
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 java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class AddtoPlaylistDialog : DialogFragment() { class AddtoPlaylistDialog : DialogFragment() {
private val TAG = "AddToPlaylistDialog" private val TAG = "AddToPlaylistDialog"

View File

@ -19,8 +19,8 @@ import com.github.libretube.obj.Playlists
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 com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputEditText
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class CreatePlaylistDialog : DialogFragment() { class CreatePlaylistDialog : DialogFragment() {
val TAG = "CreatePlaylistDialog" val TAG = "CreatePlaylistDialog"

View File

@ -17,8 +17,8 @@ import com.github.libretube.R
import com.github.libretube.obj.Login import com.github.libretube.obj.Login
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 java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class LoginDialog : DialogFragment() { class LoginDialog : DialogFragment() {
private val TAG = "LoginDialog" private val TAG = "LoginDialog"

View File

@ -22,8 +22,8 @@ import com.github.libretube.obj.Subscribe
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class ChannelFragment : Fragment() { class ChannelFragment : Fragment() {

View File

@ -43,7 +43,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.IS_DOWNLOAD_RUNNING import com.github.libretube.IS_DOWNLOAD_RUNNING
import com.github.libretube.MainActivity import com.github.libretube.MainActivity
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.SponsorBlockSettings
import com.github.libretube.adapters.CommentsAdapter import com.github.libretube.adapters.CommentsAdapter
import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.dialogs.AddtoPlaylistDialog import com.github.libretube.dialogs.AddtoPlaylistDialog
@ -56,6 +55,7 @@ import com.github.libretube.obj.Segment
import com.github.libretube.obj.Segments import com.github.libretube.obj.Segments
import com.github.libretube.obj.Streams import com.github.libretube.obj.Streams
import com.github.libretube.obj.Subscribe import com.github.libretube.obj.Subscribe
import com.github.libretube.preferences.SponsorBlockSettings
import com.github.libretube.util.CronetHelper import com.github.libretube.util.CronetHelper
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
@ -82,11 +82,11 @@ import com.google.android.exoplayer2.util.RepeatModeUtil
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import org.chromium.net.CronetEngine
import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.abs import kotlin.math.abs
import org.chromium.net.CronetEngine
import retrofit2.HttpException
var isFullScreen = false var isFullScreen = false

View File

@ -15,8 +15,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.adapters.PlaylistAdapter import com.github.libretube.adapters.PlaylistAdapter
import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.RetrofitInstance
import java.io.IOException
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class PlaylistFragment : Fragment() { class PlaylistFragment : Fragment() {
private var playlist_id: String? = null private var playlist_id: String? = null

View File

@ -30,11 +30,11 @@ import com.github.libretube.adapters.SearchHistoryAdapter
import com.github.libretube.hideKeyboard import com.github.libretube.hideKeyboard
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 java.io.IOException
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException
class SearchFragment : Fragment() { class SearchFragment : Fragment() {
private val TAG = "SearchFragment" private val TAG = "SearchFragment"

View File

@ -0,0 +1,46 @@
package com.github.libretube.preferences
import android.content.Intent
import android.os.Bundle
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.github.libretube.R
import com.github.libretube.SettingsActivity
import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.changeIcon
class AppearanceSettings : PreferenceFragmentCompat() {
private val TAG = "CustomizationSettings"
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.appearance_settings, rootKey)
val themeToggle = findPreference<ListPreference>("theme_togglee")
themeToggle?.setOnPreferenceChangeListener { _, _ ->
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
requireMainActivityRestart = true
true
}
val accentColor = findPreference<Preference>("accent_color")
accentColor?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
true
}
val iconChange = findPreference<ListPreference>("icon_change")
iconChange?.setOnPreferenceChangeListener { _, newValue ->
changeIcon(requireContext(), newValue.toString())
true
}
val gridColumns = findPreference<ListPreference>("grid")
gridColumns?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
true
}
}
}

View File

@ -0,0 +1,23 @@
package com.github.libretube.preferences
import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.github.libretube.R
class HistorySettings : PreferenceFragmentCompat() {
private val TAG = "HistorySettings"
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.history_settings, rootKey)
val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener {
val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().remove("search_history").commit()
true
}
}
}

View File

@ -0,0 +1,343 @@
package com.github.libretube.preferences
import android.Manifest
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.Html
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.github.libretube.R
import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.isCurrentViewMainSettings
import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.checkUpdate
import com.github.libretube.util.restartMainActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
import java.io.IOException
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
class SettingsFragment : PreferenceFragmentCompat() {
val TAG = "Settings"
companion object {
lateinit var getContent: ActivityResultLauncher<String>
}
override fun onCreate(savedInstanceState: Bundle?) {
getContent =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if (uri != null) {
try {
// Open a specific media item using ParcelFileDescriptor.
val resolver: ContentResolver =
requireActivity()
.contentResolver
// "rw" for read-and-write;
// "rwt" for truncating or overwriting existing file contents.
// val readOnlyMode = "r"
// uri - I have got from onActivityResult
val type = resolver.getType(uri)
var inputStream: InputStream? = resolver.openInputStream(uri)
val channels = ArrayList<String>()
if (type == "application/json") {
val json = inputStream?.bufferedReader()?.readLines()?.get(0)
val jsonObject = JSONTokener(json).nextValue() as JSONObject
Log.e(TAG, jsonObject.getJSONArray("subscriptions").toString())
for (
i in 0 until jsonObject.getJSONArray("subscriptions")
.length()
) {
var url =
jsonObject.getJSONArray("subscriptions").getJSONObject(i)
.getString("url")
url = url.replace("https://www.youtube.com/channel/", "")
Log.e(TAG, url)
channels.add(url)
}
} else {
if (type == "application/zip") {
val zis = ZipInputStream(inputStream)
var entry: ZipEntry? = zis.nextEntry
while (entry != null) {
if (entry.name.endsWith(".csv")) {
inputStream = zis
break
}
entry = zis.nextEntry
}
}
inputStream?.bufferedReader()?.readLines()?.forEach {
if (it.isNotBlank()) {
val channelId = it.substringBefore(",")
if (channelId.length == 24)
channels.add(channelId)
}
}
}
inputStream?.close()
subscribe(channels)
} catch (e: Exception) {
Log.e(TAG, e.toString())
Toast.makeText(
context,
R.string.error,
Toast.LENGTH_SHORT
).show()
}
}
}
super.onCreate(savedInstanceState)
try {
checkUpdate(childFragmentManager)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings, rootKey)
val region = findPreference<Preference>("region")
region?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
true
}
val language = findPreference<ListPreference>("language")
language?.setOnPreferenceChangeListener { _, _ ->
restartMainActivity(requireContext())
true
}
val instance = findPreference<ListPreference>("instance")
fetchInstance()
instance?.setOnPreferenceChangeListener { _, newValue ->
RetrofitInstance.url = newValue.toString()
RetrofitInstance.lazyMgr.reset()
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
if (sharedPref?.getString("token", "") != "") {
with(sharedPref!!.edit()) {
putString("token", "")
apply()
}
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
}
true
}
val login = findPreference<Preference>("login_register")
login?.setOnPreferenceClickListener {
requireMainActivityRestart = true
val newFragment = LoginDialog()
newFragment.show(childFragmentManager, "Login")
true
}
val sponsorblock = findPreference<Preference>("sponsorblock")
sponsorblock?.setOnPreferenceClickListener {
val newFragment = SponsorBlockSettings()
navigateSettings(newFragment)
true
}
val history = findPreference<Preference>("history")
history?.setOnPreferenceClickListener {
val newFragment = HistorySettings()
navigateSettings(newFragment)
true
}
val appearance = findPreference<Preference>("appearance")
appearance?.setOnPreferenceClickListener {
val newFragment = AppearanceSettings()
navigateSettings(newFragment)
true
}
val importFromYt = findPreference<Preference>("import_from_yt")
importFromYt?.setOnPreferenceClickListener {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")!!
// check StorageAccess
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Log.d("myz", "" + Build.VERSION.SDK_INT)
if (ContextCompat.checkSelfPermission(
this.requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
)
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this.requireActivity(),
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
),
1
) // permission request code is just an int
} else if (token != "") {
getContent.launch("*/*")
} else {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
}
} else {
if (ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this.requireActivity(),
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
),
1
)
} else if (token != "") {
getContent.launch("*/*")
} else {
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
}
}
true
}
val about = findPreference<Preference>("about")
about?.setOnPreferenceClickListener {
val uri = Uri.parse("https://libre-tube.github.io/")
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)
true
}
val license = findPreference<Preference>("license")
license?.setOnPreferenceClickListener {
val licenseString = view?.context?.assets!!
.open("gpl3.html").bufferedReader().use {
it.readText()
}
val licenseHtml = if (Build.VERSION.SDK_INT >= 24) Html.fromHtml(licenseString, 1)
else Html.fromHtml(licenseString)
MaterialAlertDialogBuilder(view?.context!!)
.setPositiveButton(getString(R.string.okay)) { _, _ -> }
.setMessage(licenseHtml)
.create()
.show()
true
}
}
private fun navigateSettings(newFragment: PreferenceFragmentCompat) {
isCurrentViewMainSettings = false
parentFragmentManager.beginTransaction()
.replace(R.id.settings, newFragment)
.commitNow()
}
private fun fetchInstance() {
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getInstances("https://instances.tokhmi.xyz/")
} catch (e: IOException) {
println(e)
Log.e("settings", "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e("settings", "HttpException, unexpected response $e")
return@launchWhenCreated
} catch (e: Exception) {
Log.e("settings", e.toString())
return@launchWhenCreated
}
val listEntries: MutableList<String> = ArrayList()
val listEntryValues: MutableList<String> = ArrayList()
for (item in response) {
listEntries.add(item.name!!)
listEntryValues.add(item.api_url!!)
}
val entries = listEntries.toTypedArray<CharSequence>()
val entryValues = listEntryValues.toTypedArray<CharSequence>()
runOnUiThread {
val instance = findPreference<ListPreference>("instance")
instance?.entries = entries
instance?.entryValues = entryValues
instance?.summaryProvider =
Preference.SummaryProvider<ListPreference> { preference ->
val text = preference.entry
if (TextUtils.isEmpty(text)) {
"kavin.rocks (Official)"
} else {
text
}
}
}
}
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return
if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action)
}
private fun subscribe(channels: List<String>) {
fun run() {
lifecycleScope.launchWhenCreated {
val response = try {
val sharedPref =
context?.getSharedPreferences("token", Context.MODE_PRIVATE)
RetrofitInstance.api.importSubscriptions(
false,
sharedPref?.getString("token", "")!!,
channels
)
} catch (e: IOException) {
Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response$e")
return@launchWhenCreated
}
if (response.message == "ok") {
Toast.makeText(
context,
R.string.importsuccess,
Toast.LENGTH_SHORT
).show()
}
}
}
run()
}
}

View File

@ -1,11 +1,12 @@
package com.github.libretube package com.github.libretube.preferences
import android.os.Bundle import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import com.github.libretube.R
class SponsorBlockSettings : PreferenceFragmentCompat() { class SponsorBlockSettings : PreferenceFragmentCompat() {
private val TAG = "SponsorBlockDialog" private val TAG = "SponsorBlockSettings"
companion object { companion object {
var sponsorBlockEnabled: Boolean = false var sponsorBlockEnabled: Boolean = false

View File

@ -4,12 +4,12 @@ import android.util.Log
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.github.libretube.BuildConfig import com.github.libretube.BuildConfig
import com.github.libretube.dialogs.UpdateAvailableDialog import com.github.libretube.dialogs.UpdateAvailableDialog
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStreamReader import java.io.InputStreamReader
import java.net.URL import java.net.URL
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
import org.json.JSONArray
import org.json.JSONObject
fun checkUpdate(childFragmentManager: FragmentManager) { fun checkUpdate(childFragmentManager: FragmentManager) {
var updateInfo: UpdateInfo? = UpdateInfo("", "") var updateInfo: UpdateInfo? = UpdateInfo("", "")

View File

@ -32,7 +32,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_margin="8dp" android:layout_margin="8dp"
android:visibility="gone" > android:visibility="gone">
<RadioButton <RadioButton
android:id="@+id/mkv" android:id="@+id/mkv"

View File

@ -149,7 +149,7 @@
android:gravity="center" android:gravity="center"
android:text="@string/download" android:text="@string/download"
android:maxLines="1" android:maxLines="1"
android:autoSizeTextType="uniform"/> android:autoSizeTextType="uniform" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout

View File

@ -33,28 +33,28 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="30dp"
android:background="@android:color/transparent"
app:hintEnabled="false" >
<AutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="30dp"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:dropDownWidth="match_parent" app:hintEnabled="false">
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:padding="12dp" />
</com.google.android.material.textfield.TextInputLayout> <AutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:dropDownWidth="match_parent"
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:padding="12dp" />
</com.google.android.material.textfield.TextInputLayout>
<ImageView <ImageView
android:id="@+id/clearSearch_imageView" android:id="@+id/clearSearch_imageView"
@ -65,7 +65,7 @@
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="16dp" /> android:layout_marginRight="16dp" />
</RelativeLayout> </RelativeLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
<ImageView <ImageView

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

View File

@ -118,4 +118,6 @@
<string name="playOnBackground">Play on background</string> <string name="playOnBackground">Play on background</string>
<string name="update_available">Version %1$s is available</string> <string name="update_available">Version %1$s is available</string>
<string name="update_available_text">There is a new update available. Click okay to become redirected to the update page on GitHub.</string> <string name="update_available_text">There is a new update available. Click okay to become redirected to the update page on GitHub.</string>
<string name="appearance">Appearance</string>
<string name="app_behavior">App Behavior</string>
</resources> </resources>

View File

@ -13,6 +13,6 @@
<item name="android:statusBarColor">@android:color/transparent</item> <item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item> <item name="android:navigationBarColor">@android:color/transparent</item>
</style> </style>
</resources> </resources>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="@string/appearance">
<androidx.preference.ListPreference
app:title="@string/app_theme"
app:key="theme_togglee"
app:entries="@array/themes"
app:entryValues="@array/themesValue"
app:defaultValue="A"
android:icon="@drawable/ic_theme" />
<androidx.preference.ListPreference
app:title="@string/color_accent"
app:key="accent_color"
app:entries="@array/accents"
app:entryValues="@array/accentsValue"
app:defaultValue="red"
android:icon="@drawable/ic_color" />
<androidx.preference.ListPreference
app:title="@string/app_icon"
app:key="icon_change"
app:entries="@array/icons"
app:entryValues="@array/iconsValue"
app:defaultValue="MainActivity"
android:icon="@drawable/ic_frame" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/app_behavior">
<androidx.preference.ListPreference
app:title="@string/defaultTab"
app:key="default_tab"
app:entries="@array/tabs"
app:entryValues="@array/tabsValue"
app:defaultValue="home"
android:icon="@drawable/ic_home_outlined" />
<androidx.preference.ListPreference
app:title="@string/defres"
app:key="default_res"
app:entries="@array/defres"
app:entryValues="@array/defresValue"
app:defaultValue=""
android:icon="@drawable/ic_hd"
app:useSimpleSummaryProvider="true" />
<androidx.preference.ListPreference
app:title="@string/grid"
app:key="grid"
app:entries="@array/grid"
app:entryValues="@array/grid"
app:defaultValue="@integer/grid_items"
android:icon="@drawable/ic_grid"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="@string/search_history">
<SwitchPreference
app:title="@string/search_history"
app:key="search_history_toggle"
android:defaultValue="true"
android:icon="@drawable/ic_history" />
<Preference
app:title="@string/clear_history"
app:key="clear_history"
android:icon="@drawable/ic_delete" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -54,80 +54,24 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/customization"> <PreferenceCategory app:title="@string/customization">
<ListPreference <Preference
app:title="@string/app_theme" app:key="appearance"
app:key="theme_togglee" app:title="@string/appearance"
app:entries="@array/themes"
app:entryValues="@array/themesValue"
app:defaultValue="A"
android:icon="@drawable/ic_theme" />
<ListPreference
app:title="@string/color_accent"
app:key="accent_color"
app:entries="@array/accents"
app:entryValues="@array/accentsValue"
app:defaultValue="red"
android:icon="@drawable/ic_color" /> android:icon="@drawable/ic_color" />
<ListPreference
app:title="@string/app_icon"
app:key="icon_change"
app:entries="@array/icons"
app:entryValues="@array/iconsValue"
app:defaultValue="MainActivity"
android:icon="@drawable/ic_frame" />
<androidx.preference.Preference <androidx.preference.Preference
app:title="@string/sponsorblock" app:title="@string/sponsorblock"
app:key="sponsorblock" app:key="sponsorblock"
app:summary="@string/sponsorblock_summary" app:summary="@string/sponsorblock_summary"
android:icon="@drawable/ic_block" /> android:icon="@drawable/ic_block" />
<ListPreference <androidx.preference.Preference
app:title="@string/defaultTab" app:key="history"
app:key="default_tab" app:title="@string/history"
app:entries="@array/tabs"
app:entryValues="@array/tabsValue"
app:defaultValue="home"
android:icon="@drawable/ic_home_outlined" />
<ListPreference
app:title="@string/defres"
app:key="default_res"
app:entries="@array/defres"
app:entryValues="@array/defresValue"
app:defaultValue=""
android:icon="@drawable/ic_hd"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:title="@string/grid"
app:key="grid"
app:entries="@array/grid"
app:entryValues="@array/grid"
app:defaultValue="@integer/grid_items"
android:icon="@drawable/ic_grid"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/history">
<SwitchPreference
app:title="@string/search_history"
app:key="search_history_toggle"
android:defaultValue="true"
android:icon="@drawable/ic_history" /> android:icon="@drawable/ic_history" />
<Preference
app:title="@string/clear_history"
app:key="clear_history"
android:icon="@drawable/ic_delete" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/about"> <PreferenceCategory app:title="@string/about">