Merge pull request #253 from Bnyro/theming

Accent colors and OLED Mode
This commit is contained in:
Farbod 2022-05-20 16:44:57 +04:30 committed by GitHub
commit 45f87649f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 1186 additions and 984 deletions

View File

@ -1,13 +1,11 @@
package com.github.libretube
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*

View File

@ -14,7 +14,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_libretube_round"
android:supportsRtl="true"
android:theme="@style/Theme.LibreTube"
android:theme="@style/Theme.MY"
android:name=".myApp"
android:networkSecurityConfig="@xml/network_security_config"
android:largeHeap="true"

View File

@ -12,7 +12,6 @@ import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.obj.PlaylistId
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import retrofit2.HttpException
@ -29,7 +28,7 @@ class AddtoPlaylistDialog : DialogFragment() {
videoId = arguments?.getString("videoId")!!
val builder = MaterialAlertDialogBuilder(it)
// Get the layout inflater
val inflater = requireActivity().layoutInflater;
val inflater = requireActivity().layoutInflater
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
token = sharedPref?.getString("token", "")!!
var view: View = inflater.inflate(R.layout.dialog_addtoplaylist, null)
@ -80,9 +79,7 @@ class AddtoPlaylistDialog : DialogFragment() {
}
}
} else {
}
}
}
run()
@ -108,7 +105,6 @@ class AddtoPlaylistDialog : DialogFragment() {
} else {
Toast.makeText(context, R.string.fail, Toast.LENGTH_SHORT).show()
}
}
}
run()

View File

@ -1,13 +1,10 @@
package com.github.libretube
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.text.TextUtils.substring
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -23,9 +20,8 @@ import com.github.libretube.adapters.ChannelAdapter
import com.github.libretube.obj.Subscribe
import com.google.android.material.button.MaterialButton
import com.squareup.picasso.Picasso
import retrofit2.HttpException
import java.io.IOException
import retrofit2.HttpException
class ChannelFragment : Fragment() {
@ -45,13 +41,12 @@ class ChannelFragment : Fragment() {
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_channel, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -81,18 +76,16 @@ class ChannelFragment : Fragment() {
scrollView.viewTreeObserver
.addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) {
== (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom
if (nextPage != null && !isLoading) {
isLoading = true
refreshLayout?.isRefreshing = true;
refreshLayout?.isRefreshing = true
fetchNextPage()
}
}
}
}
private fun isSubscribed(button: MaterialButton) {
@ -125,7 +118,8 @@ class ChannelFragment : Fragment() {
subscribe()
button.text = getString(R.string.unsubscribe)
}
}}
}
}
}
}
}
@ -177,18 +171,18 @@ class ChannelFragment : Fragment() {
val response = try {
RetrofitInstance.api.getChannel(channel_id!!)
} catch (e: IOException) {
refreshLayout?.isRefreshing = false;
refreshLayout?.isRefreshing = false
println(e)
Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
refreshLayout?.isRefreshing = false;
refreshLayout?.isRefreshing = false
Log.e(TAG, "HttpException, unexpected response")
return@launchWhenCreated
}
nextPage = response.nextpage
isLoading = false
refreshLayout?.isRefreshing = false;
refreshLayout?.isRefreshing = false
runOnUiThread {
view.findViewById<ScrollView>(R.id.channel_scrollView).visibility = View.VISIBLE
val channelName = view.findViewById<TextView>(R.id.channel_name)
@ -204,7 +198,6 @@ class ChannelFragment : Fragment() {
Picasso.get().load(response.avatarUrl).into(channelImage)
channelAdapter = ChannelAdapter(response.relatedStreams!!.toMutableList())
view.findViewById<RecyclerView>(R.id.channel_recView).adapter = channelAdapter
}
}
}

View File

@ -42,8 +42,7 @@ class CreatePlaylistDialog : DialogFragment() {
if (listName != "") {
setFragmentResult("key_parent", bundleOf("playlistName" to "$listName"))
dismiss()
}
else {
} else {
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
}
}

View File

@ -4,12 +4,11 @@ import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.ui.StyledPlayerControlView
import com.google.android.exoplayer2.ui.StyledPlayerView
internal class CustomExoPlayerView(
context: Context, attributeSet: AttributeSet? = null
context: Context,
attributeSet: AttributeSet? = null
) : StyledPlayerView(context, attributeSet) {
@SuppressLint("ClickableViewAccessibility")

View File

@ -12,7 +12,6 @@ import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class DownloadDialog : DialogFragment() {
private val TAG = "DownloadDialog"
var vidName = arrayListOf<String>()

View File

@ -16,7 +16,6 @@ import androidx.core.app.NotificationManagerCompat
import com.arthenica.ffmpegkit.FFmpegKit
import java.io.File
var IS_DOWNLOAD_RUNNING = false
class DownloadService : Service() {
val TAG = "DownloadService"
@ -46,8 +45,10 @@ class DownloadService : Service(){
service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val chan = NotificationChannel("service",
"DownloadService", NotificationManager.IMPORTANCE_NONE)
val chan = NotificationChannel(
"service",
"DownloadService", NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
service.createNotificationChannel(chan)
@ -128,11 +129,10 @@ class DownloadService : Service(){
val downloadManager: DownloadManager =
applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
downloadManager.enqueue(request)
} catch (e: Exception) {
Log.e(TAG, "audio download error $e")
stopService(Intent(this,DownloadService::class.java))}
stopService(Intent(this, DownloadService::class.java))
}
}
}
@ -166,17 +166,18 @@ class DownloadService : Service(){
}
var command: String = when {
videoUrl == "" -> {
"-y -i $audioDir -c copy ${libreTube}/${videoId}-audio$extension"
"-y -i $audioDir -c copy $libreTube/$videoId-audio$extension"
}
audioUrl == "" -> {
"-y -i $videoDir -c copy ${libreTube}/${videoId}-video$extension"
"-y -i $videoDir -c copy $libreTube/$videoId-video$extension"
}
else -> {
"-y -i $videoDir -i $audioDir -c copy ${libreTube}/${videoId}$extension"
"-y -i $videoDir -i $audioDir -c copy $libreTube/${videoId}$extension"
}
}
notification.setContentTitle("Muxing")
FFmpegKit.executeAsync(command,
FFmpegKit.executeAsync(
command,
{ session ->
val state = session.state
val returnCode = session.returnCode
@ -211,7 +212,8 @@ class DownloadService : Service(){
}, {
// CALLED WHEN SESSION PRINTS LOGS
Log.e(TAG, it.message.toString())
}) {
}
) {
// CALLED WHEN SESSION GENERATES STATISTICS
Log.e(TAG + "stat", it.time.toString())
/*val progress = it.time/(10*duration!!)
@ -221,7 +223,6 @@ class DownloadService : Service(){
service.notify(1,notification.build())
}*/
}
}
}
}
@ -250,5 +251,4 @@ class DownloadService : Service(){
Log.d(TAG, "dl finished!")
super.onDestroy()
}
}

