Merge branch 'master' into thumbnail

This commit is contained in:
Bnyro 2022-06-08 11:37:19 +02:00
commit a956b9852e
197 changed files with 2184 additions and 1404 deletions

View File

@ -41,7 +41,7 @@ android {
abi {
enable true
reset()
include "armeabi-v7a","arm64-v8a","x86","x86_64"
include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
universalApk false
}
@ -83,7 +83,7 @@ dependencies {
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'
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.preference.PreferenceManager
import com.arthenica.ffmpegkit.FFmpegKit
import java.io.File
@ -44,8 +45,9 @@ class DownloadService : Service() {
videoId = intent?.getStringExtra("videoId")!!
videoUrl = intent.getStringExtra("videoUrl")!!
audioUrl = intent.getStringExtra("audioUrl")!!
extension = intent.getStringExtra("extension")!!
duration = intent.getIntExtra("duration", 1)
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
extension = sharedPreferences.getString("video_format", ".mp4")!!
downloadType = if (audioUrl != "" && videoUrl != "") "mux"
else if (audioUrl != "") "audio"
else if (videoUrl != "") "video"
@ -81,11 +83,22 @@ class DownloadService : Service() {
}
// create LibreTube folder in Downloads
/*
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
val downloadsDirectory = sharedPreferences.getString("download_directory_path", "")
Log.i(TAG, downloadsDirectory!!)
libretubeDir = if (downloadsDirectory == "") File(
Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS),
"LibreTube"
)
else File(downloadsDirectory)
*/
libretubeDir = File(
Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS),
"LibreTube"
)
if (!libretubeDir.exists()) libretubeDir.mkdirs()
Log.i(TAG, libretubeDir.toString())
// start download
try {
@ -226,19 +239,20 @@ class DownloadService : Service() {
) {
// CALLED WHEN SESSION GENERATES STATISTICS
Log.e(TAG + "stat", it.time.toString())
/*val progress = it.time/(10*duration!!)
if (progress<1){
notification
.setProgress(progressMax, progress.toInt(), false)
service.notify(1,notification.build())
}*/
/*val progress = it.time/(10*duration!!)
if (progress<1){
notification
.setProgress(progressMax, progress.toInt(), false)
service.notify(1,notification.build())
}*/
}
}
override fun onDestroy() {
try {
unregisterReceiver(onDownloadComplete)
} catch (e: Exception) { }
} catch (e: Exception) {
}
IS_DOWNLOAD_RUNNING = false
Log.d(TAG, "dl finished!")

View File

@ -33,10 +33,11 @@ import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import com.github.libretube.fragments.PlayerFragment
import com.github.libretube.fragments.isFullScreen
import com.github.libretube.preferences.SponsorBlockSettings
import com.github.libretube.util.CronetHelper
import com.github.libretube.util.LocaleHelper
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.updateLanguage
import com.github.libretube.util.updateTheme
import com.github.libretube.util.ThemeHelper
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.color.DynamicColors
@ -68,8 +69,8 @@ class MainActivity : AppCompatActivity() {
SponsorBlockSettings.outroEnabled =
sharedPreferences.getBoolean("outro_category_key", false)
updateTheme(this)
updateLanguage(this)
ThemeHelper().updateTheme(this)
LocaleHelper().updateLanguage(this)
val connectivityManager =
this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

View File

@ -6,7 +6,7 @@ import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.github.libretube.util.restartMainActivity
import com.github.libretube.util.ThemeHelper
class RouterActivity : AppCompatActivity() {
val TAG = "RouterActivity"
@ -17,7 +17,7 @@ class RouterActivity : AppCompatActivity() {
handleSendText(intent)
} else {
// start app as normal if URI not in host list
restartMainActivity(this)
ThemeHelper().restartMainActivity(this)
}
}

View File

@ -1,58 +1,27 @@
package com.github.libretube
import android.Manifest
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.Bundle
import android.text.Html
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 android.widget.ImageButton
import android.widget.TextView
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
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.updateTheme
import com.github.libretube.preferences.MainSettings
import com.github.libretube.util.ThemeHelper
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
private var requireMainActivityRestart = false
class SettingsActivity :
AppCompatActivity(),
SharedPreferences.OnSharedPreferenceChangeListener {
var isCurrentViewMainSettings = true
var requireMainActivityRestart = false
class SettingsActivity : AppCompatActivity() {
val TAG = "SettingsActivity"
override fun onCreate(savedInstanceState: Bundle?) {
DynamicColors.applyToActivityIfAvailable(this)
updateTheme(this)
ThemeHelper().updateTheme(this)
// makes the preference dialogs use material dialogs
setTheme(R.style.MaterialAlertDialog)
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@ -63,361 +32,30 @@ class SettingsActivity :
view.animate().alpha(1F).duration = 300
setContentView(R.layout.activity_settings)
val backButton = view.findViewById<ImageButton>(R.id.back_imageButton)
backButton.setOnClickListener {
onBackPressed()
}
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.replace(R.id.settings, MainSettings())
.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() {
if (isCurrentViewMainSettings) {
PreferenceManager.getDefaultSharedPreferences(this)
.unregisterOnSharedPreferenceChangeListener(this)
if (requireMainActivityRestart) {
requireMainActivityRestart = false
// kill player notification
val nManager = this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val nManager =
this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
nManager.cancelAll()
restartMainActivity(this)
finishAffinity()
ThemeHelper().restartMainActivity(this)
ActivityCompat.finishAffinity(this)
} else {
super.onBackPressed()
}
@ -426,8 +64,10 @@ class SettingsActivity :
isCurrentViewMainSettings = true
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.replace(R.id.settings, MainSettings())
.commit()
val topBarTextView = findViewById<TextView>(R.id.topBar_textView)
topBarTextView?.text = getString(R.string.settings)
}
}
}

View File

@ -70,7 +70,12 @@ class SearchViewHolder(
val thumbnailImage = v.findViewById<ImageView>(R.id.search_thumbnail)
Picasso.get().load(item.thumbnail).fit().centerCrop().into(thumbnailImage)
val thumbnailDuration = v.findViewById<TextView>(R.id.search_thumbnail_duration)
thumbnailDuration.text = DateUtils.formatElapsedTime(item.duration!!)
if (item.duration != -1L) {
thumbnailDuration.text = DateUtils.formatElapsedTime(item.duration!!)
} else {
thumbnailDuration.text = v.context.getString(R.string.live)
thumbnailDuration.setBackgroundColor(R.attr.colorPrimaryDark)
}
val channelImage = v.findViewById<ImageView>(R.id.search_channel_image)
Picasso.get().load(item.uploaderAvatar).fit().centerCrop().into(channelImage)
val title = v.findViewById<TextView>(R.id.search_description)

View File

@ -53,8 +53,13 @@ class SubscriptionAdapter(
trending.views.formatShort() + "" +
DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text =
DateUtils.formatElapsedTime(trending.duration!!)
val thumbnailDuration = holder.v.findViewById<TextView>(R.id.thumbnail_duration)
if (trending.duration != -1L) {
thumbnailDuration.text = DateUtils.formatElapsedTime(trending.duration!!)
} else {
thumbnailDuration.text = holder.v.context.getString(R.string.live)
thumbnailDuration.setBackgroundColor(R.attr.colorPrimaryDark)
}
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
channelImage.setOnClickListener {
val activity = holder.v.context as MainActivity

View File

@ -42,8 +42,13 @@ class TrendingAdapter(
trending.views.formatShort() + "" +
DateUtils.getRelativeTimeSpanString(trending.uploaded!!)
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
holder.v.findViewById<TextView>(R.id.thumbnail_duration).text =
DateUtils.formatElapsedTime(trending.duration!!)
val thumbnailDuration = holder.v.findViewById<TextView>(R.id.thumbnail_duration)
if (trending.duration != -1L) {
thumbnailDuration.text = DateUtils.formatElapsedTime(trending.duration!!)
} else {
thumbnailDuration.text = holder.v.context.getString(R.string.live)
thumbnailDuration.setBackgroundColor(R.attr.colorPrimaryDark)
}
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
channelImage.setOnClickListener {
val activity = holder.v.context as MainActivity

View File

@ -13,8 +13,6 @@ import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Spinner
import android.widget.TextView
import androidx.core.app.ActivityCompat
@ -29,13 +27,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
class DownloadDialog : DialogFragment() {
private val TAG = "DownloadDialog"
var streams: Streams = Streams()
var vidName = arrayListOf<String>()
var vidUrl = arrayListOf<String>()
var audioName = arrayListOf<String>()
var audioUrl = arrayListOf<String>()
var selectedVideo = 0
var selectedAudio = 0
var extension = ".mp4"
var duration = 0
private lateinit var videoId: String
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@ -142,19 +135,13 @@ class DownloadDialog : DialogFragment() {
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
val radioGroup = view.findViewById<RadioGroup>(R.id.radioGp)
radioGroup.setOnCheckedChangeListener { group, checkedId ->
val radio: RadioButton = view.findViewById(checkedId)
extension = radio.text.toString()
Log.d(TAG, extension)
}
view.findViewById<Button>(R.id.download).setOnClickListener {
val intent = Intent(context, DownloadService::class.java)
intent.putExtra("videoId", videoId)
intent.putExtra("videoUrl", vidUrl[selectedVideo])
intent.putExtra("audioUrl", audioUrl[selectedAudio])
intent.putExtra("duration", duration)
intent.putExtra("extension", extension)
// intent.putExtra("command","-y -i ${response.videoStreams[which].url} -i ${response.audioStreams!![0].url} -c copy ${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/${videoId}.mkv")
context?.startService(intent)
dismiss()

View File

@ -10,23 +10,32 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
class UpdateAvailableDialog(
private val versionTag: String,
private val updateLink: String
private val updateLink: String,
private val updateAvailable: Boolean
) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
MaterialAlertDialogBuilder(requireContext())
.setTitle(context?.getString(R.string.update_available, versionTag))
.setMessage(context?.getString(R.string.update_available_text))
.setNegativeButton(context?.getString(R.string.cancel)) { _, _ ->
dismiss()
}
.setPositiveButton(context?.getString(R.string.okay)) { _, _ ->
val uri = Uri.parse(updateLink)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)
}
.show()
if (updateAvailable) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(context?.getString(R.string.update_available, versionTag))
.setMessage(context?.getString(R.string.update_available_text))
.setNegativeButton(context?.getString(R.string.cancel)) { _, _ ->
dismiss()
}
.setPositiveButton(context?.getString(R.string.okay)) { _, _ ->
val uri = Uri.parse(updateLink)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)
}
.show()
} else {
MaterialAlertDialogBuilder(requireContext())
.setTitle(context?.getString(R.string.app_uptodate))
.setMessage(context?.getString(R.string.no_update_available))
.setPositiveButton(context?.getString(R.string.okay)) { _, _ -> }
.show()
}
} ?: throw IllegalStateException("Activity cannot be null")
}
}

View File

@ -1,4 +1,4 @@
package com.github.libretube
package com.github.libretube.fragments
import android.os.Bundle
import android.util.Log
@ -14,6 +14,7 @@ import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.R
import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.util.RetrofitInstance
import java.io.IOException

View File

@ -1,4 +1,4 @@
package com.github.libretube
package com.github.libretube.fragments
import android.content.Context
import android.os.Bundle
@ -14,6 +14,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.R
import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.dialogs.CreatePlaylistDialog
import com.github.libretube.util.RetrofitInstance

View File

@ -43,7 +43,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.IS_DOWNLOAD_RUNNING
import com.github.libretube.MainActivity
import com.github.libretube.R
import com.github.libretube.SponsorBlockSettings
import com.github.libretube.adapters.CommentsAdapter
import com.github.libretube.adapters.TrendingAdapter
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.Streams
import com.github.libretube.obj.Subscribe
import com.github.libretube.preferences.SponsorBlockSettings
import com.github.libretube.util.CronetHelper
import com.github.libretube.util.RetrofitInstance
import com.google.android.exoplayer2.C
@ -797,6 +797,11 @@ class PlayerFragment : Fragment() {
.build()
exoPlayer.setAudioAttributes(audioAttributes, true)
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
val playbackSpeed = sharedPreferences.getString("playback_speed", "1F")?.toFloat()
exoPlayer.setPlaybackSpeed(playbackSpeed!!)
initializePlayerNotification(requireContext())
}

View File

@ -1,4 +1,4 @@
package com.github.libretube
package com.github.libretube.fragments
import android.content.Context
import android.os.Bundle
@ -23,6 +23,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.R
import com.github.libretube.adapters.SubscriptionAdapter
import com.github.libretube.adapters.SubscriptionChannelAdapter
import com.github.libretube.util.RetrofitInstance

View File

@ -0,0 +1,75 @@
package com.github.libretube.preferences
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.github.libretube.BuildConfig
import com.github.libretube.R
import com.github.libretube.util.checkUpdate
import com.google.android.material.card.MaterialCardView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class AboutFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_about, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val topBarText = activity?.findViewById<TextView>(R.id.topBar_textView)
topBarText?.text = getString(R.string.about)
val appVersion = view?.findViewById<TextView>(R.id.app_version)
appVersion.text = BuildConfig.VERSION_NAME
val website = view?.findViewById<MaterialCardView>(R.id.website)
website?.setOnClickListener {
openLink("https://libre-tube.github.io/")
}
val donate = view?.findViewById<MaterialCardView>(R.id.donate)
donate?.setOnClickListener {
openLink("https://libre-tube.github.io/#donate")
}
val contributing = view?.findViewById<MaterialCardView>(R.id.contributing)
contributing?.setOnClickListener {
openLink("https://github.com/libre-tube/LibreTube")
}
val license = view.findViewById<MaterialCardView>(R.id.license)
license?.setOnClickListener {
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
}
val update = view.findViewById<MaterialCardView>(R.id.update)
update?.setOnClickListener {
checkUpdate(childFragmentManager)
}
}
private fun openLink(link: String) {
val uri = Uri.parse(link)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)
}
}

View File

@ -0,0 +1,61 @@
package com.github.libretube.preferences
import android.content.Intent
import android.os.Bundle
import android.provider.DocumentsContract
import android.widget.TextView
import androidx.core.net.toUri
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.github.libretube.R
class AdvancedSettings : PreferenceFragmentCompat() {
val TAG = "AdvancedSettings"
private val directoryRequestCode = 9999
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.advanced_settings, rootKey)
val topBarTextView = activity?.findViewById<TextView>(R.id.topBar_textView)
topBarTextView?.text = getString(R.string.advanced)
val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener {
val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreferences.edit().remove("search_history").commit()
true
}
// doesn't work yet
val directory = findPreference<Preference>("download_directory")
directory?.setOnPreferenceClickListener {
val sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(requireContext())
val pickerInitialUri = sharedPreferences
.getString("download_directory_path", "")?.toUri()
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
startActivityForResult(
Intent.createChooser(intent, "Choose directory"),
directoryRequestCode
)
true
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
directoryRequestCode -> {
val directoryUri = data?.data
// save selected download directory to the shared preferences
val sharedPref = PreferenceManager
.getDefaultSharedPreferences(requireContext())
sharedPref.edit().putString("download_directory_path", directoryUri.toString())
.apply()
}
}
}
}

View File

@ -0,0 +1,46 @@
package com.github.libretube.preferences
import android.os.Bundle
import android.widget.TextView
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.github.libretube.R
import com.github.libretube.requireMainActivityRestart
import com.github.libretube.util.ThemeHelper
class AppearanceSettings : PreferenceFragmentCompat() {
private val TAG = "AppearanceSettings"
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.appearance_settings, rootKey)
val topBarTextView = activity?.findViewById<TextView>(R.id.topBar_textView)
topBarTextView?.text = getString(R.string.appearance)
val themeToggle = findPreference<ListPreference>("theme_togglee")
themeToggle?.setOnPreferenceChangeListener { _, _ ->
activity?.recreate()
requireMainActivityRestart = true
true
}
val accentColor = findPreference<Preference>("accent_color")
accentColor?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
activity?.recreate()
true
}
val iconChange = findPreference<ListPreference>("icon_change")
iconChange?.setOnPreferenceChangeListener { _, newValue ->
ThemeHelper().changeIcon(requireContext(), newValue.toString())
true
}
val gridColumns = findPreference<ListPreference>("grid")
gridColumns?.setOnPreferenceChangeListener { _, _ ->
requireMainActivityRestart = true
true
}
}
}

