diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 31c00cbde..4cee2a677 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,10 @@ android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:configChanges="orientation|screenSize" /> + - } - - 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() - 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) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.settings, rootKey) - val instance = findPreference("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("login_register") - login?.setOnPreferenceClickListener { - val newFragment = LoginDialog() - newFragment.show(childFragmentManager, "Login") - true - } - - val importFromYt = findPreference("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("theme_togglee") - themeToggle?.setOnPreferenceChangeListener { _, newValue -> - when (newValue.toString()) { - "A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) - "L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - "D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) - } - true - } - - val changeLanguage = findPreference("language") - changeLanguage?.setOnPreferenceChangeListener { _, _ -> - val refresh = Intent(context, MainActivity::class.java) - startActivity(refresh) - true - } - - val about = findPreference("about") - about?.setOnPreferenceClickListener { - val uri = Uri.parse("https://libre-tube.github.io/") - val intent = Intent(Intent.ACTION_VIEW).setData(uri) - startActivity(intent) - 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 = ArrayList() - val listEntryValues: MutableList = ArrayList() - for (item in response) { - listEntries.add(item.name!!) - listEntryValues.add(item.api_url!!) - } - val entries = listEntries.toTypedArray() - val entryValues = listEntryValues.toTypedArray() - runOnUiThread { - val instance = findPreference("instance") - instance?.entries = entries - instance?.entryValues = entryValues - instance?.summaryProvider = - Preference.SummaryProvider { 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) { - 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() - } -} - - diff --git a/app/src/main/java/com/github/libretube/SettingsActivity.kt b/app/src/main/java/com/github/libretube/SettingsActivity.kt new file mode 100644 index 000000000..0fb13644e --- /dev/null +++ b/app/src/main/java/com/github/libretube/SettingsActivity.kt @@ -0,0 +1,320 @@ +package com.github.libretube + +import android.Manifest +import android.content.ContentResolver +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.text.TextUtils +import android.util.Log +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.AppCompatDelegate +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 +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 SettingsActivity : AppCompatActivity(), + SharedPreferences.OnSharedPreferenceChangeListener{ + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + overridePendingTransition(50, 50); + val view = this.findViewById(android.R.id.content) + view.setAlpha(0F); + view.animate().alpha(1F).setDuration(300); + setContentView(R.layout.activity_settings) + if (savedInstanceState == null) { + supportFragmentManager + .beginTransaction() + .replace(R.id.settings, SettingsFragment()) + .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 + } + + 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() + 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) + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.settings, rootKey) + val instance = findPreference("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("login_register") + login?.setOnPreferenceClickListener { + val newFragment = LoginDialog() + newFragment.show(childFragmentManager, "Login") + true + } + + val importFromYt = findPreference("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("theme_togglee") + themeToggle?.setOnPreferenceChangeListener { _, newValue -> + when (newValue.toString()) { + "A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + "L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + "D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) + } + true + } + + val changeLanguage = findPreference("language") + changeLanguage?.setOnPreferenceChangeListener { _, _ -> + val refresh = Intent(context, MainActivity::class.java) + startActivity(refresh) + true + } + + val about = findPreference("about") + about?.setOnPreferenceClickListener { + val uri = Uri.parse("https://libre-tube.github.io/") + val intent = Intent(Intent.ACTION_VIEW).setData(uri) + startActivity(intent) + 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 = ArrayList() + val listEntryValues: MutableList = ArrayList() + for (item in response) { + listEntries.add(item.name!!) + listEntryValues.add(item.api_url!!) + } + val entries = listEntries.toTypedArray() + val entryValues = listEntryValues.toTypedArray() + runOnUiThread { + val instance = findPreference("instance") + instance?.entries = entries + instance?.entryValues = entryValues + instance?.summaryProvider = + Preference.SummaryProvider { 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) { + 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() { + PreferenceManager.getDefaultSharedPreferences(this) + .unregisterOnSharedPreferenceChangeListener(this) + intent = Intent(this, MainActivity::class.java) + startActivity(intent) + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml new file mode 100644 index 000000000..de6591a20 --- /dev/null +++ b/app/src/main/res/layout/activity_settings.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav.xml b/app/src/main/res/navigation/nav.xml index f164bbb0c..eabf2f9bc 100644 --- a/app/src/main/res/navigation/nav.xml +++ b/app/src/main/res/navigation/nav.xml @@ -46,6 +46,6 @@ \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0d709f843..51d9d8b8e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,11 @@ Light Theme Dark Theme %1$s subscribers + Settings + Location + Instance + Customization + Website %1$s videos No Internet Connection Retry diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index caa6994ce..56ae14456 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -1,6 +1,9 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file