View File

@ -2,23 +2,21 @@ package com.github.libretube
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import okhttp3.*
import retrofit2.HttpException
import com.github.libretube.adapters.TrendingAdapter
import java.io.IOException
import okhttp3.*
import retrofit2.HttpException
class Home : Fragment() {
@ -31,13 +29,13 @@ class Home : Fragment() {
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -54,12 +52,8 @@ class Home : Fragment() {
Log.d(TAG, "hmm")
fetchJson(progressbar, recyclerView)
}
}
private fun fetchJson(progressBar: ProgressBar, recyclerView: RecyclerView) {
fun run() {
lifecycleScope.launchWhenCreated {
@ -85,7 +79,6 @@ class Home : Fragment() {
}
}
run()
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return

View File

@ -17,9 +17,8 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.PlaylistsAdapter
import com.github.libretube.obj.Playlists
import retrofit2.HttpException
import java.io.IOException
import retrofit2.HttpException
class Library : Fragment() {
@ -30,12 +29,12 @@ class Library : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
@ -64,7 +63,7 @@ class Library : Fragment() {
}
childFragmentManager.setFragmentResultListener("key_parent", this) { _, result ->
val playlistName = result.getString("playlistName")
createPlaylist("$playlistName", view);
createPlaylist("$playlistName", view)
}
} else {
refreshLayout?.isEnabled = false
@ -121,7 +120,6 @@ class Library : Fragment() {
}
}
}
}
}
run()
@ -145,9 +143,7 @@ class Library : Fragment() {
Toast.makeText(context, R.string.playlistCreated, Toast.LENGTH_SHORT).show()
fetchPlaylists(view)
} else {
}
}
}
run()

View File

@ -2,7 +2,6 @@ package com.github.libretube
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
@ -15,15 +14,12 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.obj.Login
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.w3c.dom.Text
import retrofit2.HttpException
import java.io.IOException
import java.lang.Exception
import kotlin.math.log
class LoginDialog : DialogFragment() {
private val TAG = "LoginDialog"
@ -33,7 +29,7 @@ class LoginDialog : DialogFragment() {
return activity?.let {
val builder = MaterialAlertDialogBuilder(it)
// Get the layout inflater
val inflater = requireActivity().layoutInflater;
val inflater = requireActivity().layoutInflater
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
val token = sharedPref?.getString("token", "")
var view: View
@ -122,7 +118,6 @@ class LoginDialog : DialogFragment() {
}
dialog?.dismiss()
}
}
}
run()
@ -161,10 +156,8 @@ class LoginDialog : DialogFragment() {
}
dialog?.dismiss()
}
}
}
run()
}
}

View File