View File

@ -0,0 +1,316 @@
package com.github.libretube.preferences
import android.Manifest
import android.content.ContentResolver
import android.content.Context
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.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.ThemeHelper
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
class MainSettings : PreferenceFragmentCompat() {
val TAG = "SettingsFragment"
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)
}
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 { _, _ ->
ThemeHelper().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 appearance = findPreference<Preference>("appearance")
appearance?.setOnPreferenceClickListener {
val newFragment = AppearanceSettings()
navigateSettings(newFragment)
true
}
val sponsorblock = findPreference<Preference>("sponsorblock")
sponsorblock?.setOnPreferenceClickListener {
val newFragment = SponsorBlockSettings()
navigateSettings(newFragment)
true
}
val advanced = findPreference<Preference>("advanced")
advanced?.setOnPreferenceClickListener {
val newFragment = AdvancedSettings()
navigateSettings(newFragment)
true
}
val about = findPreference<Preference>("about")
about?.setOnPreferenceClickListener {
val newFragment = AboutFragment()
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
}
}
private fun navigateSettings(newFragment: Fragment) {
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,13 @@
package com.github.libretube
package com.github.libretube.preferences
import android.os.Bundle
import android.widget.TextView
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import com.github.libretube.R
class SponsorBlockSettings : PreferenceFragmentCompat() {
private val TAG = "SponsorBlockDialog"
private val TAG = "SponsorBlockSettings"
companion object {
var sponsorBlockEnabled: Boolean = false
@ -19,6 +21,10 @@ class SponsorBlockSettings : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.sponsorblock_settings, rootKey)
val topBarTextView = activity?.findViewById<TextView>(R.id.topBar_textView)
topBarTextView?.text = getString(R.string.sponsorblock)
val sponsorBlockToggle = findPreference<SwitchPreferenceCompat>("sb_enabled_key")
sponsorBlockToggle?.setOnPreferenceChangeListener { _, newValue ->
sponsorBlockEnabled = newValue as Boolean

View File

@ -0,0 +1,40 @@
package com.github.libretube.util
import android.content.Context
import android.os.Build
import androidx.preference.PreferenceManager
import java.util.*
class LocaleHelper {
fun updateLanguage(context: Context) {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val languageName = sharedPreferences.getString("language", "sys")
if (languageName != "") {
setLanguage(context, languageName!!)
}
}
private fun setLanguage(context: Context, languageName: String) {
val locale = if (languageName != "sys" && "$languageName".length < 3) {
Locale(languageName)
} else if ("$languageName".length > 3) {
Locale(languageName?.substring(0, 2), languageName?.substring(4, 6))
} else {
Locale.getDefault()
}
// Change API Language
Locale.setDefault(locale)
// Change App Language
val res = context.resources
val dm = res.displayMetrics
val conf = res.configuration
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
conf.setLocale(locale)
} else {
conf.locale = locale
}
res.updateConfiguration(conf, dm)
}
}

View File

@ -1,7 +1,8 @@
package com.github.libretube
package com.github.libretube.util
import android.app.Activity
import android.os.Bundle
import com.github.libretube.R
import com.google.android.material.color.DynamicColors
class Player : Activity() {

View File

@ -1,97 +0,0 @@
package com.github.libretube.util
import android.app.NotificationManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import com.github.libretube.R
import java.util.*
fun updateTheme(context: Context) {
updateAccentColor(context)
updateThemeMode(context)
}
fun updateAccentColor(context: Context) {
val colorAccent =
PreferenceManager.getDefaultSharedPreferences(context).getString("accent_color", "red")
when (colorAccent) {
"my" -> context.setTheme(R.style.Theme_MY)
"red" -> context.setTheme(R.style.Theme_Red)
"blue" -> context.setTheme(R.style.Theme_Blue)
"yellow" -> context.setTheme(R.style.Theme_Yellow)
"green" -> context.setTheme(R.style.Theme_Green)
"purple" -> context.setTheme(R.style.Theme_Purple)
}
}
fun updateThemeMode(context: Context) {
val themeMode =
PreferenceManager.getDefaultSharedPreferences(context).getString("theme_togglee", "A")
when (themeMode) {
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
"O" -> {
context.setTheme(R.style.OLED)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
}
fun updateLanguage(context: Context) {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val languageName = sharedPreferences.getString("language", "sys")
if (languageName != "") {
val locale = if (languageName != "sys" && "$languageName".length < 3) {
Locale(languageName)
} else if ("$languageName".length > 3) {
Locale(languageName?.substring(0, 2), languageName?.substring(4, 6))
} else {
Locale.getDefault()
}
val res = context.resources
val dm = res.displayMetrics
val conf = res.configuration
// Change App Language
conf.setLocale(locale)
// Change API Language
Locale.setDefault(locale)
res.updateConfiguration(conf, dm)
}
}
fun changeIcon(context: Context, newLogoActivityAlias: String) {
val activityAliases = context.resources.getStringArray(R.array.iconsValue)
// Disable Old Icon(s)
for (activityAlias in activityAliases) {
context.packageManager.setComponentEnabledSetting(
ComponentName(context.packageName, "com.github.libretube.$activityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
// Enable New Icon
context.packageManager.setComponentEnabledSetting(
ComponentName(context.packageName, "com.github.libretube.$newLogoActivityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
// Needed due to different MainActivity Aliases because of the app icons
fun restartMainActivity(context: Context) {
// kill player notification
val nManager = context
.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
nManager.cancelAll()
// restart to MainActivity
val pm: PackageManager = context.packageManager
val intent = pm.getLaunchIntentForPackage(context.packageName)
intent?.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
context.startActivity(intent)
}

View File

@ -0,0 +1,77 @@
package com.github.libretube.util
import android.app.NotificationManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import com.github.libretube.R
class ThemeHelper {
fun updateTheme(context: Context) {
updateAccentColor(context)
updateThemeMode(context)
}
fun updateAccentColor(context: Context) {
val colorAccent =
PreferenceManager.getDefaultSharedPreferences(context).getString("accent_color", "red")
when (colorAccent) {
"my" -> context.setTheme(R.style.Theme_MY)
"red" -> context.setTheme(R.style.Theme_Red)
"blue" -> context.setTheme(R.style.Theme_Blue)
"yellow" -> context.setTheme(R.style.Theme_Yellow)
"green" -> context.setTheme(R.style.Theme_Green)
"purple" -> context.setTheme(R.style.Theme_Purple)
}
}
fun updateThemeMode(context: Context) {
val themeMode =
PreferenceManager.getDefaultSharedPreferences(context).getString("theme_togglee", "A")
when (themeMode) {
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
"O" -> {
context.setTheme(R.style.OLED)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
}
fun changeIcon(context: Context, newLogoActivityAlias: String) {
val activityAliases = context.resources.getStringArray(R.array.iconsValue)
// Disable Old Icon(s)
for (activityAlias in activityAliases) {
context.packageManager.setComponentEnabledSetting(
ComponentName(context.packageName, "com.github.libretube.$activityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
// Enable New Icon
context.packageManager.setComponentEnabledSetting(
ComponentName(context.packageName, "com.github.libretube.$newLogoActivityAlias"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}
// Needed due to different MainActivity Aliases because of the app icons
fun restartMainActivity(context: Context) {
// kill player notification
val nManager = context
.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
nManager.cancelAll()
// restart to MainActivity
val pm: PackageManager = context.packageManager
val intent = pm.getLaunchIntentForPackage(context.packageName)
intent?.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
context.startActivity(intent)
}
}

View File

@ -28,7 +28,16 @@ fun checkUpdate(childFragmentManager: FragmentManager) {
if (updateInfo?.tagName != "" && BuildConfig.VERSION_NAME != updateInfo?.tagName) {
val updateAvailableDialog = UpdateAvailableDialog(
updateInfo?.tagName!!,
updateInfo?.updateUrl!!
updateInfo?.updateUrl!!,
true
)
updateAvailableDialog.show(childFragmentManager, "UpdateDialog")
} else {
// otherwise show the no update available dialog
val updateAvailableDialog = UpdateAvailableDialog(
updateInfo?.tagName!!,
updateInfo?.updateUrl!!,
false
)
updateAvailableDialog.show(childFragmentManager, "UpdateAvailableDialog")
}

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>

View File

@ -1,11 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?attr/colorControlNormal">
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M7,24Q7,27.05 8.1,29.875Q9.2,32.7 11.05,34.95L34.95,11.05Q32.65,9.1 29.85,8.05Q27.05,7 24,7Q16.9,7 11.95,11.95Q7,16.9 7,24ZM13.05,37Q15.3,38.95 18.125,39.975Q20.95,41 24,41Q31.1,41 36.05,36.05Q41,31.1 41,24Q41,20.95 39.95,18.15Q38.9,15.35 37,13.05ZM4,24Q4,19.85 5.575,16.2Q7.15,12.55 9.85,9.85Q12.55,7.15 16.2,5.575Q19.85,4 24,4Q28.15,4 31.8,5.575Q35.45,7.15 38.15,9.85Q40.85,12.55 42.425,16.2Q44,19.85 44,24Q44,28.15 42.425,31.8Q40.85,35.45 38.15,38.15Q35.45,40.85 31.8,42.425Q28.15,44 24,44Q19.85,44 16.2,42.425Q12.55,40.85 9.85,38.15Q7.15,35.45 5.575,31.8Q4,28.15 4,24Z" />
</vector>
android:pathData="M12,22.7994C11.55,22.7994 11.1,22.7094 10.74,22.4394 4.89,18.8394 1.29,12.6294 1.2,5.7894 1.2,4.8894 1.65,3.9894 2.46,3.5394 8.4,0.3894 15.6,0.3894 21.54,3.6294 22.35,3.9894 22.8,4.8894 22.8,5.7894 22.71,12.6294 19.11,18.8394 13.35,22.4394 12.9,22.7094 12.45,22.7994 12,22.7994ZM12,1.9194c-3.15,0 -6.3,0.81 -9.18,2.34 -0.54,0.27 -0.9,0.9 -0.9,1.53 0.09,6.57 3.51,12.51 9.18,16.02 0.54,0.36 1.26,0.36 1.8,0C18.57,18.3894 21.9,12.3594 22.08,5.7894 22.08,5.1594 21.72,4.5294 21.18,4.2594 18.3,2.7294 15.15,1.9194 12,1.9194Z" />
<path
android:fillColor="#FF000000"
android:pathData="M20.73,4.9794C15.24,2.0994 8.76,2.0994 3.27,4.9794 3,5.1594 2.82,5.4294 2.82,5.7894c0.09,6.48 3.51,12.06 8.73,15.3 0.27,0.18 0.63,0.18 0.9,0 5.13,-3.15 8.64,-8.82 8.73,-15.3C21.18,5.4294 21,5.1594 20.73,4.9794ZM9.66,15.1494L9.66,6.7794l7.29,4.23z" />
</vector>

View File

@ -1,11 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M12,22Q9.95,22 8.125,21.212Q6.3,20.425 4.938,19.062Q3.575,17.7 2.788,15.875Q2,14.05 2,12Q2,9.925 2.812,8.1Q3.625,6.275 5.013,4.925Q6.4,3.575 8.25,2.787Q10.1,2 12.2,2Q14.2,2 15.975,2.688Q17.75,3.375 19.087,4.588Q20.425,5.8 21.212,7.463Q22,9.125 22,11.05Q22,13.925 20.25,15.462Q18.5,17 16,17H14.15Q13.925,17 13.838,17.125Q13.75,17.25 13.75,17.4Q13.75,17.7 14.125,18.262Q14.5,18.825 14.5,19.55Q14.5,20.8 13.812,21.4Q13.125,22 12,22ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12ZM6.5,13Q7.15,13 7.575,12.575Q8,12.15 8,11.5Q8,10.85 7.575,10.425Q7.15,10 6.5,10Q5.85,10 5.425,10.425Q5,10.85 5,11.5Q5,12.15 5.425,12.575Q5.85,13 6.5,13ZM9.5,9Q10.15,9 10.575,8.575Q11,8.15 11,7.5Q11,6.85 10.575,6.425Q10.15,6 9.5,6Q8.85,6 8.425,6.425Q8,6.85 8,7.5Q8,8.15 8.425,8.575Q8.85,9 9.5,9ZM14.5,9Q15.15,9 15.575,8.575Q16,8.15 16,7.5Q16,6.85 15.575,6.425Q15.15,6 14.5,6Q13.85,6 13.425,6.425Q13,6.85 13,7.5Q13,8.15 13.425,8.575Q13.85,9 14.5,9ZM17.5,13Q18.15,13 18.575,12.575Q19,12.15 19,11.5Q19,10.85 18.575,10.425Q18.15,10 17.5,10Q16.85,10 16.425,10.425Q16,10.85 16,11.5Q16,12.15 16.425,12.575Q16.85,13 17.5,13ZM12,20Q12.225,20 12.363,19.875Q12.5,19.75 12.5,19.55Q12.5,19.2 12.125,18.725Q11.75,18.25 11.75,17.3Q11.75,16.25 12.475,15.625Q13.2,15 14.25,15H16Q17.65,15 18.825,14.037Q20,13.075 20,11.05Q20,8.025 17.688,6.012Q15.375,4 12.2,4Q8.8,4 6.4,6.325Q4,8.65 4,12Q4,15.325 6.338,17.663Q8.675,20 12,20Z" />
android:pathData="M24,44Q19.9,44 16.25,42.425Q12.6,40.85 9.875,38.125Q7.15,35.4 5.575,31.75Q4,28.1 4,24Q4,19.8 5.6,16.15Q7.2,12.5 9.975,9.8Q12.75,7.1 16.475,5.55Q20.2,4 24.45,4Q28.4,4 31.95,5.325Q35.5,6.65 38.175,9Q40.85,11.35 42.425,14.575Q44,17.8 44,21.65Q44,27.05 40.85,30.175Q37.7,33.3 32.5,33.3H28.75Q27.85,33.3 27.2,34Q26.55,34.7 26.55,35.55Q26.55,36.55 27.275,37.45Q28,38.35 28,39.6Q28,40.9 26.775,42.45Q25.55,44 24,44ZM12.35,25.3Q13.35,25.3 14.1,24.55Q14.85,23.8 14.85,22.8Q14.85,21.8 14.1,21.05Q13.35,20.3 12.35,20.3Q11.35,20.3 10.6,21.05Q9.85,21.8 9.85,22.8Q9.85,23.8 10.6,24.55Q11.35,25.3 12.35,25.3ZM18.65,16.8Q19.65,16.8 20.4,16.05Q21.15,15.3 21.15,14.3Q21.15,13.3 20.4,12.55Q19.65,11.8 18.65,11.8Q17.65,11.8 16.9,12.55Q16.15,13.3 16.15,14.3Q16.15,15.3 16.9,16.05Q17.65,16.8 18.65,16.8ZM29.35,16.8Q30.35,16.8 31.1,16.05Q31.85,15.3 31.85,14.3Q31.85,13.3 31.1,12.55Q30.35,11.8 29.35,11.8Q28.35,11.8 27.6,12.55Q26.85,13.3 26.85,14.3Q26.85,15.3 27.6,16.05Q28.35,16.8 29.35,16.8ZM35.9,25.3Q36.9,25.3 37.65,24.55Q38.4,23.8 38.4,22.8Q38.4,21.8 37.65,21.05Q36.9,20.3 35.9,20.3Q34.9,20.3 34.15,21.05Q33.4,21.8 33.4,22.8Q33.4,23.8 34.15,24.55Q34.9,25.3 35.9,25.3Z" />
</vector>

View File

@ -1,10 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM17,13l-5,5 -5,-5h3V9h4v4h3z" />
android:fillColor="#FF000000"
android:pathData="M24,32.1 L13.9,22.05 16.35,19.6 22.3,25.55V7.15H25.7V25.55L31.65,19.6L34.1,22.05ZM10.8,40.55Q9.45,40.55 8.425,39.55Q7.4,38.55 7.4,37.15V29.45H10.8V37.15Q10.8,37.15 10.8,37.15Q10.8,37.15 10.8,37.15H37.15Q37.15,37.15 37.15,37.15Q37.15,37.15 37.15,37.15V29.45H40.55V37.15Q40.55,38.55 39.55,39.55Q38.55,40.55 37.15,40.55Z" />
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z" />
</vector>

View File

@ -1,11 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="96"
android:viewportHeight="96"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:fillType="evenOdd"
android:pathData="m57.411,13.076 l-9.029,9.029 -4.941,-7.036c-5.632,-8.02 -5.066,-7.713 -8.714,-4.727l-2.772,2.269 4.077,5.695L40.11,24H29.005C9.058,24 8.009,25.489 8.004,53.8 7.998,85.455 6.068,83.991 47.8,83.996c42.13,0.005 40.193,1.452 40.193,-29.996 0,-28.3 -1.143,-30 -20.168,-30H57.55l7.245,-7.294 7.245,-7.293 -2.8,-2.683 -2.8,-2.683 -9.029,9.029M17.2,33.2c-1.695,1.695 -1.695,39.905 0,41.6 1.695,1.695 39.905,1.695 41.6,0 1.695,-1.695 1.695,-39.905 0,-41.6 -1.695,-1.695 -39.905,-1.695 -41.6,0M67.5,54v22h5.05c6.625,0 7.45,-1.019 7.45,-9.2V60h-8v-8h4c3.333,0 4,-0.333 4,-2s-0.667,-2 -4,-2h-4v-8h4c3.714,0 4,-0.2 4,-2.8 0,-4.007 -1.709,-5.2 -7.45,-5.2H67.5v22" />
android:pathData="M13.05,21.7 L24.05,4 35.05,21.7ZM35.3,44Q31.6,44 29.1,41.5Q26.6,39 26.6,35.3Q26.6,31.6 29.1,29.1Q31.6,26.6 35.3,26.6Q39,26.6 41.5,29.1Q44,31.6 44,35.3Q44,39 41.5,41.5Q39,44 35.3,44ZM6,42.75V27.55H21.2V42.75Z" />
</vector>

View File

@ -3,9 +3,8 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M5,11Q4.175,11 3.587,10.412Q3,9.825 3,9V5Q3,4.175 3.587,3.587Q4.175,3 5,3H9Q9.825,3 10.413,3.587Q11,4.175 11,5V9Q11,9.825 10.413,10.412Q9.825,11 9,11ZM5,21Q4.175,21 3.587,20.413Q3,19.825 3,19V15Q3,14.175 3.587,13.587Q4.175,13 5,13H9Q9.825,13 10.413,13.587Q11,14.175 11,15V19Q11,19.825 10.413,20.413Q9.825,21 9,21ZM15,11Q14.175,11 13.588,10.412Q13,9.825 13,9V5Q13,4.175 13.588,3.587Q14.175,3 15,3H19Q19.825,3 20.413,3.587Q21,4.175 21,5V9Q21,9.825 20.413,10.412Q19.825,11 19,11ZM15,21Q14.175,21 13.588,20.413Q13,19.825 13,19V15Q13,14.175 13.588,13.587Q14.175,13 15,13H19Q19.825,13 20.413,13.587Q21,14.175 21,15V19Q21,19.825 20.413,20.413Q19.825,21 19,21ZM5,9H9V5H5ZM15,9H19V5H15ZM15,19H19V15H15ZM5,19H9V15H5ZM15,9ZM15,15ZM9,15ZM9,9Z" />
android:pathData="M5,21Q4.175,21 3.587,20.413Q3,19.825 3,19V5Q3,4.175 3.587,3.587Q4.175,3 5,3H11V21ZM13,21V12H21V19Q21,19.825 20.413,20.413Q19.825,21 19,21ZM13,10V3H19Q19.825,3 20.413,3.587Q21,4.175 21,5V10Z" />
</vector>

View File

@ -1,11 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M6.75,15Q7.075,15 7.287,14.787Q7.5,14.575 7.5,14.25V13H9.5V14.25Q9.5,14.575 9.713,14.787Q9.925,15 10.25,15Q10.575,15 10.788,14.787Q11,14.575 11,14.25V9.75Q11,9.425 10.788,9.212Q10.575,9 10.25,9Q9.925,9 9.713,9.212Q9.5,9.425 9.5,9.75V11.5H7.5V9.75Q7.5,9.425 7.287,9.212Q7.075,9 6.75,9Q6.425,9 6.213,9.212Q6,9.425 6,9.75V14.25Q6,14.575 6.213,14.787Q6.425,15 6.75,15ZM13.5,15H17Q17.425,15 17.712,14.712Q18,14.425 18,14V10Q18,9.575 17.712,9.287Q17.425,9 17,9H13.5Q13.3,9 13.15,9.15Q13,9.3 13,9.5V14.5Q13,14.7 13.15,14.85Q13.3,15 13.5,15ZM14.5,13.5V10.5H16.5Q16.5,10.5 16.5,10.5Q16.5,10.5 16.5,10.5V13.5Q16.5,13.5 16.5,13.5Q16.5,13.5 16.5,13.5ZM4,20Q3.175,20 2.588,19.413Q2,18.825 2,18V6Q2,5.175 2.588,4.588Q3.175,4 4,4H20Q20.825,4 21.413,4.588Q22,5.175 22,6V18Q22,18.825 21.413,19.413Q20.825,20 20,20ZM4,18Q4,18 4,18Q4,18 4,18V6Q4,6 4,6Q4,6 4,6Q4,6 4,6Q4,6 4,6V18Q4,18 4,18Q4,18 4,18ZM4,18H20Q20,18 20,18Q20,18 20,18V6Q20,6 20,6Q20,6 20,6H4Q4,6 4,6Q4,6 4,6V18Q4,18 4,18Q4,18 4,18Z" />
android:pathData="M12,30.15H14.5V25.7H19.5V30.15H22V17.85H19.5V23.2H14.5V17.85H12ZM26,30.15H33.5Q34.5,30.15 35.25,29.4Q36,28.65 36,27.65V20.35Q36,19.35 35.25,18.6Q34.5,17.85 33.5,17.85H26ZM28.5,27.65V20.35H33.5Q33.5,20.35 33.5,20.35Q33.5,20.35 33.5,20.35V27.65Q33.5,27.65 33.5,27.65Q33.5,27.65 33.5,27.65ZM7,40Q5.8,40 4.9,39.1Q4,38.2 4,37V11Q4,9.8 4.9,8.9Q5.8,8 7,8H41Q42.2,8 43.1,8.9Q44,9.8 44,11V37Q44,38.2 43.1,39.1Q42.2,40 41,40Z" />
</vector>

View File

@ -1,10 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,17Q12.425,17 12.713,16.712Q13,16.425 13,16V11.975Q13,11.55 12.713,11.275Q12.425,11 12,11Q11.575,11 11.288,11.287Q11,11.575 11,12V16.025Q11,16.45 11.288,16.725Q11.575,17 12,17ZM12,9Q12.425,9 12.713,8.712Q13,8.425 13,8Q13,7.575 12.713,7.287Q12.425,7 12,7Q11.575,7 11.288,7.287Q11,7.575 11,8Q11,8.425 11.288,8.712Q11.575,9 12,9ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12ZM12,20Q15.325,20 17.663,17.663Q20,15.325 20,12Q20,8.675 17.663,6.337Q15.325,4 12,4Q8.675,4 6.338,6.337Q4,8.675 4,12Q4,15.325 6.338,17.663Q8.675,20 12,20Z" />
android:fillColor="#FF000000"
android:pathData="M24,44Q19.75,44 16.1,42.475Q12.45,40.95 9.75,38.25Q7.05,35.55 5.525,31.9Q4,28.25 4,24Q4,19.8 5.525,16.15Q7.05,12.5 9.75,9.8Q12.45,7.1 16.1,5.55Q19.75,4 24,4Q28.2,4 31.85,5.55Q35.5,7.1 38.2,9.8Q40.9,12.5 42.45,16.15Q44,19.8 44,24Q44,28.25 42.45,31.9Q40.9,35.55 38.2,38.25Q35.5,40.95 31.85,42.475Q28.2,44 24,44ZM24,18.3Q24.7,18.3 25.175,17.85Q25.65,17.4 25.65,16.7Q25.65,16 25.175,15.5Q24.7,15 24,15Q23.3,15 22.825,15.5Q22.35,16 22.35,16.7Q22.35,17.4 22.825,17.85Q23.3,18.3 24,18.3ZM22.65,34H25.65V22H22.65Z" />
</vector>

View File

@ -5,6 +5,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:fillColor="@android:color/black"
android:pathData="M4,14h4v-4L4,10v4zM4,19h4v-4L4,15v4zM4,9h4L8,5L4,5v4zM9,14h12v-4L9,10v4zM9,19h12v-4L9,15v4zM9,5v4h12L21,5L9,5z" />
</vector>
</vector>

View File

@ -1,11 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M7.5,6Q6.875,6 6.438,6.438Q6,6.875 6,7.5Q6,8.125 6.438,8.562Q6.875,9 7.5,9Q8.125,9 8.562,8.562Q9,8.125 9,7.5Q9,6.875 8.562,6.438Q8.125,6 7.5,6ZM7.5,16Q6.875,16 6.438,16.438Q6,16.875 6,17.5Q6,18.125 6.438,18.562Q6.875,19 7.5,19Q8.125,19 8.562,18.562Q9,18.125 9,17.5Q9,16.875 8.562,16.438Q8.125,16 7.5,16ZM4,3H20Q20.425,3 20.712,3.287Q21,3.575 21,4V11Q21,11.425 20.712,11.712Q20.425,12 20,12H4Q3.575,12 3.288,11.712Q3,11.425 3,11V4Q3,3.575 3.288,3.287Q3.575,3 4,3ZM5,5V10H19V5ZM4,13H20Q20.425,13 20.712,13.287Q21,13.575 21,14V21Q21,21.425 20.712,21.712Q20.425,22 20,22H4Q3.575,22 3.288,21.712Q3,21.425 3,21V14Q3,13.575 3.288,13.287Q3.575,13 4,13ZM5,15V20H19V15ZM5,5V10ZM5,15V20Z" />
android:pathData="M7.7,23.3Q6.95,23.3 6.475,22.7Q6,22.1 6,21.25V7.8Q6,7 6.475,6.525Q6.95,6.05 7.7,6.05H40.25Q41.05,6.05 41.525,6.525Q42,7 42,7.8V21.25Q42,22.1 41.525,22.7Q41.05,23.3 40.25,23.3ZM14.35,17.15Q15.4,17.15 16.125,16.425Q16.85,15.7 16.85,14.65Q16.85,13.6 16.125,12.875Q15.4,12.15 14.35,12.15Q13.3,12.15 12.575,12.875Q11.85,13.6 11.85,14.65Q11.85,15.7 12.575,16.425Q13.3,17.15 14.35,17.15ZM7.95,44Q7.15,44 6.575,43.475Q6,42.95 6,41.95V28.75Q6,27.95 6.475,27.325Q6.95,26.7 7.7,26.7H40.05Q40.8,26.7 41.4,27.325Q42,27.95 42,28.75V41.95Q42,42.95 41.4,43.475Q40.8,44 40.05,44ZM14.35,37.85Q15.4,37.85 16.125,37.125Q16.85,36.4 16.85,35.35Q16.85,34.3 16.125,33.575Q15.4,32.85 14.35,32.85Q13.3,32.85 12.575,33.575Q11.85,34.3 11.85,35.35Q11.85,36.4 12.575,37.125Q13.3,37.85 14.35,37.85Z" />
</vector>

View File

@ -1,10 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" />
android:fillColor="#FF000000"
android:pathData="M36.35,44Q34,44 32.325,42.325Q30.65,40.65 30.65,38.3Q30.65,37.95 30.725,37.475Q30.8,37 30.95,36.6L15.8,27.8Q15.05,28.65 13.95,29.175Q12.85,29.7 11.7,29.7Q9.35,29.7 7.675,28.025Q6,26.35 6,24Q6,21.6 7.675,19.95Q9.35,18.3 11.7,18.3Q12.85,18.3 13.9,18.75Q14.95,19.2 15.8,20.05L30.95,11.35Q30.8,11 30.725,10.55Q30.65,10.1 30.65,9.7Q30.65,7.3 32.325,5.65Q34,4 36.35,4Q38.75,4 40.4,5.65Q42.05,7.3 42.05,9.7Q42.05,12.05 40.4,13.725Q38.75,15.4 36.35,15.4Q35.2,15.4 34.125,15.025Q33.05,14.65 32.3,13.8L17.15,22.2Q17.25,22.6 17.325,23.125Q17.4,23.65 17.4,24Q17.4,24.35 17.325,24.75Q17.25,25.15 17.15,25.55L32.3,34.15Q33.05,33.45 34.05,33.025Q35.05,32.6 36.35,32.6Q38.75,32.6 40.4,34.25Q42.05,35.9 42.05,38.3Q42.05,40.65 40.4,42.325Q38.75,44 36.35,44Z" />
</vector>

View File

@ -1,11 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:width="24dp"
android:viewportHeight="48"
android:tint="?attr/colorControlNormal">
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M24,42Q16.5,42 11.25,36.75Q6,31.5 6,24Q6,17.25 9.975,12.55Q13.95,7.85 20.4,6.5Q22.45,6.1 23.2,7.2Q23.95,8.3 23.15,10.2Q22.7,11.35 22.45,12.55Q22.2,13.75 22.2,15Q22.2,19.5 25.35,22.65Q28.5,25.8 33,25.8Q34.25,25.8 35.425,25.575Q36.6,25.35 37.7,24.95Q39.85,24.15 40.9,25.025Q41.95,25.9 41.45,28Q40.1,34.05 35.4,38.025Q30.7,42 24,42ZM24,39Q29.45,39 33.5,35.625Q37.55,32.25 38.55,27.7Q37.3,28.25 35.875,28.525Q34.45,28.8 33,28.8Q27.25,28.8 23.225,24.775Q19.2,20.75 19.2,15Q19.2,13.8 19.45,12.425Q19.7,11.05 20.35,9.3Q15.45,10.65 12.225,14.775Q9,18.9 9,24Q9,30.25 13.375,34.625Q17.75,39 24,39ZM23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Q23.8,24.15 23.8,24.15Z" />
android:pathData="M24,42Q16.5,42 11.25,36.75Q6,31.5 6,24Q6,16.5 11.25,11.25Q16.5,6 24,6Q24.4,6 24.85,6.025Q25.3,6.05 26,6.1Q24.2,7.7 23.2,10.05Q22.2,12.4 22.2,15Q22.2,19.5 25.35,22.65Q28.5,25.8 33,25.8Q35.6,25.8 37.95,24.875Q40.3,23.95 41.9,22.3Q41.95,22.9 41.975,23.275Q42,23.65 42,24Q42,31.5 36.75,36.75Q31.5,42 24,42Z" />
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z" />
</vector>

View File

@ -3,14 +3,14 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Player"
android:background="@color/black">
tools:context=".util.Player"
android:background="@android:color/black">
<com.github.libretube.util.CustomExoPlayerView
android:id="@+id/fullscreen_player"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black" />
android:background="@android:color/black" />
</RelativeLayout>

View File

@ -1,9 +1,35 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/back_imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginVertical="10dp"
android:backgroundTint="@android:color/transparent"
android:src="@drawable/ic_arrow_back" />
<TextView
android:id="@+id/topBar_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings"
android:layout_marginLeft="14dp"
android:textSize="20sp"
android:layout_gravity="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/settings"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -35,6 +35,6 @@
android:layout_alignParentEnd="true"
android:backgroundTint="?attr/colorOnPrimary"
android:text="@string/unsubscribe"
android:textColor="@color/white"
android:textColor="@android:color/white"
app:cornerRadius="20dp" />
</RelativeLayout>

View File

@ -26,29 +26,6 @@
android:layout_height="wrap_content"
android:layout_margin="8dp" />
<RadioGroup
android:id="@+id/radioGp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="8dp"
android:visibility="gone" >
<RadioButton
android:id="@+id/mkv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=".mkv"
android:layout_marginRight="16dp"
android:checked="true" />
<RadioButton
android:id="@+id/mp4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=".mp4" />
</RadioGroup>
<Button
android:id="@+id/download"
android:layout_width="wrap_content"
@ -61,4 +38,5 @@
android:padding="8dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp" />
</LinearLayout>

View File

@ -52,7 +52,7 @@
android:src="@drawable/ic_close"
android:padding="@dimen/exo_icon_padding"
android:background="#00FFFFFF"
app:tint="@color/white" />
app:tint="@android:color/white" />
</LinearLayout>
<LinearLayout
@ -90,7 +90,7 @@
android:src="@drawable/ic_arrow_down"
android:padding="@dimen/exo_icon_padding"
android:background="#00FFFFFF"
app:tint="@color/white" />
app:tint="@android:color/white" />
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
style="@style/roundedImageViewRounded"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="LibreTube"
android:textSize="27sp"
android:textStyle="bold" />
<TextView
android:id="@+id/app_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:layout_marginBottom="30dp"
android:textSize="18sp" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/website"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="16dp"
android:padding="20dp"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:text="@string/website"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:text="@string/website_summary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/contributing"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="16dp"
android:padding="20dp"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:text="@string/contributing"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:text="@string/contributing_summary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/donate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="16dp"
android:padding="20dp"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:text="@string/donate"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:text="@string/donate_summary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="16dp"
android:padding="20dp"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:text="@string/license"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:text="@string/license_summary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="20dp"
android:padding="20dp"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="10dp"
android:text="@string/update"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="10dp"
android:text="@string/update_summary" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Home">
tools:context=".fragments.Home">
<ProgressBar
android:id="@+id/progressBar"

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Library">
tools:context=".fragments.Library">
<RelativeLayout
android:id="@+id/loginOrRegister2"

View File

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

View File

@ -33,28 +33,28 @@
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
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"
<com.google.android.material.textfield.TextInputLayout
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"
android:dropDownWidth="match_parent"
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:padding="12dp" />
app:hintEnabled="false">
</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
android:id="@+id/clearSearch_imageView"
@ -65,7 +65,7 @@
android:layout_centerVertical="true"
android:layout_marginRight="16dp" />
</RelativeLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<ImageView

View File

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Subscriptions">
tools:context=".fragments.Subscriptions">
<ProgressBar
android:id="@+id/sub_progress"

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Some files were not shown because too many files have changed in this diff Show More