LibreTube/app/src/main/java/com/github/libretube/SettingsActivity.kt

413 lines
17 KiB
Kotlin
Raw Normal View History

2022-05-11 01:35:15 +05:30
package com.github.libretube
import android.Manifest
2022-06-01 11:32:16 +05:30
import android.app.NotificationManager
2022-05-24 00:56:11 +05:30
import android.content.ContentResolver
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
2022-05-11 01:35:15 +05:30
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
2022-05-17 02:02:32 +05:30
import android.text.Html
2022-05-11 01:35:15 +05:30
import android.text.TextUtils
import android.util.Log
2022-05-11 13:34:48 +05:30
import android.view.View
2022-05-11 01:35:15 +05:30
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
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 androidx.preference.PreferenceManager
2022-06-03 00:40:16 +05:30
import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.util.RetrofitInstance
2022-05-20 20:03:29 +05:30
import com.google.android.material.color.DynamicColors
2022-05-20 19:05:05 +05:30
import com.google.android.material.dialog.MaterialAlertDialogBuilder
2022-05-11 01:35:15 +05:30
import java.io.IOException
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
2022-06-02 21:44:55 +05:30
import org.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
2022-05-24 00:04:18 +05:30
2022-05-22 15:28:27 +05:30
private var isCurrentViewMainSettings = true
2022-05-31 01:49:42 +05:30
private var requireMainActivityRestart = false
2022-05-22 15:28:27 +05:30
2022-05-20 03:23:55 +05:30
class SettingsActivity :
AppCompatActivity(),
SharedPreferences.OnSharedPreferenceChangeListener {
2022-05-31 01:53:44 +05:30
2022-05-11 01:35:15 +05:30
override fun onCreate(savedInstanceState: Bundle?) {
2022-05-20 03:43:02 +05:30
DynamicColors.applyToActivityIfAvailable(this)
2022-05-20 03:11:21 +05:30
updateAccentColor(this)
updateThemeMode(this)
2022-05-11 01:35:15 +05:30
super.onCreate(savedInstanceState)
2022-05-13 22:25:15 +05:30
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
overridePendingTransition(50, 50)
2022-05-13 22:25:15 +05:30
}
2022-05-11 13:34:48 +05:30
val view = this.findViewById<View>(android.R.id.content)
2022-05-20 03:39:47 +05:30
view.alpha = 0F
view.animate().alpha(1F).duration = 300
2022-05-11 01:35:15 +05:30
setContentView(R.layout.activity_settings)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this)
}
2022-05-21 13:32:04 +05:30
override fun onSharedPreferenceChanged(
sharedPreferences: SharedPreferences?,
rootKey: String?
) {
}
2022-05-11 01:35:15 +05:30
class SettingsFragment : PreferenceFragmentCompat() {
val TAG = "Settings"
companion object {
lateinit var getContent: ActivityResultLauncher<String>
}
override fun onCreate(savedInstanceState: Bundle?) {
2022-05-21 13:32:04 +05:30
getContent =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if (uri != null) {
try {
// Open a specific media item using ParcelFileDescriptor.
val resolver: ContentResolver =
requireActivity()
.contentResolver
2022-05-11 01:35:15 +05:30
2022-05-21 13:32:04 +05:30
// "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)
2022-05-11 01:35:15 +05:30
2022-05-21 13:32:04 +05:30
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
2022-05-11 01:35:15 +05:30
}
}
2022-05-21 13:32:04 +05:30
inputStream?.bufferedReader()?.readLines()?.forEach {
if (it.isNotBlank()) {
val channelId = it.substringBefore(",")
if (channelId.length == 24)
channels.add(channelId)
}
2022-05-11 01:35:15 +05:30
}
}
2022-05-21 13:32:04 +05:30
inputStream?.close()
2022-05-11 01:35:15 +05:30
2022-05-21 13:32:04 +05:30
subscribe(channels)
} catch (e: Exception) {
Log.e(TAG, e.toString())
Toast.makeText(
context,
R.string.error,
Toast.LENGTH_SHORT
).show()
}
2022-05-11 01:35:15 +05:30
}
}
super.onCreate(savedInstanceState)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings, rootKey)
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 {
2022-06-02 21:37:09 +05:30
requireMainActivityRestart = true
2022-05-11 01:35:15 +05:30
val newFragment = LoginDialog()
newFragment.show(childFragmentManager, "Login")
true
}
2022-05-16 15:41:22 +05:30
val sponsorblock = findPreference<Preference>("sponsorblock")
sponsorblock?.setOnPreferenceClickListener {
2022-05-22 15:28:27 +05:30
isCurrentViewMainSettings = false
2022-05-16 15:41:22 +05:30
val newFragment = SponsorBlockSettings()
2022-05-20 03:23:55 +05:30
parentFragmentManager.beginTransaction()
2022-05-16 15:41:22 +05:30
.replace(R.id.settings, newFragment)
.commitNow()
true
}
2022-05-11 01:35:15 +05:30
val importFromYt = findPreference<Preference>("import_from_yt")
importFromYt?.setOnPreferenceClickListener {
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")!!
2022-05-20 03:23:55 +05:30
// check StorageAccess
2022-05-11 01:35:15 +05:30
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(
2022-05-20 03:23:55 +05:30
this.requireActivity(),
arrayOf(
2022-05-11 01:35:15 +05:30
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
2022-05-20 03:23:55 +05:30
),
1
) // permission request code is just an int
2022-05-11 01:35:15 +05:30
} 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
2022-05-21 13:32:04 +05:30
) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(
2022-05-20 03:23:55 +05:30
requireContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
2022-05-11 01:35:15 +05:30
) {
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")
2022-05-22 15:28:27 +05:30
themeToggle?.setOnPreferenceChangeListener { _, _ ->
2022-05-20 03:11:21 +05:30
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
2022-05-31 01:49:42 +05:30
requireMainActivityRestart = true
2022-05-11 01:35:15 +05:30
true
}
val accentColor = findPreference<Preference>("accent_color")
2022-05-20 03:23:55 +05:30
accentColor?.setOnPreferenceChangeListener { _, _ ->
2022-05-31 01:49:42 +05:30
requireMainActivityRestart = true
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
true
}
2022-05-22 23:54:12 +05:30
val iconChange = findPreference<ListPreference>("icon_change")
2022-05-23 23:10:02 +05:30
iconChange?.setOnPreferenceChangeListener { _, newValue ->
changeIcon(requireContext(), newValue.toString())
2022-05-22 23:54:12 +05:30
true
}
2022-05-31 01:49:42 +05:30
val gridColumns = findPreference<ListPreference>("grid")
gridColumns?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
2022-05-11 01:35:15 +05:30
true
}
val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener {
2022-05-21 13:32:04 +05:30
val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().remove("search_history").commit()
true
}
2022-05-11 01:35:15 +05:30
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
}
2022-05-17 02:02:32 +05:30
val license = findPreference<Preference>("license")
license?.setOnPreferenceClickListener {
2022-05-20 03:23:55 +05:30
val licenseString = view?.context?.assets!!.open("gpl3.html").bufferedReader().use {
2022-05-17 02:02:32 +05:30
it.readText()
}
val licenseHtml = if (Build.VERSION.SDK_INT >= 24) {
2022-05-20 03:23:55 +05:30
Html.fromHtml(licenseString, 1)
2022-05-17 02:02:32 +05:30
} else {
Html.fromHtml(licenseString)
}
2022-05-20 19:05:05 +05:30
MaterialAlertDialogBuilder(view?.context!!)
2022-05-21 13:32:04 +05:30
.setPositiveButton(
getString(R.string.okay),
DialogInterface.OnClickListener { _, _ -> }
)
2022-05-17 02:02:32 +05:30
.setMessage(licenseHtml)
.create()
.show()
true
}
2022-05-11 01:35:15 +05:30
}
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 {
2022-05-21 13:32:04 +05:30
val sharedPref =
context?.getSharedPreferences("token", Context.MODE_PRIVATE)
2022-05-11 01:35:15 +05:30
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()
}
}
2022-05-11 13:34:48 +05:30
override fun onBackPressed() {
2022-05-22 15:28:27 +05:30
if (isCurrentViewMainSettings) {
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this)
2022-05-31 01:49:42 +05:30
if (requireMainActivityRestart) {
2022-05-31 11:12:55 +05:30
requireMainActivityRestart = false
2022-06-01 11:32:16 +05:30
// kill player notification
val nManager = this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
nManager.cancelAll()
2022-05-31 01:49:42 +05:30
restartMainActivity(this)
finishAffinity()
} else {
super.onBackPressed()
}
finishAndRemoveTask()
2022-05-22 15:28:27 +05:30
} else {
isCurrentViewMainSettings = true
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
2022-05-11 01:35:15 +05:30
}
2022-05-20 03:23:55 +05:30
}