From 0356031720f4c56d23512e67a7493cb2dd492eda Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Fri, 13 May 2022 07:33:29 +0300 Subject: [PATCH 01/17] Ignore case for response.uploader --- app/src/main/java/com/github/libretube/PlaylistFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/PlaylistFragment.kt b/app/src/main/java/com/github/libretube/PlaylistFragment.kt index 89943781a..ef6ab7f6d 100644 --- a/app/src/main/java/com/github/libretube/PlaylistFragment.kt +++ b/app/src/main/java/com/github/libretube/PlaylistFragment.kt @@ -73,7 +73,7 @@ class PlaylistFragment : Fragment() { val sharedPref2 = context?.getSharedPreferences("username", Context.MODE_PRIVATE) val user = sharedPref2?.getString("username","") var isOwner = false - if(response.uploaderUrl == null && response.uploader == user){ + if(response.uploaderUrl == null && response.uploader.equals(user, true)){ isOwner = true } playlistAdapter = PlaylistAdapter(response.relatedStreams!!.toMutableList(), playlist_id!!, isOwner, requireActivity()) From 665721fbdec8566bc844392b1656352aee89d111 Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Fri, 13 May 2022 19:55:15 +0300 Subject: [PATCH 02/17] Fix animation --- app/src/main/java/com/github/libretube/SettingsActivity.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/SettingsActivity.kt b/app/src/main/java/com/github/libretube/SettingsActivity.kt index 0fb13644e..2ee7f5645 100644 --- a/app/src/main/java/com/github/libretube/SettingsActivity.kt +++ b/app/src/main/java/com/github/libretube/SettingsActivity.kt @@ -38,7 +38,9 @@ class SettingsActivity : AppCompatActivity(), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - overridePendingTransition(50, 50); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + overridePendingTransition(50, 50); + } val view = this.findViewById(android.R.id.content) view.setAlpha(0F); view.animate().alpha(1F).setDuration(300); From d9b5c18cac796965e16cec54a397c805d54fbd85 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 14 May 2022 00:09:33 +0200 Subject: [PATCH 03/17] Added default tab on app startup --- .../main/java/com/github/libretube/MainActivity.kt | 7 +++++++ app/src/main/res/values/array.xml | 13 +++++++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/settings.xml | 9 +++++++++ 4 files changed, 30 insertions(+) diff --git a/app/src/main/java/com/github/libretube/MainActivity.kt b/app/src/main/java/com/github/libretube/MainActivity.kt index 7cd322ee4..5678469bc 100644 --- a/app/src/main/java/com/github/libretube/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/MainActivity.kt @@ -18,6 +18,7 @@ import android.view.* import android.view.inputmethod.InputMethodManager import android.widget.Button import android.widget.LinearLayout +import android.widget.Toast import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.widget.Toolbar import androidx.constraintlayout.motion.widget.MotionLayout @@ -86,6 +87,12 @@ class MainActivity : AppCompatActivity() { navController = findNavController(R.id.fragment) bottomNavigationView.setupWithNavController(navController) + when (sharedPreferences.getString("default_tab", "home")!!) { + "home" -> navController.navigate(R.id.home2) + "subscriptions" -> navController.navigate(R.id.subscriptions) + "library" -> navController.navigate(R.id.library) + } + bottomNavigationView.setOnItemSelectedListener { when (it.itemId) { R.id.home2 -> { diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index a68fe1239..05860585e 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -470,6 +470,19 @@ L D + + + @string/startpage + @string/subscriptions + @string/library + + + + home + subscriptions + library + + HLS 1080p diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 51d9d8b8e..82c632a45 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,4 +72,5 @@ No Internet Connection Retry Comments + Default Tab diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 56ae14456..dccf89391 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -71,6 +71,15 @@ android:icon="@drawable/ic_theme" /> + + Date: Sat, 14 May 2022 18:14:53 +0200 Subject: [PATCH 04/17] Added Sub Toggle --- .../com/github/libretube/Subscriptions.kt | 8 ++++++- .../res/layout/channel_subscription_row.xml | 4 ++-- .../res/layout/fragment_subscriptions.xml | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/Subscriptions.kt b/app/src/main/java/com/github/libretube/Subscriptions.kt index 3fbfb8387..eb63d6147 100644 --- a/app/src/main/java/com/github/libretube/Subscriptions.kt +++ b/app/src/main/java/com/github/libretube/Subscriptions.kt @@ -52,7 +52,7 @@ class Subscriptions : Fragment() { progressBar.visibility=View.VISIBLE var channelRecView = view.findViewById(R.id.sub_channels) - channelRecView?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) + channelRecView?.layoutManager = GridLayoutManager(context, 4) fetchChannels(channelRecView) var feedRecView = view.findViewById(R.id.sub_feed) @@ -66,6 +66,12 @@ class Subscriptions : Fragment() { fetchFeed(feedRecView, progressBar, view) } + var toggleSubs = view.findViewById(R.id.toggle_subs) + toggleSubs.setOnClickListener { + channelRecView.visibility = if (channelRecView.visibility == View.GONE) View.VISIBLE else View.GONE + feedRecView.visibility = if (feedRecView.visibility == View.GONE) View.VISIBLE else View.GONE + } + val scrollView = view.findViewById(R.id.scrollview_sub) scrollView.viewTreeObserver .addOnScrollChangedListener { diff --git a/app/src/main/res/layout/channel_subscription_row.xml b/app/src/main/res/layout/channel_subscription_row.xml index c9d1df987..97cbf0228 100644 --- a/app/src/main/res/layout/channel_subscription_row.xml +++ b/app/src/main/res/layout/channel_subscription_row.xml @@ -9,8 +9,8 @@ > + + + + + + + + Date: Sun, 15 May 2022 08:34:43 +0200 Subject: [PATCH 05/17] Lazy Load Subs and hide when not logged in --- .../java/com/github/libretube/Subscriptions.kt | 16 ++++++++++++---- .../main/res/layout/fragment_subscriptions.xml | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/github/libretube/Subscriptions.kt b/app/src/main/java/com/github/libretube/Subscriptions.kt index eb63d6147..6dba0f985 100644 --- a/app/src/main/java/com/github/libretube/Subscriptions.kt +++ b/app/src/main/java/com/github/libretube/Subscriptions.kt @@ -8,6 +8,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.* +import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager @@ -52,8 +53,6 @@ class Subscriptions : Fragment() { progressBar.visibility=View.VISIBLE var channelRecView = view.findViewById(R.id.sub_channels) - channelRecView?.layoutManager = GridLayoutManager(context, 4) - fetchChannels(channelRecView) var feedRecView = view.findViewById(R.id.sub_feed) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) @@ -67,9 +66,18 @@ class Subscriptions : Fragment() { } var toggleSubs = view.findViewById(R.id.toggle_subs) + toggleSubs.visibility = View.VISIBLE toggleSubs.setOnClickListener { - channelRecView.visibility = if (channelRecView.visibility == View.GONE) View.VISIBLE else View.GONE - feedRecView.visibility = if (feedRecView.visibility == View.GONE) View.VISIBLE else View.GONE + if (!channelRecView.isVisible) { + channelRecView?.layoutManager = GridLayoutManager(context, 4) + fetchChannels(channelRecView) + channelRecView.visibility = View.VISIBLE + feedRecView.visibility = View.GONE + } + else { + channelRecView.visibility = View.GONE + feedRecView.visibility = View.VISIBLE + } } val scrollView = view.findViewById(R.id.scrollview_sub) diff --git a/app/src/main/res/layout/fragment_subscriptions.xml b/app/src/main/res/layout/fragment_subscriptions.xml index dec57928a..ec0bd7bc6 100644 --- a/app/src/main/res/layout/fragment_subscriptions.xml +++ b/app/src/main/res/layout/fragment_subscriptions.xml @@ -58,7 +58,8 @@ android:id="@+id/toggle_subs" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="10dp"> + android:layout_margin="10dp" + android:visibility="gone"> Date: Sun, 15 May 2022 21:11:27 +0200 Subject: [PATCH 06/17] Added verified in Channel Page --- .../java/com/github/libretube/ChannelFragment.kt | 2 ++ app/src/main/res/layout/fragment_channel.xml | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/app/src/main/java/com/github/libretube/ChannelFragment.kt b/app/src/main/java/com/github/libretube/ChannelFragment.kt index 96d3d77e9..6288739dd 100644 --- a/app/src/main/java/com/github/libretube/ChannelFragment.kt +++ b/app/src/main/java/com/github/libretube/ChannelFragment.kt @@ -4,6 +4,7 @@ package com.github.libretube import android.annotation.SuppressLint import android.app.Activity import android.content.Context +import android.media.Image import android.opengl.Visibility import android.os.Bundle import android.util.Log @@ -209,6 +210,7 @@ class ChannelFragment : Fragment() { runOnUiThread { view.findViewById(R.id.channel_scrollView).visibility = View.VISIBLE view.findViewById(R.id.channel_name).text=response.name + if (response.verified) view.findViewById(R.id.channel_verified).visibility = View.VISIBLE view.findViewById(R.id.channel_subs).text=resources.getString(R.string.subscribers, response.subscriberCount.formatShort()) view.findViewById(R.id.channel_description).text=response.description val bannerImage = view.findViewById(R.id.channel_banner) diff --git a/app/src/main/res/layout/fragment_channel.xml b/app/src/main/res/layout/fragment_channel.xml index 3e5005186..28c666278 100644 --- a/app/src/main/res/layout/fragment_channel.xml +++ b/app/src/main/res/layout/fragment_channel.xml @@ -44,6 +44,10 @@ android:layout_height="match_parent" android:orientation="vertical"> + + + + + + Date: Sun, 15 May 2022 21:16:46 +0200 Subject: [PATCH 07/17] Removed import --- app/src/main/java/com/github/libretube/ChannelFragment.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ChannelFragment.kt b/app/src/main/java/com/github/libretube/ChannelFragment.kt index 6288739dd..0894d58ff 100644 --- a/app/src/main/java/com/github/libretube/ChannelFragment.kt +++ b/app/src/main/java/com/github/libretube/ChannelFragment.kt @@ -4,8 +4,6 @@ package com.github.libretube import android.annotation.SuppressLint import android.app.Activity import android.content.Context -import android.media.Image -import android.opengl.Visibility import android.os.Bundle import android.util.Log import android.util.TypedValue @@ -210,7 +208,8 @@ class ChannelFragment : Fragment() { runOnUiThread { view.findViewById(R.id.channel_scrollView).visibility = View.VISIBLE view.findViewById(R.id.channel_name).text=response.name - if (response.verified) view.findViewById(R.id.channel_verified).visibility = View.VISIBLE + val channelVerified = view.findViewById(R.id.channel_verified) + if (response.verified) channelVerified.visibility = View.VISIBLE view.findViewById(R.id.channel_subs).text=resources.getString(R.string.subscribers, response.subscriberCount.formatShort()) view.findViewById(R.id.channel_description).text=response.description val bannerImage = view.findViewById(R.id.channel_banner) From af22e6ae778ba6fc3e24cf205a93ba2f2ba269a0 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 15 May 2022 23:40:33 +0200 Subject: [PATCH 08/17] Comment Channel Icons clickable, improved Channel View --- .../com/github/libretube/ChannelFragment.kt | 5 +++-- .../com/github/libretube/PlayerFragment.kt | 4 ++-- .../libretube/adapters/CommentsAdapter.kt | 22 +++++++++++++++++-- app/src/main/res/layout/fragment_channel.xml | 13 +---------- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ChannelFragment.kt b/app/src/main/java/com/github/libretube/ChannelFragment.kt index 0894d58ff..b745a9b70 100644 --- a/app/src/main/java/com/github/libretube/ChannelFragment.kt +++ b/app/src/main/java/com/github/libretube/ChannelFragment.kt @@ -5,6 +5,7 @@ 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 @@ -207,11 +208,11 @@ class ChannelFragment : Fragment() { refreshLayout?.isRefreshing = false; runOnUiThread { view.findViewById(R.id.channel_scrollView).visibility = View.VISIBLE - view.findViewById(R.id.channel_name).text=response.name + view.findViewById(R.id.channel_name).text = if (response.name?.length!! > 19) response.name.toString().substring(0,16) + "..." else response.name val channelVerified = view.findViewById(R.id.channel_verified) if (response.verified) channelVerified.visibility = View.VISIBLE view.findViewById(R.id.channel_subs).text=resources.getString(R.string.subscribers, response.subscriberCount.formatShort()) - view.findViewById(R.id.channel_description).text=response.description + view.findViewById(R.id.channel_description).text=response.description?.trim() val bannerImage = view.findViewById(R.id.channel_banner) val channelImage = view.findViewById(R.id.channel_image) Picasso.get().load(response.bannerUrl).into(bannerImage) diff --git a/app/src/main/java/com/github/libretube/PlayerFragment.kt b/app/src/main/java/com/github/libretube/PlayerFragment.kt index 459a9809c..ce00bfca7 100644 --- a/app/src/main/java/com/github/libretube/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/PlayerFragment.kt @@ -536,9 +536,9 @@ class PlayerFragment : Fragment() { view.findViewById(R.id.player_description).text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Html.fromHtml(response.description, Html.FROM_HTML_MODE_COMPACT) + Html.fromHtml(response.description, Html.FROM_HTML_MODE_COMPACT).trim() } else { - Html.fromHtml(response.description) + Html.fromHtml(response.description).trim() } view.findViewById(R.id.player_views_info).text = response.views.formatShort() + " views • " + response.uploadDate diff --git a/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt b/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt index bdd0f0811..36bdcaf58 100644 --- a/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt +++ b/app/src/main/java/com/github/libretube/adapters/CommentsAdapter.kt @@ -1,11 +1,15 @@ package com.github.libretube.adapters +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView +import androidx.constraintlayout.motion.widget.MotionLayout +import androidx.core.os.bundleOf import androidx.recyclerview.widget.RecyclerView +import com.github.libretube.MainActivity import com.github.libretube.R import com.github.libretube.formatShort import com.github.libretube.obj.Comment @@ -27,8 +31,8 @@ class CommentsAdapter(private val comments: MutableList): RecyclerView override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.v.findViewById(R.id.comment_infos).text = comments[position].author.toString() + " • " + comments[position].commentedTime.toString() holder.v.findViewById(R.id.comment_text).text = comments[position].commentText.toString() - val thumbnailImage = holder.v.findViewById(R.id.commentor_image) - Picasso.get().load(comments[position].thumbnail).fit().centerCrop().into(thumbnailImage) + val channelImage = holder.v.findViewById(R.id.commentor_image) + Picasso.get().load(comments[position].thumbnail).fit().centerCrop().into(channelImage) holder.v.findViewById(R.id.likes_textView).text = comments[position].likeCount?.toLong().formatShort() if (comments[position].verified == true) { holder.v.findViewById(R.id.verified_imageView).visibility = View.VISIBLE @@ -39,6 +43,20 @@ class CommentsAdapter(private val comments: MutableList): RecyclerView if (comments[position].hearted == true) { holder.v.findViewById(R.id.hearted_imageView).visibility = View.VISIBLE } + channelImage.setOnClickListener{ + val activity = holder.v.context as MainActivity + val bundle = bundleOf("channel_id" to comments[position].commentorUrl) + activity.navController.navigate(R.id.channel, bundle) + try { + val mainMotionLayout = activity.findViewById(R.id.mainMotionLayout) + if (mainMotionLayout.progress == 0.toFloat()) { + mainMotionLayout.transitionToEnd() + activity.findViewById(R.id.playerMotionLayout).transitionToEnd() + } + }catch (e: Exception){ + + } + } } override fun getItemCount(): Int { diff --git a/app/src/main/res/layout/fragment_channel.xml b/app/src/main/res/layout/fragment_channel.xml index 28c666278..cf565285a 100644 --- a/app/src/main/res/layout/fragment_channel.xml +++ b/app/src/main/res/layout/fragment_channel.xml @@ -95,20 +95,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="10dp" - android:layout_marginBottom="5dp" + android:layout_marginBottom="15dp" android:text="" /> - - Date: Mon, 16 May 2022 13:11:22 +0300 Subject: [PATCH 09/17] Integrated SponsorBlock --- .../java/com/github/libretube/MainActivity.kt | 7 ++ .../java/com/github/libretube/PipedApi.kt | 3 + .../com/github/libretube/PlayerFragment.kt | 64 +++++++++++++++++++ .../com/github/libretube/SettingsActivity.kt | 9 +++ .../github/libretube/SponsorBlockSettings.kt | 55 ++++++++++++++++ .../java/com/github/libretube/obj/Segment.kt | 12 ++++ .../java/com/github/libretube/obj/Segments.kt | 10 +++ app/src/main/res/drawable/ic_sponsorblock.xml | 13 ++++ .../main/res/layout/fragment_sponsorblock.xml | 10 +++ app/src/main/res/values/strings.xml | 15 +++++ app/src/main/res/xml/settings.xml | 6 ++ .../main/res/xml/sponsorblock_settings.xml | 40 ++++++++++++ 12 files changed, 244 insertions(+) create mode 100644 app/src/main/java/com/github/libretube/SponsorBlockSettings.kt create mode 100644 app/src/main/java/com/github/libretube/obj/Segment.kt create mode 100644 app/src/main/java/com/github/libretube/obj/Segments.kt create mode 100644 app/src/main/res/drawable/ic_sponsorblock.xml create mode 100644 app/src/main/res/layout/fragment_sponsorblock.xml create mode 100644 app/src/main/res/xml/sponsorblock_settings.xml diff --git a/app/src/main/java/com/github/libretube/MainActivity.kt b/app/src/main/java/com/github/libretube/MainActivity.kt index 1b52e5660..29e6d857e 100644 --- a/app/src/main/java/com/github/libretube/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/MainActivity.kt @@ -44,6 +44,13 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) RetrofitInstance.url = sharedPreferences.getString("instance", "https://pipedapi.kavin.rocks/")!! + SponsorBlockSettings.sponsorBlockEnabled = sharedPreferences.getBoolean("sponsorblock_enabled_key", false) + SponsorBlockSettings.introEnabled = sharedPreferences.getBoolean("intro_category_key", false) + SponsorBlockSettings.selfPromoEnabled = sharedPreferences.getBoolean("selfpromo_category_key", false) + SponsorBlockSettings.interactionEnabled = sharedPreferences.getBoolean("interaction_category_key", false) + SponsorBlockSettings.sponsorsEnabled = sharedPreferences.getBoolean("sponsors_category_key", false) + SponsorBlockSettings.outroEnabled = sharedPreferences.getBoolean("outro_category_key", false) + DynamicColors.applyToActivitiesIfAvailable(application) val languageName = sharedPreferences.getString("language", "sys") if (languageName != "") { diff --git a/app/src/main/java/com/github/libretube/PipedApi.kt b/app/src/main/java/com/github/libretube/PipedApi.kt index 94c2a65b5..3332c8ca4 100644 --- a/app/src/main/java/com/github/libretube/PipedApi.kt +++ b/app/src/main/java/com/github/libretube/PipedApi.kt @@ -13,6 +13,9 @@ interface PipedApi { @GET("comments/{videoId}") suspend fun getComments(@Path("videoId") videoId: String): CommentsPage + @GET("sponsors/{videoId}") + 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 diff --git a/app/src/main/java/com/github/libretube/PlayerFragment.kt b/app/src/main/java/com/github/libretube/PlayerFragment.kt index 459a9809c..8c7691023 100644 --- a/app/src/main/java/com/github/libretube/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/PlayerFragment.kt @@ -14,6 +14,7 @@ import android.os.Build.VERSION.SDK_INT import android.os.Bundle import android.os.Environment import android.text.Html +import android.text.TextUtils import android.util.Log import android.view.LayoutInflater import android.view.View @@ -35,6 +36,8 @@ import androidx.recyclerview.widget.RecyclerView import com.github.libretube.adapters.CommentsAdapter import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.obj.PipedStream +import com.github.libretube.obj.Segment +import com.github.libretube.obj.Segments import com.github.libretube.obj.Subscribe import com.google.android.exoplayer2.C import com.google.android.exoplayer2.ExoPlayer @@ -87,6 +90,7 @@ class PlayerFragment : Fragment() { private lateinit var motionLayout: MotionLayout private lateinit var exoPlayer: ExoPlayer private lateinit var mediaSource: MediaSource + private lateinit var segmentData: Segments private lateinit var relDownloadVideo: LinearLayout @@ -270,6 +274,26 @@ class PlayerFragment : Fragment() { } } + private fun checkForSegments() + { + if (!exoPlayer.isPlaying || !SponsorBlockSettings.sponsorBlockEnabled) return + + exoPlayerView.postDelayed(this::checkForSegments, 100) + + if(segmentData.segments.isEmpty() ) + return + + segmentData.segments.forEach { segment: Segment -> + val segmentStart = (segment.segment!![0] * 1000.0f).toLong() + val segmentEnd = (segment.segment!![1] * 1000.0f).toLong() + val currentPosition = exoPlayer.currentPosition + if(currentPosition in segmentStart until segmentEnd) { + Toast.makeText(context,R.string.segment_skipped, Toast.LENGTH_SHORT).show() + exoPlayer.seekTo(segmentEnd); + } + } + } + private fun fetchJson(view: View) { fun run() { lifecycleScope.launchWhenCreated { @@ -297,6 +321,39 @@ class PlayerFragment : Fragment() { Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() return@launchWhenCreated } + if(SponsorBlockSettings.sponsorBlockEnabled) { + segmentData = try { + val categories: ArrayList = arrayListOf() + if (SponsorBlockSettings.introEnabled) { + categories.add("intro") + } + if (SponsorBlockSettings.selfPromoEnabled) { + categories.add("selfpromo") + } + if (SponsorBlockSettings.interactionEnabled) { + categories.add("interaction") + } + if (SponsorBlockSettings.sponsorsEnabled) { + categories.add("sponsor") + } + if (SponsorBlockSettings.outroEnabled) { + categories.add("outro") + } + + RetrofitInstance.api.getSegments(videoId!!, "[\"" + TextUtils.join("\",\"", categories) + "\"]" + ) + } catch (e: IOException) { + println(e) + Log.e(TAG, "IOException, you might not have internet connection") + Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show() + return@launchWhenCreated + } catch (e: HttpException) { + Log.e(TAG, "HttpException, unexpected response") + Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() + return@launchWhenCreated + } + } + isLoading = false var videosNameArray: Array = arrayOf() videosNameArray += "HLS" @@ -502,6 +559,13 @@ 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) + { + exoPlayerView.postDelayed(this@PlayerFragment::checkForSegments, 100) + } + } + override fun onPlayerStateChanged( playWhenReady: Boolean, playbackState: Int diff --git a/app/src/main/java/com/github/libretube/SettingsActivity.kt b/app/src/main/java/com/github/libretube/SettingsActivity.kt index 0fb13644e..d26961057 100644 --- a/app/src/main/java/com/github/libretube/SettingsActivity.kt +++ b/app/src/main/java/com/github/libretube/SettingsActivity.kt @@ -157,6 +157,15 @@ class SettingsActivity : AppCompatActivity(), true } + val sponsorblock = findPreference("sponsorblock") + sponsorblock?.setOnPreferenceClickListener { + val newFragment = SponsorBlockSettings() + parentFragmentManager.beginTransaction() + .replace(R.id.settings, newFragment) + .commitNow() + true + } + val importFromYt = findPreference("import_from_yt") importFromYt?.setOnPreferenceClickListener { val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE) diff --git a/app/src/main/java/com/github/libretube/SponsorBlockSettings.kt b/app/src/main/java/com/github/libretube/SponsorBlockSettings.kt new file mode 100644 index 000000000..813a3f472 --- /dev/null +++ b/app/src/main/java/com/github/libretube/SponsorBlockSettings.kt @@ -0,0 +1,55 @@ +package com.github.libretube + +import android.os.Bundle +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SwitchPreferenceCompat + +class SponsorBlockSettings : PreferenceFragmentCompat() { + private val TAG = "SponsorBlockDialog" + companion object { + var sponsorBlockEnabled: Boolean = false + var sponsorsEnabled: Boolean = false + var selfPromoEnabled: Boolean = false + var interactionEnabled: Boolean = false + var introEnabled: Boolean = false + var outroEnabled: Boolean = false + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.sponsorblock_settings, rootKey) + val sponsorBlockToggle = findPreference("sponsorblock_enabled_key") + sponsorBlockToggle?.setOnPreferenceChangeListener { _, newValue -> + sponsorBlockEnabled = newValue as Boolean + true + } + + val sponsorToggle = findPreference("sponsors_category_key") + sponsorToggle?.setOnPreferenceChangeListener { _, newValue -> + sponsorsEnabled = newValue as Boolean + true + } + val selfPromoToggle = findPreference("selfpromo_category_key") + selfPromoToggle?.setOnPreferenceChangeListener { _, newValue -> + selfPromoEnabled = newValue as Boolean + true + } + + val interactionToggle = findPreference("interaction_category_key") + interactionToggle?.setOnPreferenceChangeListener { _, newValue -> + interactionEnabled = newValue as Boolean + true + } + + val introToggle = findPreference("intro_category_key") + introToggle?.setOnPreferenceChangeListener { _, newValue -> + introEnabled = newValue as Boolean + true + } + + val outroToggle = findPreference("outro_category_key") + outroToggle?.setOnPreferenceChangeListener { _, newValue -> + outroEnabled = newValue as Boolean + true + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/libretube/obj/Segment.kt b/app/src/main/java/com/github/libretube/obj/Segment.kt new file mode 100644 index 000000000..4608971b7 --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/Segment.kt @@ -0,0 +1,12 @@ +package com.github.libretube.obj + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Segment( + val actionType: String?, + val category: String?, + val segment: List? +){ + constructor(): this("", "", arrayListOf()) +} diff --git a/app/src/main/java/com/github/libretube/obj/Segments.kt b/app/src/main/java/com/github/libretube/obj/Segments.kt new file mode 100644 index 000000000..a6ed285bc --- /dev/null +++ b/app/src/main/java/com/github/libretube/obj/Segments.kt @@ -0,0 +1,10 @@ +package com.github.libretube.obj + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties + +@JsonIgnoreProperties(ignoreUnknown = true) +data class Segments( + val segments: MutableList = arrayListOf() +){ + constructor(): this(arrayListOf()) +} diff --git a/app/src/main/res/drawable/ic_sponsorblock.xml b/app/src/main/res/drawable/ic_sponsorblock.xml new file mode 100644 index 000000000..ffdc099ab --- /dev/null +++ b/app/src/main/res/drawable/ic_sponsorblock.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_sponsorblock.xml b/app/src/main/res/layout/fragment_sponsorblock.xml new file mode 100644 index 000000000..329590044 --- /dev/null +++ b/app/src/main/res/layout/fragment_sponsorblock.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 51d9d8b8e..678cac795 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,4 +72,19 @@ No Internet Connection Retry Comments + SponsorBlock + Skipped segment. + SponsorBlock + Enabled + Segments + Sponsor + Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like. + Unpaid/Self Promotion + Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like. + Interaction Reminder (Subscribe) + When there is a short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should be under self promotion instead. + Intermission/Intro Animation + An interval without actual content. Could be a pause, static frame, repeating animation. This should not be used for transitions containing information. + Endcards/Credits + Credits or when the YouTube endcards appear. Not for conclusions with information. diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 56ae14456..bee43d0fc 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -71,6 +71,12 @@ android:icon="@drawable/ic_theme" /> + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e215c9b0b46ba26cb80672c95ebfe7bd267ab1d6 Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 13:13:39 +0300 Subject: [PATCH 10/17] Fix small format error --- app/src/main/java/com/github/libretube/PlayerFragment.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/libretube/PlayerFragment.kt b/app/src/main/java/com/github/libretube/PlayerFragment.kt index 8c7691023..96ab68380 100644 --- a/app/src/main/java/com/github/libretube/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/PlayerFragment.kt @@ -340,8 +340,7 @@ class PlayerFragment : Fragment() { categories.add("outro") } - RetrofitInstance.api.getSegments(videoId!!, "[\"" + TextUtils.join("\",\"", categories) + "\"]" - ) + RetrofitInstance.api.getSegments(videoId!!, "[\"" + TextUtils.join("\",\"", categories) + "\"]") } catch (e: IOException) { println(e) Log.e(TAG, "IOException, you might not have internet connection") From 6006996d15b3f1d8f8e87a6d350ed2837e2dcb61 Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 13:19:16 +0300 Subject: [PATCH 11/17] Get rid of unused fragment that I left while testing --- app/src/main/res/layout/fragment_sponsorblock.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 app/src/main/res/layout/fragment_sponsorblock.xml diff --git a/app/src/main/res/layout/fragment_sponsorblock.xml b/app/src/main/res/layout/fragment_sponsorblock.xml deleted file mode 100644 index 329590044..000000000 --- a/app/src/main/res/layout/fragment_sponsorblock.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file From 2910aceb3fbd2eb36c679bfe31c2ebd9cb145f67 Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 13:34:13 +0300 Subject: [PATCH 12/17] Don't retrieve segments if no category is enabled --- .../com/github/libretube/PlayerFragment.kt | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/github/libretube/PlayerFragment.kt b/app/src/main/java/com/github/libretube/PlayerFragment.kt index 96ab68380..9c41a40dc 100644 --- a/app/src/main/java/com/github/libretube/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/PlayerFragment.kt @@ -322,34 +322,41 @@ class PlayerFragment : Fragment() { return@launchWhenCreated } if(SponsorBlockSettings.sponsorBlockEnabled) { - segmentData = try { - val categories: ArrayList = arrayListOf() - if (SponsorBlockSettings.introEnabled) { - categories.add("intro") - } - if (SponsorBlockSettings.selfPromoEnabled) { - categories.add("selfpromo") - } - if (SponsorBlockSettings.interactionEnabled) { - categories.add("interaction") - } - if (SponsorBlockSettings.sponsorsEnabled) { - categories.add("sponsor") - } - if (SponsorBlockSettings.outroEnabled) { - categories.add("outro") - } + val categories: ArrayList = arrayListOf() + if (SponsorBlockSettings.introEnabled) { + categories.add("intro") + } + if (SponsorBlockSettings.selfPromoEnabled) { + categories.add("selfpromo") + } + if (SponsorBlockSettings.interactionEnabled) { + categories.add("interaction") + } + if (SponsorBlockSettings.sponsorsEnabled) { + categories.add("sponsor") + } + if (SponsorBlockSettings.outroEnabled) { + categories.add("outro") + } + if(categories.size > 0) { + segmentData = try { - RetrofitInstance.api.getSegments(videoId!!, "[\"" + TextUtils.join("\",\"", categories) + "\"]") - } catch (e: IOException) { - println(e) - Log.e(TAG, "IOException, you might not have internet connection") - Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show() - return@launchWhenCreated - } catch (e: HttpException) { - Log.e(TAG, "HttpException, unexpected response") - Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() - return@launchWhenCreated + RetrofitInstance.api.getSegments( + videoId!!, + "[\"" + TextUtils.join("\",\"", categories) + "\"]" + ) + } catch (e: IOException) { + println(e) + Log.e(TAG, "IOException, you might not have internet connection") + Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT) + .show() + return@launchWhenCreated + } catch (e: HttpException) { + Log.e(TAG, "HttpException, unexpected response") + Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT) + .show() + return@launchWhenCreated + } } } From 1677d9267958090dab2360647d5895f5b9c05883 Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 13:58:27 +0300 Subject: [PATCH 13/17] Fixed wrong description for self promotions --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 678cac795..64a646591 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,7 +80,7 @@ Sponsor Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like. Unpaid/Self Promotion - Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like. + Similar to \"sponsor\" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with. Interaction Reminder (Subscribe) When there is a short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should be under self promotion instead. Intermission/Intro Animation From 418266f06efddb2e170ee77d8a4dfb15701b15ec Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 15:30:26 +0300 Subject: [PATCH 14/17] Add API link per SponsorBlock license requirements --- app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/settings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 64a646591..9197b2733 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -73,6 +73,7 @@ Retry Comments SponsorBlock + Uses API from https://sponsor.ajay.app/ Skipped segment. SponsorBlock Enabled diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index bee43d0fc..21b5e8632 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -74,6 +74,7 @@ From a3cec2027ccf987e5c40450c5d072abfdee01d6c Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 May 2022 17:33:22 +0200 Subject: [PATCH 15/17] Load channels only once --- app/src/main/java/com/github/libretube/Subscriptions.kt | 9 +++++++-- app/src/main/res/layout/fragment_subscriptions.xml | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/Subscriptions.kt b/app/src/main/java/com/github/libretube/Subscriptions.kt index 6dba0f985..5db11caac 100644 --- a/app/src/main/java/com/github/libretube/Subscriptions.kt +++ b/app/src/main/java/com/github/libretube/Subscriptions.kt @@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.github.libretube.adapters.SubscriptionAdapter import com.github.libretube.adapters.SubscriptionChannelAdapter +import org.chromium.base.ThreadUtils.runOnUiThread import retrofit2.HttpException import java.io.IOException @@ -67,10 +68,14 @@ class Subscriptions : Fragment() { var toggleSubs = view.findViewById(R.id.toggle_subs) toggleSubs.visibility = View.VISIBLE + var loadedSubbedChannels = false toggleSubs.setOnClickListener { if (!channelRecView.isVisible) { - channelRecView?.layoutManager = GridLayoutManager(context, 4) - fetchChannels(channelRecView) + if (!loadedSubbedChannels) { + channelRecView?.layoutManager = GridLayoutManager(context, 4) + fetchChannels(channelRecView) + loadedSubbedChannels = true + } channelRecView.visibility = View.VISIBLE feedRecView.visibility = View.GONE } diff --git a/app/src/main/res/layout/fragment_subscriptions.xml b/app/src/main/res/layout/fragment_subscriptions.xml index ec0bd7bc6..90f827f8e 100644 --- a/app/src/main/res/layout/fragment_subscriptions.xml +++ b/app/src/main/res/layout/fragment_subscriptions.xml @@ -58,7 +58,7 @@ android:id="@+id/toggle_subs" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="10dp" + android:layout_margin="12dp" android:visibility="gone"> Date: Mon, 16 May 2022 15:55:35 +0200 Subject: [PATCH 16/17] Update strings.xml --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0920a44e9..bc68be368 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,5 +88,5 @@ Intermission/Intro Animation An interval without actual content. Could be a pause, static frame, repeating animation. This should not be used for transitions containing information. Endcards/Credits - Credits or when the YouTube endcards appear. Not for conclusions with information.Credits or when the YouTube endcards appear. Not for conclusions with information. From 535d0093426323db7880f05b9975c7e8af91fa6a Mon Sep 17 00:00:00 2001 From: janisslsm <97699850+janisslsm@users.noreply.github.com> Date: Mon, 16 May 2022 17:03:18 +0300 Subject: [PATCH 17/17] Reorder sponsorblock --- app/src/main/res/xml/settings.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index fe7ab3ef1..18349aaa1 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -71,7 +71,14 @@ android:icon="@drawable/ic_theme" /> - + + - -