@ -17,7 +17,6 @@ import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.Toolbar
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.constraintlayout.widget.ConstraintLayout
@ -30,7 +29,6 @@ import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.color.DynamicColors
import java.util.*
class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
@ -50,42 +48,21 @@ class MainActivity : AppCompatActivity() {
SponsorBlockSettings.sponsorsEnabled = sharedPreferences.getBoolean("sponsors_category_key", false)
SponsorBlockSettings.outroEnabled = sharedPreferences.getBoolean("outro_category_key", false)
val languageName = sharedPreferences.getString("language", "sys")
if (languageName != "") {
var 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 = resources
val dm = res.displayMetrics
val conf = res.configuration
conf.setLocale(locale)
Locale.setDefault(locale)
res.updateConfiguration(conf, dm)
}
when (sharedPreferences.getString("theme_togglee", "A")!!) {
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
"D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
updateAccentColor(this)
updateThemeMode(this)
updateLanguage(this)
val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
val isConnected = networkInfo != null && networkInfo.isConnected
if (isConnected == false) {
if (!isConnected) {
setContentView(R.layout.activity_nointernet)
findViewById<Button>(R.id.retry_button).setOnClickListener() {
recreate()
}
} else {
setContentView(R.layout.activity_main)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
bottomNavigationView = findViewById(R.id.bottomNav)
@ -98,6 +75,7 @@ class MainActivity : AppCompatActivity() {
"library" -> navController.navigate(R.id.library)
}
bottomNavigationView.setBackgroundColor(0) // otherwise Navbar Theme doesn't change
bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home2 -> {
@ -121,7 +99,7 @@ class MainActivity : AppCompatActivity() {
toolbar = findViewById(R.id.toolbar)
val typedValue = TypedValue()
this.theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true)
this.theme.resolveAttribute(R.attr.colorPrimary, typedValue, true)
val hexColor = String.format("#%06X", (0xFFFFFF and typedValue.data))
val appName = HtmlCompat.fromHtml(
"Libre<span style='color:$hexColor';>Tube</span>",
@ -146,7 +124,6 @@ class MainActivity : AppCompatActivity() {
false
}
}
}
override fun onStart() {
@ -168,8 +145,7 @@ class MainActivity : AppCompatActivity() {
navController.navigate(R.id.channel, bundle)
} else if (data.path!!.contains("/playlist")) {
var playlist = data.query!!
if (playlist.contains("&"))
{
if (playlist.contains("&")) {
var playlists = playlist.split("&")
for (v in playlists) {
if (v.contains("list=")) {
@ -201,8 +177,7 @@ class MainActivity : AppCompatActivity() {
} else if (data.path!!.contains("/watch") && data.query != null) {
Log.d("dafaq", data.query!!)
var watch = data.query!!
if (watch.contains("&"))
{
if (watch.contains("&")) {
var watches = watch.split("&")
for (v in watches) {
if (v.contains("v=")) {
@ -226,7 +201,6 @@ class MainActivity : AppCompatActivity() {
motionLayout.transitionToEnd()
motionLayout.transitionToStart()
}, 100)
} else {
var watch = data.path!!.replace("/", "")
var bundle = Bundle()
@ -246,9 +220,7 @@ class MainActivity : AppCompatActivity() {
}, 100)
}
}
}
}
}
@ -303,12 +275,14 @@ class MainActivity : AppCompatActivity() {
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_FULLSCREEN
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_IMMERSIVE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
)
}
}
private fun unsetFullscreen() {
@ -335,7 +309,6 @@ class MainActivity : AppCompatActivity() {
(fragment as? PlayerFragment)?.onUserLeaveHint()
}
}
}
fun Fragment.hideKeyboard() {
view?.let { activity?.hideKeyboard(it) }

View File

@ -17,7 +17,10 @@ interface PipedApi {
suspend fun getSegments(@Path("videoId") videoId: String, @Query("category") category: String): Segments
@GET("nextpage/comments/{videoId}")
suspend fun getCommentsNextPage(@Path("videoId") videoId: String, @Query("nextpage") nextPage: String): CommentsPage
suspend fun getCommentsNextPage(
@Path("videoId") videoId: String,
@Query("nextpage") nextPage: String
): CommentsPage
@GET("search")
suspend fun getSearchResults(
@ -39,13 +42,19 @@ interface PipedApi {
suspend fun getChannel(@Path("channelId") channelId: String): Channel
@GET("nextpage/channel/{channelId}")
suspend fun getChannelNextPage(@Path("channelId") channelId: String, @Query("nextpage") nextPage: String): Channel
suspend fun getChannelNextPage(
@Path("channelId") channelId: String,
@Query("nextpage") nextPage: String
): Channel
@GET("playlists/{playlistId}")
suspend fun getPlaylist(@Path("playlistId") playlistId: String): Playlist
@GET("nextpage/playlists/{playlistId}")
suspend fun getPlaylistNextPage(@Path("playlistId") playlistId: String, @Query("nextpage") nextPage: String): Playlist
suspend fun getPlaylistNextPage(
@Path("playlistId") playlistId: String,
@Query("nextpage") nextPage: String
): Playlist
@POST("login")
suspend fun login(@Body login: Login): Token
@ -57,7 +66,10 @@ interface PipedApi {
suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem>
@GET("subscribed")
suspend fun isSubscribed(@Query("channelId") channelId: String, @Header("Authorization") token: String): Subscribed
suspend fun isSubscribed(
@Query("channelId") channelId: String,
@Header("Authorization") token: String
): Subscribed
@GET("subscriptions")
suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription>
@ -69,7 +81,11 @@ interface PipedApi {
suspend fun unsubscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message
@POST("import")
suspend fun importSubscriptions(@Query("override") override: Boolean, @Header("Authorization") token: String, @Body channels: List<String>): Message
suspend fun importSubscriptions(
@Query("override") override: Boolean,
@Header("Authorization") token: String,
@Body channels: List<String>
): Message
@GET("user/playlists")
suspend fun playlists(@Header("Authorization") token: String): List<Playlists>
@ -84,12 +100,12 @@ interface PipedApi {
suspend fun addToPlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message
@POST("user/playlists/remove")
suspend fun removeFromPlaylist(@Header("Authorization") token: String, @Body playlistId: PlaylistId): Message
suspend fun removeFromPlaylist(
@Header("Authorization") token: String,
@Body playlistId: PlaylistId
): Message
// only for fetching servers list
@GET
suspend fun getInstances(@Url url: String): List<Instances>
}

View File

@ -8,20 +8,11 @@ import com.google.android.material.color.DynamicColors
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class Player : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
DynamicColors.applyToActivityIfAvailable(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
}
}

View File

@ -58,13 +58,12 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.util.RepeatModeUtil
import com.google.android.material.button.MaterialButton
import com.squareup.picasso.Picasso
import org.chromium.net.CronetEngine
import retrofit2.HttpException
import java.io.IOException
import java.net.URLEncoder
import java.util.concurrent.Executors
import kotlin.math.abs
import org.chromium.net.CronetEngine
import retrofit2.HttpException
var isFullScreen = false
@ -247,7 +246,6 @@ class PlayerFragment : Fragment() {
) {
fetchNextComments()
}
}
commentsRecView = view.findViewById(R.id.comments_recView)
@ -274,8 +272,7 @@ class PlayerFragment : Fragment() {
}
}
private fun checkForSegments()
{
private fun checkForSegments() {
if (!exoPlayer.isPlaying || !SponsorBlockSettings.sponsorBlockEnabled) return
exoPlayerView.postDelayed(this::checkForSegments, 100)
@ -289,7 +286,7 @@ class PlayerFragment : Fragment() {
val currentPosition = exoPlayer.currentPosition
if (currentPosition in segmentStart until segmentEnd) {
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT).show()
exoPlayer.seekTo(segmentEnd);
exoPlayer.seekTo(segmentEnd)
}
}
}
@ -401,10 +398,10 @@ class PlayerFragment : Fragment() {
exoPlayerView.setShowSubtitleButton(true)
exoPlayerView.setShowNextButton(false)
exoPlayerView.setShowPreviousButton(false)
exoPlayerView.setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL);
exoPlayerView.setRepeatToggleModes(RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL)
// exoPlayerView.controllerShowTimeoutMs = 1500
exoPlayerView.controllerHideOnTouch = true
exoPlayer.setAudioAttributes(audioAttributes,true);
exoPlayer.setAudioAttributes(audioAttributes, true)
exoPlayerView.player = exoPlayer
val sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(requireContext())
@ -433,9 +430,11 @@ class PlayerFragment : Fragment() {
ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(
fromUri(
response.audioStreams!![getMostBitRate(
response.audioStreams!![
getMostBitRate(
response.audioStreams
)].url!!
)
].url!!
)
)
}
@ -479,9 +478,11 @@ class PlayerFragment : Fragment() {
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(
fromUri(
response.audioStreams!![getMostBitRate(
response.audioStreams!![
getMostBitRate(
response.audioStreams
)].url!!
)
].url!!
)
)
}
@ -545,9 +546,11 @@ class PlayerFragment : Fragment() {
ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(
fromUri(
response.audioStreams!![getMostBitRate(
response.audioStreams!![
getMostBitRate(
response.audioStreams
)].url!!
)
].url!!
)
)
}
@ -555,7 +558,7 @@ class PlayerFragment : Fragment() {
MergingMediaSource(videoSource, audioSource)
exoPlayer.setMediaSource(mergeSource)
}
exoPlayer.seekTo(lastPosition);
exoPlayer.seekTo(lastPosition)
view.findViewById<TextView>(R.id.quality_text).text =
videosNameArray[which]
}
@ -566,8 +569,7 @@ class PlayerFragment : Fragment() {
// Listener for play and pause icon change
exoPlayer!!.addListener(object : com.google.android.exoplayer2.Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
if(isPlaying && SponsorBlockSettings.sponsorBlockEnabled)
{
if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) {
exoPlayerView.postDelayed(this@PlayerFragment::checkForSegments, 100)
}
}
@ -772,7 +774,6 @@ class PlayerFragment : Fragment() {
return@launchWhenCreated
}
runOnUiThread {
if (response.subscribed == true) {
isSubscribed = true
@ -898,7 +899,7 @@ class PlayerFragment : Fragment() {
view?.findViewById<FrameLayout>(R.id.top_bar)?.visibility = View.GONE
val mainActivity = activity as MainActivity
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
isFullScreen = false;
isFullScreen = false
} else {
with(motionLayout) {
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
@ -917,6 +918,6 @@ class PlayerFragment : Fragment() {
if (SDK_INT >= Build.VERSION_CODES.N && exoPlayer.isPlaying && (scrollView?.getLocalVisibleRect(bounds) == true || isFullScreen)) {
requireActivity().enterPictureInPictureMode()
};
}
}
}

View File

@ -3,22 +3,18 @@ package com.github.libretube
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ScrollView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.adapters.ChannelAdapter
import com.github.libretube.adapters.PlaylistAdapter
import com.squareup.picasso.Picasso
import retrofit2.HttpException
import java.io.IOException
import retrofit2.HttpException
class PlaylistFragment : Fragment() {
private var playlist_id: String? = null
@ -34,7 +30,8 @@ class PlaylistFragment : Fragment() {
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
@ -82,13 +79,13 @@ class PlaylistFragment : Fragment() {
scrollView.viewTreeObserver
.addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) {
== (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom
if (nextPage != null && !isLoading) {
isLoading = true
fetchNextPage()
}
} else {
// scroll view is not at bottom
}
@ -116,7 +113,6 @@ class PlaylistFragment : Fragment() {
nextPage = response.nextpage
playlistAdapter?.updateItems(response.relatedStreams!!)
isLoading = false
}
}
run()

View File

@ -13,5 +13,4 @@ object RetrofitInstance {
.build()
.create(PipedApi::class.java)
}
}

View File

@ -23,12 +23,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.adapters.SearchAdapter
import com.github.libretube.adapters.SearchHistoryAdapter
import java.io.IOException
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
class SearchFragment : Fragment() {
private val TAG = "SearchFragment"
@ -42,19 +42,18 @@ class SearchFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
searchRecView = view.findViewById<RecyclerView>(R.id.search_recycler)
@ -81,10 +80,16 @@ class SearchFragment : Fragment() {
MaterialAlertDialogBuilder(view.context)
.setTitle(getString(R.string.choose_filter))
.setSingleChoiceItems(filterOptions, selectedFilter, DialogInterface.OnClickListener {
_, id -> tempSelectedItem = id
})
.setPositiveButton(getString(R.string.okay), DialogInterface.OnClickListener { _, _ ->
.setSingleChoiceItems(
filterOptions, selectedFilter,
DialogInterface.OnClickListener {
_, id ->
tempSelectedItem = id
}
)
.setPositiveButton(
getString(R.string.okay),
DialogInterface.OnClickListener { _, _ ->
selectedFilter = tempSelectedItem
apiSearchFilter = when (selectedFilter) {
0 -> "all"
@ -98,7 +103,8 @@ class SearchFragment : Fragment() {
else -> "all"
}
fetchSearch(autoTextView.text.toString())
})
}
)
.setNegativeButton(getString(R.string.cancel), null)
.create()
.show()
@ -129,7 +135,6 @@ class SearchFragment : Fragment() {
count: Int,
after: Int
) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
@ -143,7 +148,6 @@ class SearchFragment : Fragment() {
if (!searchRecView.canScrollVertically(1)) {
fetchNextSearchItems(autoTextView.text.toString())
}
}
GlobalScope.launch {
@ -167,16 +171,17 @@ class SearchFragment : Fragment() {
}
}
}
})
autoTextView.setOnEditorActionListener(OnEditorActionListener { _, actionId, _ ->
autoTextView.setOnEditorActionListener(
OnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
hideKeyboard()
autoTextView.dismissDropDown()
return@OnEditorActionListener true
}
false
})
}
)
autoTextView.setOnItemClickListener { _, _, _, _ ->
hideKeyboard()
}
@ -263,18 +268,14 @@ class SearchFragment : Fragment() {
var historyList = getHistory()
if (historyList.size != 0 && query == historyList.get(historyList.size - 1)) {
return
} else if (query == "") {
return
} else {
historyList = historyList + query
}
if (historyList.size > 10) {
historyList = historyList.takeLast(10)
}
@ -293,7 +294,5 @@ class SearchFragment : Fragment() {
} catch (e: Exception) {
return emptyList()
}
}
}

View File

@ -15,7 +15,6 @@ 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
@ -25,26 +24,31 @@ 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
import org.json.JSONObject
import org.json.JSONTokener
import retrofit2.HttpException
class SettingsActivity : AppCompatActivity(),
class SettingsActivity :
AppCompatActivity(),
SharedPreferences.OnSharedPreferenceChangeListener {
override fun onCreate(savedInstanceState: Bundle?) {
DynamicColors.applyToActivityIfAvailable(this)
updateAccentColor(this)
updateThemeMode(this)
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
overridePendingTransition(50, 50);
overridePendingTransition(50, 50)
}
val view = this.findViewById<View>(android.R.id.content)
view.setAlpha(0F);
view.animate().alpha(1F).setDuration(300);
view.alpha = 0F
view.animate().alpha(1F).duration = 300
setContentView(R.layout.activity_settings)
if (savedInstanceState == null) {
supportFragmentManager
@ -55,12 +59,10 @@ class SettingsActivity : AppCompatActivity(),
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, rootKey: String?) {}
class SettingsFragment : PreferenceFragmentCompat() {
val TAG = "Settings"
@ -70,7 +72,6 @@ class SettingsActivity : AppCompatActivity(),
override fun onCreate(savedInstanceState: Bundle?) {
getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
if (uri != null) {
try {
// Open a specific media item using ParcelFileDescriptor.
@ -129,8 +130,6 @@ class SettingsActivity : AppCompatActivity(),
).show()
}
}
}
super.onCreate(savedInstanceState)
}
@ -185,10 +184,12 @@ class SettingsActivity : AppCompatActivity(),
!= PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this.requireActivity(), arrayOf(
this.requireActivity(),
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
), 1
),
1
) // permission request code is just an int
} else if (token != "") {
getContent.launch("*/*")
@ -223,11 +224,15 @@ class SettingsActivity : AppCompatActivity(),
val themeToggle = findPreference<ListPreference>("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)
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
true
}
val accentColor = findPreference<Preference>("accent_color")
accentColor?.setOnPreferenceChangeListener { _, _ ->
val refresh = Intent(context, SettingsActivity::class.java)
startActivity(refresh)
true
}
@ -318,7 +323,6 @@ class SettingsActivity : AppCompatActivity(),
activity?.runOnUiThread(action)
}
private fun subscribe(channels: List<String>) {
fun run() {
lifecycleScope.launchWhenCreated {

View File

@ -3,13 +3,10 @@ package com.github.libretube
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.recyclerview.widget.RecyclerView
/**
*
@ -33,7 +30,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
startId: Int,
endId: Int
) {
}
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
@ -49,7 +45,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
positive: Boolean,
progress: Float
) {
}
})
@ -59,7 +54,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
startId: Int,
endId: Int
) {
}
override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
@ -78,7 +72,6 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
positive: Boolean,
progress: Float
) {
}
})
}
@ -91,12 +84,15 @@ class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeS
transitionListenerList += listener
}
private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
private val gestureDetector = GestureDetector(
context,
object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
transitionToEnd()
return false
}
})
}
)
override fun onTouchEvent(event: MotionEvent): Boolean {
// gestureDetector.onTouchEvent(event)

View File

@ -3,23 +3,22 @@ package com.github.libretube
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.github.libretube.adapters.SubscriptionAdapter
import com.github.libretube.adapters.SubscriptionChannelAdapter
import java.io.IOException
import org.chromium.base.ThreadUtils.runOnUiThread
import retrofit2.HttpException
import java.io.IOException
class Subscriptions : Fragment() {
val TAG = "SubFragment"
@ -34,7 +33,8 @@ class Subscriptions : Fragment() {
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
@ -78,8 +78,7 @@ class Subscriptions : Fragment() {
}
channelRecView.visibility = View.VISIBLE
feedRecView.visibility = View.GONE
}
else {
} else {
channelRecView.visibility = View.GONE
feedRecView.visibility = View.VISIBLE
}
@ -89,14 +88,14 @@ class Subscriptions : Fragment() {
scrollView.viewTreeObserver
.addOnScrollChangedListener {
if (scrollView.getChildAt(0).bottom
== (scrollView.height + scrollView.scrollY)) {
== (scrollView.height + scrollView.scrollY)
) {
// scroll view is at bottom
if (isLoaded) {
refreshLayout?.isRefreshing = true
subscriptionAdapter?.updateItems()
refreshLayout?.isRefreshing = false
}
}
}
} else {
@ -178,5 +177,4 @@ class Subscriptions : Fragment() {
if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action)
}
}

View File

@ -0,0 +1,53 @@
package com.github.libretube
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import java.util.*
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" -> oledMode(context)
}
}
fun oledMode(context: Context) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
context.setTheme(R.style.Theme_OLED)
}
fun updateLanguage(context: Context) {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
val languageName = sharedPreferences.getString("language", "sys")
if (languageName != "") {
var 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
conf.setLocale(locale)
Locale.setDefault(locale)
res.updateConfiguration(conf, dm)
}
}

View File

@ -1,6 +1,5 @@
package com.github.libretube.adapters
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -54,7 +53,6 @@ class CommentsAdapter(private val comments: MutableList<Comment>): RecyclerView
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
}
} catch (e: Exception) {
}
}
}
@ -62,7 +60,6 @@ class CommentsAdapter(private val comments: MutableList<Comment>): RecyclerView
override fun getItemCount(): Int {
return comments.size
}
}
class ViewHolder(val v: View) : RecyclerView.ViewHolder(v) {

View File

@ -18,12 +18,17 @@ import com.github.libretube.RetrofitInstance
import com.github.libretube.obj.PlaylistId
import com.github.libretube.obj.StreamItem
import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private val playlistId: String, private val isOwner: Boolean, private val activity: Activity): RecyclerView.Adapter<PlaylistViewHolder>() {
class PlaylistAdapter(
private val videoFeed: MutableList<StreamItem>,
private val playlistId: String,
private val isOwner: Boolean,
private val activity: Activity
) : RecyclerView.Adapter<PlaylistViewHolder>() {
private val TAG = "PlaylistAdapter"
override fun getItemCount(): Int {
return videoFeed.size
@ -82,7 +87,6 @@ class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private va
Log.e(TAG, "HttpException, unexpected response")
return@launch
} finally {
}
try {
if (response.message == "ok") {
@ -98,11 +102,9 @@ class PlaylistAdapter(private val videoFeed: MutableList<StreamItem>, private va
} catch (e: Exception) {
Log.e(TAG, e.toString())
}
}
}
run()
}
}
class PlaylistViewHolder(val v: View) : RecyclerView.ViewHolder(v) {

View File

@ -17,13 +17,15 @@ import com.github.libretube.RetrofitInstance
import com.github.libretube.obj.PlaylistId
import com.github.libretube.obj.Playlists
import com.squareup.picasso.Picasso
import java.io.IOException
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private val activity: Activity): RecyclerView.Adapter<PlaylistsViewHolder>() {
class PlaylistsAdapter(
private val playlists: MutableList<Playlists>,
private val activity: Activity
) : RecyclerView.Adapter<PlaylistsViewHolder>() {
val TAG = "PlaylistsAdapter"
override fun getItemCount(): Int {
return playlists.size
@ -63,7 +65,6 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
val bundle = bundleOf("playlist_id" to playlist.id)
activity.navController.navigate(R.id.playlistFragment, bundle)
}
}
private fun deletePlaylist(id: String, token: String, position: Int) {
fun run() {
@ -78,7 +79,6 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
Log.e(TAG, "HttpException, unexpected response")
return@launch
} finally {
}
try {
if (response.message == "ok") {
@ -94,13 +94,10 @@ class PlaylistsAdapter(private val playlists: MutableList<Playlists>, private va
} catch (e: Exception) {
Log.e(TAG, e.toString())
}
}
}
run()
}
}
class PlaylistsViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
init {

View File

@ -17,7 +17,6 @@ import com.github.libretube.formatShort
import com.github.libretube.obj.SearchItem
import com.squareup.picasso.Picasso
class SearchAdapter(private val searchItems: MutableList<SearchItem>) : RecyclerView.Adapter<CustomViewHolder1>() {
fun updateItems(newItems: List<SearchItem>) {

View File

@ -11,16 +11,17 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.google.android.material.imageview.ShapeableImageView
class SearchHistoryAdapter(private val context: Context, private var historyList: List<String> , private val editText : AutoCompleteTextView) :
class SearchHistoryAdapter(
private val context: Context,
private var historyList: List<String>,
private val editText: AutoCompleteTextView
) :
RecyclerView.Adapter<SearchHistoryViewHolder>() {
override fun getItemCount(): Int {
return historyList.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchHistoryViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cell = layoutInflater.inflate(R.layout.searchhistory_row, parent, false)
@ -31,7 +32,6 @@ class SearchHistoryAdapter(private val context: Context, private var historyList
val history = historyList[position]
holder.v.findViewById<TextView>(R.id.history_text).text = history
holder.v.findViewById<ShapeableImageView>(R.id.delete_history).setOnClickListener {
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

View File

@ -57,7 +57,6 @@ class SubscriptionAdapter(private val videoFeed: List<StreamItem>): RecyclerView
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
}
} catch (e: Exception) {
}
}
Picasso.get().load(trending.thumbnail).into(thumbnailImage)

View File

@ -47,7 +47,6 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
activity.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
}
} catch (e: Exception) {
}
}
if (trending.thumbnail!!.isEmpty()) {
@ -59,7 +58,6 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
Picasso.get().load(trending.uploaderAvatar).into(channelImage)
}
holder.v.setOnClickListener {
var bundle = Bundle()
bundle.putString("videoId", trending.url!!.replace("/watch?v=", ""))

View File

@ -2,6 +2,4 @@ package com.github.libretube
import android.app.Application
class myApp : Application() {
}
class myApp : Application()

View File

@ -17,4 +17,3 @@ data class Comment(
) {
constructor() : this("", "", "", "", "", null, 0, null, "", null)
}

View File

@ -27,6 +27,8 @@ data class Streams(
val proxyUrl: String?,
val chapters: List<ChapterSegment>?
) {
constructor(): this("","","","","","","","","","",null,-1,-1,-1,-1, emptyList(), emptyList(),
emptyList(), emptyList(), null,"", emptyList())
constructor() : this(
"", "", "", "", "", "", "", "", "", "", null, -1, -1, -1, -1, emptyList(), emptyList(),
emptyList(), emptyList(), null, "", emptyList()
)
}

View File

@ -0,0 +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">
<path
android:fillColor="@android:color/white"
android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>

View File

@ -50,7 +50,7 @@
android:layout_marginStart="24dp"
android:background="@android:color/transparent"
android:text="@string/subscribe"
android:textColor="@color/colorPrimary"
android:textColor="?attr/colorPrimary"
android:visibility="gone"
app:layout_constraintStart_toEndOf="@+id/search_channel_image" />

View File

@ -97,6 +97,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="15dp"
android:text="" />

View File

@ -236,7 +236,7 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:backgroundTint="?android:attr/colorBackground"
android:backgroundTint="?attr/colorOnPrimary"
android:drawableLeft="@drawable/ic_bell"
android:drawableTint="?android:attr/textColorPrimary"
android:text="@string/subscribe"

View File

@ -1,36 +1,104 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.LibreTube" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/md_theme_dark_primary</item>
<item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_theme_dark_tertiary</item>
<item name="colorOnTertiary">@color/md_theme_dark_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_theme_dark_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_theme_dark_onTertiaryContainer</item>
<item name="colorError">@color/md_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_dark_background</item>
<item name="colorOnBackground">@color/md_theme_dark_onBackground</item>
<item name="colorSurface">@color/md_theme_dark_surface</item>
<item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_dark_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_dark_primaryInverse</item>
<style name="Theme.MY" parent="Theme.Material3.Dark.NoActionBar"></style>
<style name="Theme.Red" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/red_dark_accentLight</item> // container
<item name="colorOnPrimary">@color/red_dark_accentDark</item> // title
<item name="colorPrimaryContainer">@color/red_dark_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/red_dark_accentLight</item> //
<item name="colorSecondary">@color/red_dark_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/red_dark_accentDark</item> //
<item name="colorSecondaryContainer">@color/red_dark_accentDark</item> // navbar surround
<!-- <item name="colorOnSecondaryContainer">@color/red_dark_background</item> --> // navbar icon fill
<item name="android:colorBackground">@color/red_dark_background</item> // background
<item name="colorOnBackground">@color/red_dark_background</item>
<item name="android:statusBarColor" tools:targetApi="m">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Blue" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/blue_dark_accentLight</item> // container
<item name="colorOnPrimary">@color/blue_dark_accentDark</item> // title
<item name="colorPrimaryContainer">@color/blue_dark_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/blue_dark_accentLight</item> //
<item name="colorSecondary">@color/blue_dark_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/blue_dark_accentDark</item> //
<item name="colorSecondaryContainer">@color/blue_dark_accentDark</item> // navbar surround
<!-- <item name="colorOnSecondaryContainer">@color/blue_dark_background</item> --> // navbar icon fill
<item name="android:colorBackground">@color/blue_dark_background</item> // background
<item name="colorOnBackground">@color/blue_dark_background</item>
<item name="android:statusBarColor" tools:targetApi="m">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Yellow" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/yellow_dark_accentLight</item> // container
<item name="colorOnPrimary">@color/yellow_dark_accentDark</item> // title
<item name="colorPrimaryContainer">@color/yellow_dark_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/yellow_dark_accentLight</item> //
<item name="colorSecondary">@color/yellow_dark_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/yellow_dark_accentDark</item> //
<item name="colorSecondaryContainer">@color/yellow_dark_accentDark</item> // navbar surround
<!-- <item name="colorOnSecondaryContainer">@color/yellow_dark_background</item> --> // navbar icon fill
<item name="android:colorBackground">@color/yellow_dark_background</item> // background
<item name="colorOnBackground">@color/yellow_dark_background</item>
<item name="android:statusBarColor" tools:targetApi="m">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Green" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/green_dark_accentLight</item> // container
<item name="colorOnPrimary">@color/green_dark_accentDark</item> // title
<item name="colorPrimaryContainer">@color/green_dark_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/green_dark_accentLight</item> //
<item name="colorSecondary">@color/green_dark_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/green_dark_accentDark</item> //
<item name="colorSecondaryContainer">@color/green_dark_accentDark</item> // navbar surround
<!-- <item name="colorOnSecondaryContainer">@color/green_dark_background</item> --> // navbar icon fill
<item name="android:colorBackground">@color/green_dark_background</item> // background
<item name="colorOnBackground">@color/green_dark_background</item>
<item name="android:statusBarColor" tools:targetApi="m">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Purple" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/purple_dark_accentLight</item> // container
<item name="colorOnPrimary">@color/purple_dark_accentDark</item> // title
<item name="colorPrimaryContainer">@color/purple_dark_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/purple_dark_accentLight</item> //
<item name="colorSecondary">@color/purple_dark_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/purple_dark_accentDark</item> //
<item name="colorSecondaryContainer">@color/purple_dark_accentDark</item> // navbar surround
<!-- <item name="colorOnSecondaryContainer">@color/purple_dark_background</item> --> // navbar icon fill
<item name="android:colorBackground">@color/purple_dark_background</item> // background
<item name="colorOnBackground">@color/purple_dark_background</item>
<item name="android:statusBarColor" tools:targetApi="m">@android:color/transparent</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.OLED" parent="Theme.Material3.Dark.NoActionBar">
<item name="android:colorBackground">@color/black</item>
</style>
</resources>

View File

@ -1,37 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.LibreTube" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_light_secondary</item>
<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_theme_light_tertiary</item>
<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
<item name="colorError">@color/md_theme_light_error</item>
<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
<item name="colorOnError">@color/md_theme_light_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_light_background</item>
<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
<item name="colorSurface">@color/md_theme_light_surface</item>
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
<style name="Theme.MY" parent="Theme.Material3.Light.NoActionBar"></style>
<style name="Theme.Red" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/red_light_accentLight</item> // container
<item name="colorOnPrimary">@color/red_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/red_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/red_light_accentLight</item> //
<item name="colorSecondary">@color/red_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/red_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/red_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/red_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/red_light_background</item> // background
<item name="colorOnBackground">@color/red_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Blue" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/blue_light_accentLight</item> // container
<item name="colorOnPrimary">@color/blue_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/blue_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/blue_light_accentLight</item> //
<item name="colorSecondary">@color/blue_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/blue_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/blue_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/blue_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/blue_light_background</item> // background
<item name="colorOnBackground">@color/blue_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Yellow" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/yellow_light_accentLight</item> // container
<item name="colorOnPrimary">@color/yellow_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/yellow_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/yellow_light_accentLight</item> //
<item name="colorSecondary">@color/yellow_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/yellow_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/yellow_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/yellow_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/yellow_light_background</item> // background
<item name="colorOnBackground">@color/yellow_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Green" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/green_light_accentLight</item> // container
<item name="colorOnPrimary">@color/green_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/green_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/green_light_accentLight</item> //
<item name="colorSecondary">@color/green_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/green_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/green_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/green_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/green_light_background</item> // background
<item name="colorOnBackground">@color/green_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Purple" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/purple_light_accentLight</item> // container
<item name="colorOnPrimary">@color/purple_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/purple_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/purple_light_accentLight</item> //
<item name="colorSecondary">@color/purple_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/purple_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/purple_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/purple_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/purple_light_background</item> // background
<item name="colorOnBackground">@color/purple_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>

View File

@ -463,12 +463,32 @@
<item>@string/systemDefault</item>
<item>@string/lightTheme</item>
<item>@string/darkTheme</item>
<item>@string/oledTheme</item>
</string-array>
<string-array name="themesValue">
<item>A</item>
<item>L</item>
<item>D</item>
<item>O</item>
</string-array>
<string-array name="accents">
<item>@string/material_you</item>
<item>@string/color_red</item>
<item>@string/color_blue</item>
<item>@string/color_yellow</item>
<item>@string/color_green</item>
<item>@string/color_purple</item>
</string-array>
<string-array name="accentsValue">
<item>my</item>
<item>red</item>
<item>blue</item>
<item>yellow</item>
<item>green</item>
<item>purple</item>
</string-array>
<string-array name="tabs">

View File

@ -6,59 +6,44 @@
<color name="duration_background_color">#AA000000</color>
<color name="duration_text_color">#EEFFFFFF</color>
<color name="colorPrimary">#B81B3B</color>
<color name="md_theme_light_primary">#B81B3B</color>
<color name="md_theme_light_onPrimary">#FFFFFF</color>
<color name="md_theme_light_primaryContainer">#FFDADC</color>
<color name="md_theme_light_onPrimaryContainer">#40000B</color>
<color name="md_theme_light_secondary">#9C4145</color>
<color name="md_theme_light_onSecondary">#FFFFFF</color>
<color name="md_theme_light_secondaryContainer">#FFD9DA</color>
<color name="md_theme_light_onSecondaryContainer">#400008</color>
<color name="md_theme_light_tertiary">#98470F</color>
<color name="md_theme_light_onTertiary">#FFFFFF</color>
<color name="md_theme_light_tertiaryContainer">#FFDBC8</color>
<color name="md_theme_light_onTertiaryContainer">#341100</color>
<color name="md_theme_light_error">#BA1B1B</color>
<color name="md_theme_light_errorContainer">#FFDAD4</color>
<color name="md_theme_light_onError">#FFFFFF</color>
<color name="md_theme_light_onErrorContainer">#410001</color>
<color name="md_theme_light_background">#FCFCFC</color>
<color name="md_theme_light_onBackground">#201A1A</color>
<color name="md_theme_light_surface">#FCFCFC</color>
<color name="md_theme_light_onSurface">#201A1A</color>
<color name="md_theme_light_surfaceVariant">#F4DDDD</color>
<color name="md_theme_light_onSurfaceVariant">#524343</color>
<color name="md_theme_light_outline">#847373</color>
<color name="md_theme_light_inverseOnSurface">#FBEDED</color>
<color name="md_theme_light_inverseSurface">#362F2F</color>
<color name="md_theme_light_primaryInverse">#FFB3B8</color>
<color name="md_theme_dark_primary">#FFB3B8</color>
<color name="md_theme_dark_onPrimary">#680018</color>
<color name="md_theme_dark_primaryContainer">#920026</color>
<color name="md_theme_dark_onPrimaryContainer">#FFDADC</color>
<color name="md_theme_dark_secondary">#FFB2B3</color>
<color name="md_theme_dark_onSecondary">#60131B</color>
<color name="md_theme_dark_secondaryContainer">#7D2A2F</color>
<color name="md_theme_dark_onSecondaryContainer">#FFD9DA</color>
<color name="md_theme_dark_tertiary">#FFB68C</color>
<color name="md_theme_dark_onTertiary">#552100</color>
<color name="md_theme_dark_tertiaryContainer">#783200</color>
<color name="md_theme_dark_onTertiaryContainer">#FFDBC8</color>
<color name="md_theme_dark_error">#FFB4A9</color>
<color name="md_theme_dark_errorContainer">#930006</color>
<color name="md_theme_dark_onError">#680003</color>
<color name="md_theme_dark_onErrorContainer">#FFDAD4</color>
<color name="md_theme_dark_background">#201A1A</color>
<color name="md_theme_dark_onBackground">#ECDFDF</color>
<color name="md_theme_dark_surface">#201A1A</color>
<color name="md_theme_dark_onSurface">#ECDFDF</color>
<color name="md_theme_dark_surfaceVariant">#524343</color>
<color name="md_theme_dark_onSurfaceVariant">#D7C2C2</color>
<color name="md_theme_dark_outline">#9F8C8C</color>
<color name="md_theme_dark_inverseOnSurface">#201A1A</color>
<color name="md_theme_dark_inverseSurface">#ECDFDF</color>
<color name="md_theme_dark_primaryInverse">#B81B3B</color>
<color name="seed">#BD1F3E</color>
<color name="error">#BA1B1B</color>
<color name="red_light_accentLight">#F1395E</color>
<color name="red_light_accentDark">#B81B3B</color>
<color name="red_light_background">#FFC3C3</color>
<color name="red_dark_accentLight">#F1395E</color>
<color name="red_dark_accentDark">#8F001D</color>
<color name="red_dark_background">#1E0D0D</color>
<color name="blue_light_accentLight">#2196F3</color>
<color name="blue_light_accentDark">#0E4B67</color>
<color name="blue_light_background">#DDF0FF</color>
<color name="blue_dark_accentLight">#2196F3</color>
<color name="blue_dark_accentDark">#0E4B67</color>
<color name="blue_dark_background">#080C20</color>
<color name="yellow_light_accentLight">#F3E570</color>
<color name="yellow_light_accentDark">#EDE06A</color>
<color name="yellow_light_background">#FFF9C8</color>
<color name="yellow_dark_accentLight">#E2EF55</color>
<color name="yellow_dark_accentDark">#999520</color>
<color name="yellow_dark_background">#1C1A05</color>
<color name="green_light_accentLight">#8BC34A</color>
<color name="green_light_accentDark">#5BD861</color>
<color name="green_light_background">#E8FFCE</color>
<color name="green_dark_accentLight">#8BC34A</color>
<color name="green_dark_accentDark">#155C1B</color>
<color name="green_dark_background">#131C09</color>
<color name="purple_light_accentLight">#db1fb6</color>
<color name="purple_light_accentDark">#d42cb2</color>
<color name="purple_light_background">#FFDAE6</color>
<color name="purple_dark_accentLight">#9621AA</color>
<color name="purple_dark_accentDark">#371377</color>
<color name="purple_dark_background">#120B20</color>
</resources>

View File

@ -101,4 +101,12 @@
<string name="category_outro">Endcards/Credits</string>
<string name="category_outro_description">Credits or when the YouTube endcards appear. Not for conclusions with information.</string>
<string name="license">License</string>
<string name="color_accent">Color Accent</string>
<string name="color_red">Red</string>
<string name="color_blue">Blue</string>
<string name="color_yellow">Yellow</string>
<string name="color_green">Green</string>
<string name="color_purple">Purple</string>
<string name="oledTheme">OLED Theme</string>
<string name="material_you">Material You</string>
</resources>

View File

@ -1,33 +1,89 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.LibreTube" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_light_secondary</item>
<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_theme_light_tertiary</item>
<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
<item name="colorError">@color/md_theme_light_error</item>
<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
<item name="colorOnError">@color/md_theme_light_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_light_background</item>
<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
<item name="colorSurface">@color/md_theme_light_surface</item>
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
<style name="Theme.MY" parent="Theme.Material3.Light.NoActionBar"></style>
<style name="Theme.Red" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/red_light_accentLight</item> // container
<item name="colorOnPrimary">@color/red_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/red_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/red_light_accentLight</item> //
<item name="colorSecondary">@color/red_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/red_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/red_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/red_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/red_light_background</item> // background
<item name="colorOnBackground">@color/red_light_background</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Blue" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/blue_light_accentLight</item> // container
<item name="colorOnPrimary">@color/blue_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/blue_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/blue_light_accentLight</item> //
<item name="colorSecondary">@color/blue_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/blue_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/blue_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/blue_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/blue_light_background</item> // background
<item name="colorOnBackground">@color/blue_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Yellow" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/yellow_light_accentLight</item> // container
<item name="colorOnPrimary">@color/yellow_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/yellow_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/yellow_light_accentLight</item> //
<item name="colorSecondary">@color/yellow_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/yellow_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/yellow_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/yellow_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/yellow_light_background</item> // background
<item name="colorOnBackground">@color/yellow_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Green" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/green_light_accentLight</item> // container
<item name="colorOnPrimary">@color/green_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/green_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/green_light_accentLight</item> //
<item name="colorSecondary">@color/green_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/green_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/green_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/green_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/green_light_background</item> // background
<item name="colorOnBackground">@color/green_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="Theme.Purple" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/purple_light_accentLight</item> // container
<item name="colorOnPrimary">@color/purple_light_accentDark</item> // title
<item name="colorPrimaryContainer">@color/purple_light_accentLight</item> //
<item name="colorOnPrimaryContainer">@color/purple_light_accentLight</item> //
<item name="colorSecondary">@color/purple_light_accentLight</item> // Settings Categories
<item name="colorOnSecondary">@color/purple_light_accentDark</item> //
<item name="colorSecondaryContainer">@color/purple_light_accentDark</item> // navbar surround
<item name="colorOnSecondaryContainer">@color/purple_light_background</item> // navbar icon fill
<item name="android:colorBackground">@color/purple_light_background</item> // background
<item name="colorOnBackground">@color/purple_light_background</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>

View File

@ -71,6 +71,15 @@
android:icon="@drawable/ic_theme"
/>
<ListPreference
app:title="@string/color_accent"
app:key="accent_color"
app:entries="@array/accents"
app:entryValues="@array/accentsValue"
app:defaultValue="red"
android:icon="@drawable/ic_color"
/>
<androidx.preference.Preference
app:title="@string/sponsorblock"
app:key="sponsorblock"

View File

@ -1,8 +1,7 @@
package com.github.libretube
import org.junit.Test
import org.junit.Assert.*
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).