From f74ef1e38cbcc8b755d0658ebd49843216f40893 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 13 Jun 2022 16:15:02 +0200 Subject: [PATCH 1/9] chapters --- .../libretube/adapters/ChaptersAdapter.kt | 48 ++++++++++++++ .../libretube/fragments/PlayerFragment.kt | 25 +++++++- .../libretube/fragments/SearchFragment.kt | 1 - app/src/main/res/layout/chapter_column.xml | 24 +++++++ app/src/main/res/layout/fragment_player.xml | 63 +++++++++++++++---- .../main/res/layout/searchsuggestion_row.xml | 2 +- app/src/main/res/values/strings.xml | 2 + 7 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/adapters/ChaptersAdapter.kt create mode 100644 app/src/main/res/layout/chapter_column.xml diff --git a/app/src/main/java/com/github/libretube/adapters/ChaptersAdapter.kt b/app/src/main/java/com/github/libretube/adapters/ChaptersAdapter.kt new file mode 100644 index 000000000..66a0d7247 --- /dev/null +++ b/app/src/main/java/com/github/libretube/adapters/ChaptersAdapter.kt @@ -0,0 +1,48 @@ +package com.github.libretube.adapters + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.github.libretube.R +import com.github.libretube.obj.ChapterSegment +import com.google.android.exoplayer2.ExoPlayer +import com.squareup.picasso.Picasso + +class ChaptersAdapter( + private val chapters: List, + private val exoPlayer: ExoPlayer +) : RecyclerView.Adapter() { + val TAG = "ChaptersAdapter" + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChaptersViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val cell = layoutInflater.inflate(R.layout.chapter_column, parent, false) + return ChaptersViewHolder(cell) + } + + override fun onBindViewHolder(holder: ChaptersViewHolder, position: Int) { + val chapter = chapters[position] + val chapterImage = holder.v.findViewById(R.id.chapter_image) + Picasso.get().load(chapter.image).fit().centerCrop().into(chapterImage) + + val chapterTitle = holder.v.findViewById(R.id.chapter_title) + chapterTitle.text = chapter.title + + holder.v.setOnClickListener { + val chapterStart = chapter.start!!.toLong() * 1000 // multiply by thousand for ms -> s + exoPlayer.seekTo(chapterStart) + } + } + + override fun getItemCount(): Int { + return chapters.size + } +} + +class ChaptersViewHolder(val v: View) : RecyclerView.ViewHolder(v) { + init { + } +} diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index cfec34244..224d31801 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -43,6 +43,7 @@ import androidx.recyclerview.widget.RecyclerView import com.github.libretube.IS_DOWNLOAD_RUNNING import com.github.libretube.MainActivity import com.github.libretube.R +import com.github.libretube.adapters.ChaptersAdapter import com.github.libretube.adapters.CommentsAdapter import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.dialogs.AddtoPlaylistDialog @@ -597,8 +598,28 @@ class PlayerFragment : Fragment() { } private fun initializeChapters(chapters: List) { - chapters.forEach { chapter -> - Log.e(TAG, chapter.title!!) + val chaptersToggle = view?.findViewById(R.id.chapters_toggle) + val chaptersRecView = view?.findViewById(R.id.chapters_recView) + val chaptersToggleText = view?.findViewById(R.id.chapters_toggle_text) + val chaptersToggleArrow = view?.findViewById(R.id.chapters_toggle_arrow) + + if (chapters.isNotEmpty()) { + chaptersToggle?.visibility = View.VISIBLE + + chaptersToggle?.setOnClickListener { + if (chaptersRecView?.isVisible!!) { + chaptersRecView?.visibility = View.GONE + chaptersToggleText?.text = getString(R.string.show_chapters) + } else { + chaptersRecView?.visibility = View.VISIBLE + chaptersToggleText?.text = getString(R.string.hide_chapters) + } + chaptersToggleArrow!!.animate().setDuration(100).rotationBy(180F).start() + } + + chaptersRecView?.layoutManager = + LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false) + chaptersRecView?.adapter = ChaptersAdapter(chapters, exoPlayer) } } diff --git a/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt b/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt index 63ddd43e4..a61714dd8 100644 --- a/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt @@ -198,7 +198,6 @@ class SearchFragment : Fragment() { lifecycleScope.launchWhenCreated { isFetchingSearch = true hideKeyboard() - Log.e("here", "here") val response = try { RetrofitInstance.api.getSearchResults(query, apiSearchFilter) } catch (e: IOException) { diff --git a/app/src/main/res/layout/chapter_column.xml b/app/src/main/res/layout/chapter_column.xml new file mode 100644 index 000000000..4f5171ea4 --- /dev/null +++ b/app/src/main/res/layout/chapter_column.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_player.xml b/app/src/main/res/layout/fragment_player.xml index 2622e435a..212256b9e 100644 --- a/app/src/main/res/layout/fragment_player.xml +++ b/app/src/main/res/layout/fragment_player.xml @@ -26,15 +26,16 @@ android:orientation="vertical"> - + + + + + + + + + + + + + + + android:nestedScrollingEnabled="false" + android:visibility="gone" /> + android:text="@string/download" /> diff --git a/app/src/main/res/layout/searchsuggestion_row.xml b/app/src/main/res/layout/searchsuggestion_row.xml index 09200c426..c7d535866 100644 --- a/app/src/main/res/layout/searchsuggestion_row.xml +++ b/app/src/main/res/layout/searchsuggestion_row.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="8dp" - android:paddingVertical="6dp" + android:paddingVertical="8dp" android:background="?android:attr/selectableItemBackground"> Get to know team LibreTube and how it all happens. Related streams Show related streams to videos. + Show chapters + Hide chapters From 7105bc786987ea19879d6463ed7a81b7dfd7c1b1 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 13 Jun 2022 21:19:19 +0200 Subject: [PATCH 2/9] video options dialog in subscriptions page and minor bug fixes --- .../libretube/adapters/ChannelAdapter.kt | 13 +- .../libretube/dialogs/VideoOptionsDialog.kt | 3 +- .../libretube/fragments/ChannelFragment.kt | 5 +- .../libretube/preferences/InstanceSettings.kt | 2 - .../main/res/drawable/ic_empty_playlist.xml | 10 +- app/src/main/res/layout/comments_row.xml | 165 +++++++++--------- app/src/main/res/layout/fragment_about.xml | 15 +- .../main/res/layout/searchsuggestion_row.xml | 1 - app/src/main/res/xml/advanced_settings.xml | 61 +++---- app/src/main/res/xml/appearance_settings.xml | 51 +++--- 10 files changed, 172 insertions(+), 154 deletions(-) diff --git a/app/src/main/java/com/github/libretube/adapters/ChannelAdapter.kt b/app/src/main/java/com/github/libretube/adapters/ChannelAdapter.kt index 28f716ac1..7dbf5d9d7 100644 --- a/app/src/main/java/com/github/libretube/adapters/ChannelAdapter.kt +++ b/app/src/main/java/com/github/libretube/adapters/ChannelAdapter.kt @@ -8,14 +8,19 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.RecyclerView import com.github.libretube.R +import com.github.libretube.dialogs.VideoOptionsDialog import com.github.libretube.fragments.PlayerFragment import com.github.libretube.obj.StreamItem import com.github.libretube.util.formatShort import com.squareup.picasso.Picasso -class ChannelAdapter(private val videoFeed: MutableList) : +class ChannelAdapter( + private val videoFeed: MutableList, + private val childFragmentManager: FragmentManager +) : RecyclerView.Adapter() { override fun getItemCount(): Int { return videoFeed.size @@ -55,6 +60,12 @@ class ChannelAdapter(private val videoFeed: MutableList) : .replace(R.id.container, frag) .commitNow() } + holder.v.setOnLongClickListener { + val videoId = trending.url!!.replace("/watch?v=", "") + VideoOptionsDialog(videoId, holder.v.context) + .show(childFragmentManager, VideoOptionsDialog.TAG) + true + } } } diff --git a/app/src/main/java/com/github/libretube/dialogs/VideoOptionsDialog.kt b/app/src/main/java/com/github/libretube/dialogs/VideoOptionsDialog.kt index 19a521ee8..532808e0d 100644 --- a/app/src/main/java/com/github/libretube/dialogs/VideoOptionsDialog.kt +++ b/app/src/main/java/com/github/libretube/dialogs/VideoOptionsDialog.kt @@ -67,7 +67,8 @@ class VideoOptionsDialog(private val videoId: String, context: Context) : Dialog } 2 -> { val shareDialog = ShareDialog(videoId) - shareDialog.show(childFragmentManager, "ShareDialog") + // using parentFragmentManager is important here + shareDialog.show(parentFragmentManager, "ShareDialog") } else -> { dialog.dismiss() diff --git a/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt b/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt index d7c3fd030..f42f95b69 100644 --- a/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt @@ -218,7 +218,10 @@ class ChannelFragment : Fragment() { val channelImage = view.findViewById(R.id.channel_image) Picasso.get().load(response.bannerUrl).into(bannerImage) Picasso.get().load(response.avatarUrl).into(channelImage) - channelAdapter = ChannelAdapter(response.relatedStreams!!.toMutableList()) + channelAdapter = ChannelAdapter( + response.relatedStreams!!.toMutableList(), + childFragmentManager + ) view.findViewById(R.id.channel_recView).adapter = channelAdapter } } diff --git a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt index 6e125f17b..430f89944 100644 --- a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt +++ b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt @@ -13,7 +13,6 @@ import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.core.app.ActivityCompat -import androidx.core.app.ActivityCompat.recreate import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope @@ -30,7 +29,6 @@ import java.io.IOException import java.io.InputStream import java.util.zip.ZipEntry import java.util.zip.ZipInputStream -import org.chromium.base.ThreadUtils.runOnUiThread import org.json.JSONObject import org.json.JSONTokener import retrofit2.HttpException diff --git a/app/src/main/res/drawable/ic_empty_playlist.xml b/app/src/main/res/drawable/ic_empty_playlist.xml index 819452cc1..3b7371ebc 100644 --- a/app/src/main/res/drawable/ic_empty_playlist.xml +++ b/app/src/main/res/drawable/ic_empty_playlist.xml @@ -3,9 +3,9 @@ android:height="144dp" android:viewportWidth="143" android:viewportHeight="144" - android:tint="?android:attr/colorControlNormal" > - + android:tint="?android:attr/colorControlNormal"> + diff --git a/app/src/main/res/layout/comments_row.xml b/app/src/main/res/layout/comments_row.xml index 295108ce1..d764f3b71 100644 --- a/app/src/main/res/layout/comments_row.xml +++ b/app/src/main/res/layout/comments_row.xml @@ -9,105 +9,106 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> - - - + android:paddingBottom="16dp"> + + - - - - - - - - - + android:orientation="vertical"> - + - + + + + + + + android:layout_marginBottom="4dp" + android:autoLink="web" + android:text="Comment Text" /> - + + + + + + + + - - + diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 7d9f03a4d..63936c4c3 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -39,7 +39,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingHorizontal="20dp" android:paddingVertical="10dp"> + android:paddingHorizontal="20dp" + android:paddingVertical="10dp"> + android:paddingHorizontal="20dp" + android:paddingVertical="10dp"> + android:paddingHorizontal="20dp" + android:paddingVertical="10dp"> + android:paddingHorizontal="20dp" + android:paddingVertical="10dp"> + android:paddingHorizontal="20dp" + android:paddingVertical="10dp"> @@ -27,55 +27,44 @@ + app:title="@string/video_format" /> + app:icon="@drawable/ic_download" + app:key="download_location" + app:summary="@string/download_directory_summary" + app:title="@string/download_directory" /> + app:key="download_folder" + app:summary="@string/download_folder_summary" + app:title="@string/download_folder" /> + android:icon="@drawable/ic_history" + app:key="search_history_toggle" + app:title="@string/search_history" /> - - - - - - + app:title="@string/clear_history" /> diff --git a/app/src/main/res/xml/appearance_settings.xml b/app/src/main/res/xml/appearance_settings.xml index 592084d19..5b52bb864 100644 --- a/app/src/main/res/xml/appearance_settings.xml +++ b/app/src/main/res/xml/appearance_settings.xml @@ -5,30 +5,30 @@ @@ -36,23 +36,34 @@ + + + + + + \ No newline at end of file From ccca33f9d0be1089a3a372d3b015b896385915c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jun 2022 06:49:43 +0000 Subject: [PATCH 3/9] Bump ScaCap/action-ktlint from 1.3 to 1.4 Bumps [ScaCap/action-ktlint](https://github.com/ScaCap/action-ktlint) from 1.3 to 1.4. - [Release notes](https://github.com/ScaCap/action-ktlint/releases) - [Commits](https://github.com/ScaCap/action-ktlint/compare/1.3...1.4) --- updated-dependencies: - dependency-name: ScaCap/action-ktlint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8e5b4d0ec..f7b10d0ac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,7 +10,7 @@ jobs: with: fetch-depth: 1 - name: ktlint - uses: ScaCap/action-ktlint@1.3 + uses: ScaCap/action-ktlint@1.4 with: github_token: ${{ secrets.GITHUB_TOKEN }} reporter: github-pr-check From dfde1354d6f4e55a43e44b68823128eabefa9e20 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 Jun 2022 10:46:35 +0200 Subject: [PATCH 4/9] added support for time stamped links --- .../java/com/github/libretube/MainActivity.kt | 74 +++++++++---------- .../libretube/fragments/PlayerFragment.kt | 8 +- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/github/libretube/MainActivity.kt b/app/src/main/java/com/github/libretube/MainActivity.kt index 183fe853f..2f05022a3 100644 --- a/app/src/main/java/com/github/libretube/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/MainActivity.kt @@ -10,6 +10,7 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Handler +import android.os.Looper import android.util.Log import android.util.TypedValue import android.view.View @@ -199,19 +200,12 @@ class MainActivity : AppCompatActivity() { .replace("/embed/", "") val bundle = Bundle() bundle.putString("videoId", watch) - val frag = PlayerFragment() - frag.arguments = bundle - supportFragmentManager.beginTransaction() - .remove(PlayerFragment()) - .commit() - supportFragmentManager.beginTransaction() - .replace(R.id.container, frag) - .commitNow() - Handler().postDelayed({ - val motionLayout = findViewById(R.id.playerMotionLayout) - motionLayout.transitionToEnd() - motionLayout.transitionToStart() - }, 100) + // for time stamped links + if (data.query?.contains("t=")!!) { + val timeStamp = data.query.toString().split("t=")[1] + bundle.putLong("timeStamp", timeStamp.toLong()) + } + loadWatch(bundle) } else if (data.path!!.contains("/watch") && data.query != null) { Log.d("dafaq", data.query!!) var watch = data.query!! @@ -226,39 +220,41 @@ class MainActivity : AppCompatActivity() { } var bundle = Bundle() bundle.putString("videoId", watch.replace("v=", "")) - var frag = PlayerFragment() - frag.arguments = bundle - supportFragmentManager.beginTransaction() - .remove(PlayerFragment()) - .commit() - supportFragmentManager.beginTransaction() - .replace(R.id.container, frag) - .commitNow() - Handler().postDelayed({ - val motionLayout = findViewById(R.id.playerMotionLayout) - motionLayout.transitionToEnd() - motionLayout.transitionToStart() - }, 100) + // for time stamped links + if (data.query?.contains("t=")!!) { + val timeStamp = data.query.toString().split("t=")[1] + bundle.putLong("timeStamp", timeStamp.toLong()) + } + loadWatch(bundle) } else { var watch = data.path!!.replace("/", "") var bundle = Bundle() bundle.putString("videoId", watch) - var frag = PlayerFragment() - frag.arguments = bundle - supportFragmentManager.beginTransaction() - .remove(PlayerFragment()) - .commit() - supportFragmentManager.beginTransaction() - .replace(R.id.container, frag) - .commitNow() - Handler().postDelayed({ - val motionLayout = findViewById(R.id.playerMotionLayout) - motionLayout.transitionToEnd() - motionLayout.transitionToStart() - }, 100) + // for time stamped links + if (data.query?.contains("t=")!!) { + val timeStamp = data.query.toString().split("t=")[1] + bundle.putLong("timeStamp", timeStamp.toLong()) + } + loadWatch(bundle) } } + private fun loadWatch(bundle: Bundle) { + var frag = PlayerFragment() + frag.arguments = bundle + supportFragmentManager.beginTransaction() + .remove(PlayerFragment()) + .commit() + supportFragmentManager.beginTransaction() + .replace(R.id.container, frag) + .commitNow() + Handler(Looper.getMainLooper()).postDelayed({ + val motionLayout = findViewById(R.id.playerMotionLayout) + motionLayout.transitionToEnd() + motionLayout.transitionToStart() + }, 100) + } + override fun onBackPressed() { try { val mainMotionLayout = findViewById(R.id.mainMotionLayout) diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index 224d31801..255b2f2b4 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -435,9 +435,15 @@ class PlayerFragment : Fragment() { prepareExoPlayerView() if (response.chapters != null) initializeChapters(response.chapters) setResolutionAndSubtitles(view, response) + // support for time stamped links + if (arguments?.getLong("timeStamp") != null) { + val position = arguments?.getLong("timeStamp")!! * 1000 + exoPlayer.seekTo(position) + } exoPlayer.prepare() exoPlayer.play() initializePlayerView(view, response) + initializePlayerNotification(requireContext()) if (!relatedStreamsEnabled) toggleComments() } } @@ -843,8 +849,6 @@ class PlayerFragment : Fragment() { val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) val playbackSpeed = sharedPreferences.getString("playback_speed", "1F")?.toFloat() exoPlayer.setPlaybackSpeed(playbackSpeed!!) - - initializePlayerNotification(requireContext()) } private fun initializePlayerNotification(c: Context) { From 2a8ae96feb9787ac26f6969d3e1fe24493f0416d Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 Jun 2022 12:00:58 +0200 Subject: [PATCH 5/9] notification thumbnail and description --- .../libretube/fragments/PlayerFragment.kt | 70 ++++++++++++------- .../libretube/util/DescriptionAdapter.kt | 56 +++++++++++++++ 2 files changed, 102 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index 255b2f2b4..c8792bdcf 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -58,6 +58,7 @@ import com.github.libretube.obj.Streams import com.github.libretube.obj.Subscribe import com.github.libretube.preferences.SponsorBlockSettings import com.github.libretube.util.CronetHelper +import com.github.libretube.util.DescriptionAdapter import com.github.libretube.util.RetrofitInstance import com.github.libretube.util.formatShort import com.google.android.exoplayer2.C @@ -85,11 +86,11 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.squareup.picasso.Picasso +import org.chromium.net.CronetEngine +import retrofit2.HttpException import java.io.IOException import java.util.concurrent.Executors import kotlin.math.abs -import org.chromium.net.CronetEngine -import retrofit2.HttpException var isFullScreen = false @@ -123,6 +124,10 @@ class PlayerFragment : Fragment() { private lateinit var mediaSessionConnector: MediaSessionConnector private lateinit var playerNotification: PlayerNotificationManager + private lateinit var title: String + private lateinit var uploader: String + private lateinit var thumbnailUrl: String + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.let { @@ -209,7 +214,7 @@ class PlayerFragment : Fragment() { playerMotionLayout.progress = 1.toFloat() playerMotionLayout.transitionToStart() - fetchJson(view) + fetchJsonAndInitPlayer(view) view.findViewById(R.id.close_imageView).setOnClickListener { motionLayout.transitionToEnd() val mainActivity = activity as MainActivity @@ -373,7 +378,7 @@ class PlayerFragment : Fragment() { } } - private fun fetchJson(view: View) { + private fun fetchJsonAndInitPlayer(view: View) { fun run() { lifecycleScope.launchWhenCreated { val response = try { @@ -388,6 +393,40 @@ class PlayerFragment : Fragment() { Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() return@launchWhenCreated } + // for the notification description adapter + title = response.title!! + uploader = response.uploader!! + thumbnailUrl = response.thumbnailUrl!! + + // check whether related streams are enabled + val sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(requireContext()) + relatedStreamsEnabled = sharedPreferences.getBoolean("related_streams_toggle", true) + runOnUiThread { + createExoPlayer(view) + prepareExoPlayerView() + if (response.chapters != null) initializeChapters(response.chapters) + setResolutionAndSubtitles(view, response) + // support for time stamped links + if (arguments?.getLong("timeStamp") != null) { + val position = arguments?.getLong("timeStamp")!! * 1000 + exoPlayer.seekTo(position) + } + exoPlayer.prepare() + exoPlayer.play() + initializePlayerView(view, response) + initializePlayerNotification(requireContext()) + fetchSponsorBlockSegments() + if (!relatedStreamsEnabled) toggleComments() + } + } + } + run() + } + + private fun fetchSponsorBlockSegments() { + fun run() { + lifecycleScope.launchWhenCreated { if (SponsorBlockSettings.sponsorBlockEnabled) { val categories: ArrayList = arrayListOf() if (SponsorBlockSettings.introEnabled) { @@ -426,26 +465,6 @@ class PlayerFragment : Fragment() { } } } - // check whether related streams are enabled - val sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(requireContext()) - relatedStreamsEnabled = sharedPreferences.getBoolean("related_streams_toggle", true) - runOnUiThread { - createExoPlayer(view) - prepareExoPlayerView() - if (response.chapters != null) initializeChapters(response.chapters) - setResolutionAndSubtitles(view, response) - // support for time stamped links - if (arguments?.getLong("timeStamp") != null) { - val position = arguments?.getLong("timeStamp")!! * 1000 - exoPlayer.seekTo(position) - } - exoPlayer.prepare() - exoPlayer.play() - initializePlayerView(view, response) - initializePlayerNotification(requireContext()) - if (!relatedStreamsEnabled) toggleComments() - } } } run() @@ -863,6 +882,9 @@ class PlayerFragment : Fragment() { playerNotification = PlayerNotificationManager .Builder(c, 1, "background_mode") + .setMediaDescriptionAdapter( + DescriptionAdapter(title, uploader, thumbnailUrl) + ) .build() playerNotification.apply { diff --git a/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt new file mode 100644 index 000000000..b0b997e1a --- /dev/null +++ b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt @@ -0,0 +1,56 @@ +package com.github.libretube.util + +import android.app.PendingIntent +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import com.google.android.exoplayer2.Player +import com.google.android.exoplayer2.ui.PlayerNotificationManager +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import java.net.URL + + +// used to show title and thumbnail of the video in the notification +class DescriptionAdapter( + private val title: String, + private val channelName: String, + private val thumbnailUrl: String) : + PlayerNotificationManager.MediaDescriptionAdapter { + override fun getCurrentContentTitle(player: Player): CharSequence { + // return controller.metadata.description.title.toString() + return title + } + + override fun createCurrentContentIntent(player: Player): PendingIntent? { + // return controller.sessionActivity + return null + } + + override fun getCurrentContentText(player: Player): CharSequence? { + // return controller.metadata.description.subtitle.toString() + return channelName + } + + override fun getCurrentLargeIcon( + player: Player, + callback: PlayerNotificationManager.BitmapCallback + ): Bitmap? { + lateinit var bitmap: Bitmap + val thread = Thread { + try { + val inputStream = URL(thumbnailUrl).openStream() + bitmap = BitmapFactory.decodeStream(inputStream) + } catch (ex: java.lang.Exception) { + ex.printStackTrace() + } + } + thread.start() + thread.join() + return try { + bitmap + } catch (e: Exception) { + null + } + } +} \ No newline at end of file From 388e9fa90b2707582cee6041579e6bb9623df2c9 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 Jun 2022 12:21:18 +0200 Subject: [PATCH 6/9] added to background mode and code cleanup --- .../com/github/libretube/BackgroundMode.kt | 23 +++++++++---- .../libretube/fragments/PlayerFragment.kt | 34 ++++++------------- .../libretube/util/DescriptionAdapter.kt | 9 ++--- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/github/libretube/BackgroundMode.kt b/app/src/main/java/com/github/libretube/BackgroundMode.kt index c85e4fd06..3f51ea58b 100644 --- a/app/src/main/java/com/github/libretube/BackgroundMode.kt +++ b/app/src/main/java/com/github/libretube/BackgroundMode.kt @@ -3,6 +3,7 @@ package com.github.libretube import android.content.Context import android.support.v4.media.session.MediaSessionCompat import com.github.libretube.obj.Streams +import com.github.libretube.util.DescriptionAdapter import com.github.libretube.util.RetrofitInstance import com.google.android.exoplayer2.C import com.google.android.exoplayer2.ExoPlayer @@ -10,6 +11,7 @@ import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.audio.AudioAttributes import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import com.google.android.exoplayer2.ui.PlayerNotificationManager +import gen._base._base_java__rjava_resources.srcjar.R.id.title import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -66,13 +68,20 @@ class BackgroundMode { /** * Initializes the [playerNotification] attached to the [player] and shows it. */ - private fun initializePlayerNotification(c: Context) { + private fun initializePlayerNotification(c: Context, streams: Streams) { playerNotification = PlayerNotificationManager - .Builder(c, 1, "background_mode").build() - playerNotification.setPlayer(player) - playerNotification.setUsePreviousAction(false) - playerNotification.setUseNextAction(false) - playerNotification.setMediaSessionToken(mediaSession.sessionToken) + .Builder(c, 1, "background_mode") + // set the description of the notification + .setMediaDescriptionAdapter( + DescriptionAdapter(streams.title!!, streams.uploader!!, streams.thumbnailUrl!!) + ) + .build() + playerNotification.apply { + setPlayer(player) + setUsePreviousAction(false) + setUseNextAction(false) + setMediaSessionToken(mediaSession.sessionToken) + } } /** @@ -104,7 +113,7 @@ class BackgroundMode { job.join() initializePlayer(c) - initializePlayerNotification(c) + initializePlayerNotification(c, response!!) player?.apply { playWhenReady = playWhenReadyPlayer diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index c8792bdcf..3c6828e59 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -18,9 +18,6 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.LinearInterpolator -import android.view.animation.RotateAnimation import android.widget.FrameLayout import android.widget.ImageButton import android.widget.ImageView @@ -86,11 +83,11 @@ import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.squareup.picasso.Picasso -import org.chromium.net.CronetEngine -import retrofit2.HttpException import java.io.IOException import java.util.concurrent.Executors import kotlin.math.abs +import org.chromium.net.CronetEngine +import retrofit2.HttpException var isFullScreen = false @@ -148,6 +145,11 @@ class PlayerFragment : Fragment() { super.onViewCreated(view, savedInstanceState) hideKeyboard() + initializeTransitionLayout(view) + fetchJsonAndInitPlayer(view) + } + + private fun initializeTransitionLayout(view: View) { val playerDescription = view.findViewById(R.id.player_description) videoId = videoId!!.replace("/watch?v=", "") relDownloadVideo = view.findViewById(R.id.relPlayer_download) @@ -214,7 +216,7 @@ class PlayerFragment : Fragment() { playerMotionLayout.progress = 1.toFloat() playerMotionLayout.transitionToStart() - fetchJsonAndInitPlayer(view) + view.findViewById(R.id.close_imageView).setOnClickListener { motionLayout.transitionToEnd() val mainActivity = activity as MainActivity @@ -245,25 +247,11 @@ class PlayerFragment : Fragment() { } view.findViewById(R.id.player_title_layout).setOnClickListener { + val image = view.findViewById(R.id.player_description_arrow) + image.animate().rotationBy(180F).setDuration(100).start() if (playerDescription.isVisible) { - val image = view.findViewById(R.id.player_description_arrow) - image.clearAnimation() playerDescription.visibility = View.GONE } else { - // toggle button - val rotate = RotateAnimation( - 0F, - 180F, - Animation.RELATIVE_TO_SELF, - 0.5f, - Animation.RELATIVE_TO_SELF, - 0.5f - ) - rotate.duration = 100 - rotate.interpolator = LinearInterpolator() - rotate.fillAfter = true - val image = view.findViewById(R.id.player_description_arrow) - image.startAnimation(rotate) playerDescription.visibility = View.VISIBLE } } @@ -325,8 +313,6 @@ class PlayerFragment : Fragment() { commentsRecView.layoutManager = LinearLayoutManager(view.context) commentsRecView.setItemViewCacheSize(20) - commentsRecView.isDrawingCacheEnabled = true - commentsRecView.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH relatedRecView = view.findViewById(R.id.player_recView) relatedRecView.layoutManager = diff --git a/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt index b0b997e1a..aab8853d1 100644 --- a/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt +++ b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt @@ -5,17 +5,14 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.ui.PlayerNotificationManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import java.net.URL - // used to show title and thumbnail of the video in the notification class DescriptionAdapter( private val title: String, private val channelName: String, - private val thumbnailUrl: String) : + private val thumbnailUrl: String +) : PlayerNotificationManager.MediaDescriptionAdapter { override fun getCurrentContentTitle(player: Player): CharSequence { // return controller.metadata.description.title.toString() @@ -53,4 +50,4 @@ class DescriptionAdapter( null } } -} \ No newline at end of file +} From da0bdf357cd0e470ce24fc3ab50844b1724e5161 Mon Sep 17 00:00:00 2001 From: Pantsufan Date: Tue, 14 Jun 2022 17:20:02 +0530 Subject: [PATCH 7/9] Added New SponsorBlock Categories Preview, Filler & Music Offtopic --- .../java/com/github/libretube/MainActivity.kt | 6 ++++++ .../libretube/fragments/PlayerFragment.kt | 9 ++++++++ .../preferences/SponsorBlockSettings.kt | 21 +++++++++++++++++++ app/src/main/res/values/strings.xml | 6 ++++++ .../main/res/xml/sponsorblock_settings.xml | 15 +++++++++++++ 5 files changed, 57 insertions(+) diff --git a/app/src/main/java/com/github/libretube/MainActivity.kt b/app/src/main/java/com/github/libretube/MainActivity.kt index 2f05022a3..4e26f1451 100644 --- a/app/src/main/java/com/github/libretube/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/MainActivity.kt @@ -69,6 +69,12 @@ class MainActivity : AppCompatActivity() { sharedPreferences.getBoolean("sponsors_category_key", false) SponsorBlockSettings.outroEnabled = sharedPreferences.getBoolean("outro_category_key", false) + SponsorBlockSettings.fillerEnabled = + sharedPreferences.getBoolean("filler_category_key", false) + SponsorBlockSettings.musicOfftopicEnabled = + sharedPreferences.getBoolean("music_offtopic_category_key", false) + SponsorBlockSettings.previewEnabled = + sharedPreferences.getBoolean("preview_category_key", false) ThemeHelper().updateTheme(this) LocaleHelper().updateLanguage(this) diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index 3c6828e59..cbf71ed01 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -430,6 +430,15 @@ class PlayerFragment : Fragment() { if (SponsorBlockSettings.outroEnabled) { categories.add("outro") } + if (SponsorBlockSettings.fillerEnabled) { + categories.add("filler") + } + if (SponsorBlockSettings.musicOfftopicEnabled) { + categories.add("music_offtopic") + } + if (SponsorBlockSettings.previewEnabled) { + categories.add("preview") + } if (categories.size > 0) { segmentData = try { diff --git a/app/src/main/java/com/github/libretube/preferences/SponsorBlockSettings.kt b/app/src/main/java/com/github/libretube/preferences/SponsorBlockSettings.kt index 1579feab0..1236a8b5c 100644 --- a/app/src/main/java/com/github/libretube/preferences/SponsorBlockSettings.kt +++ b/app/src/main/java/com/github/libretube/preferences/SponsorBlockSettings.kt @@ -17,6 +17,9 @@ class SponsorBlockSettings : PreferenceFragmentCompat() { var interactionEnabled: Boolean = false var introEnabled: Boolean = false var outroEnabled: Boolean = false + var fillerEnabled: Boolean = false + var musicOfftopicEnabled: Boolean = false + var previewEnabled: Boolean = false } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -65,5 +68,23 @@ class SponsorBlockSettings : PreferenceFragmentCompat() { outroEnabled = newValue as Boolean true } + + val fillerToggle = findPreference("filler_category_key") + fillerToggle?.setOnPreferenceChangeListener { _, newValue -> + fillerEnabled = newValue as Boolean + true + } + + val musicToggle = findPreference("music_offtopic_category_key") + musicToggle?.setOnPreferenceChangeListener { _, newValue -> + musicOfftopicEnabled = newValue as Boolean + true + } + + val previewToggle = findPreference("preview_category_key") + previewToggle?.setOnPreferenceChangeListener { _, newValue -> + previewEnabled = newValue as Boolean + true + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a89c3d96..f6f5686b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -100,6 +100,12 @@ An interval without actual content. Could be a pause, static frame, repeating animation. Should not be used for transitions containing info. End cards and credits Info following the ending. Not for conclusions with info. + Filler Tangent/Jokes + This is for tangential scenes added only for filler or humor that are not required to understand the main content of the video. + Music: Non-Music Section + This is only for use in music videos. It should cover parts of the video not part of official mixes. In the end, the video should resemble the Spotify or any other mix version as closely as possible, or should reduce talking or other distractions. + Preview/Recap + For segments that show what is coming up in this or future videos of the same series, but do not provide additional information. If it includes clips that only appear here, this is very likely not the right category. License Accents Resting red diff --git a/app/src/main/res/xml/sponsorblock_settings.xml b/app/src/main/res/xml/sponsorblock_settings.xml index 395229c7c..8b9e138c8 100644 --- a/app/src/main/res/xml/sponsorblock_settings.xml +++ b/app/src/main/res/xml/sponsorblock_settings.xml @@ -41,6 +41,21 @@ app:title="@string/category_outro" app:summary="@string/category_outro_description" /> + + + + + + From a8f90405a9ebd01d29f19cd524afedd191651a4b Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 Jun 2022 14:40:16 +0200 Subject: [PATCH 8/9] share dialog crash fixed --- app/src/main/java/com/github/libretube/MainActivity.kt | 6 +++--- .../java/com/github/libretube/util/DescriptionAdapter.kt | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/MainActivity.kt b/app/src/main/java/com/github/libretube/MainActivity.kt index 4e26f1451..db9894118 100644 --- a/app/src/main/java/com/github/libretube/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/MainActivity.kt @@ -207,7 +207,7 @@ class MainActivity : AppCompatActivity() { val bundle = Bundle() bundle.putString("videoId", watch) // for time stamped links - if (data.query?.contains("t=")!!) { + if (data.query != null && data.query?.contains("t=")!!) { val timeStamp = data.query.toString().split("t=")[1] bundle.putLong("timeStamp", timeStamp.toLong()) } @@ -227,7 +227,7 @@ class MainActivity : AppCompatActivity() { var bundle = Bundle() bundle.putString("videoId", watch.replace("v=", "")) // for time stamped links - if (data.query?.contains("t=")!!) { + if (data.query != null && data.query?.contains("t=")!!) { val timeStamp = data.query.toString().split("t=")[1] bundle.putLong("timeStamp", timeStamp.toLong()) } @@ -237,7 +237,7 @@ class MainActivity : AppCompatActivity() { var bundle = Bundle() bundle.putString("videoId", watch) // for time stamped links - if (data.query?.contains("t=")!!) { + if (data.query != null && data.query?.contains("t=")!!) { val timeStamp = data.query.toString().split("t=")[1] bundle.putLong("timeStamp", timeStamp.toLong()) } diff --git a/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt index aab8853d1..bd9de4aea 100644 --- a/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt +++ b/app/src/main/java/com/github/libretube/util/DescriptionAdapter.kt @@ -36,6 +36,7 @@ class DescriptionAdapter( lateinit var bitmap: Bitmap val thread = Thread { try { + // try to parse the thumbnailUrl to a Bitmap val inputStream = URL(thumbnailUrl).openStream() bitmap = BitmapFactory.decodeStream(inputStream) } catch (ex: java.lang.Exception) { @@ -44,6 +45,7 @@ class DescriptionAdapter( } thread.start() thread.join() + // return bitmap if initialized return try { bitmap } catch (e: Exception) { From e9af0fb5bb51a224edf31435084e96ebed066b61 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 Jun 2022 15:09:47 +0200 Subject: [PATCH 9/9] bump kotlin gradle plugin --- .../libretube/fragments/PlayerFragment.kt | 130 +++++++++--------- .../libretube/preferences/AboutFragment.kt | 32 +++-- build.gradle | 2 +- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index cbf71ed01..28d552abb 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -3,7 +3,6 @@ package com.github.libretube.fragments import android.annotation.SuppressLint import android.app.NotificationManager import android.content.Context -import android.content.DialogInterface import android.content.Intent import android.content.pm.ActivityInfo import android.graphics.Rect @@ -101,7 +100,7 @@ class PlayerFragment : Fragment() { private var whichQuality = 0 private var isZoomed: Boolean = false - var isSubscribed: Boolean = false + private var isSubscribed: Boolean = false private lateinit var relatedRecView: RecyclerView private lateinit var commentsRecView: RecyclerView @@ -491,7 +490,7 @@ class PlayerFragment : Fragment() { view.findViewById(R.id.player_description).text = response.description // Listener for play and pause icon change - exoPlayer.addListener(object : com.google.android.exoplayer2.Player.Listener { + exoPlayer.addListener(object : Player.Listener { override fun onIsPlayingChanged(isPlaying: Boolean) { if (isPlaying && SponsorBlockSettings.sponsorBlockEnabled) { exoPlayerView.postDelayed( @@ -500,7 +499,7 @@ class PlayerFragment : Fragment() { ) } } - + @Deprecated(message = "Deprecated", level = DeprecationLevel.HIDDEN) override fun onPlayerStateChanged( playWhenReady: Boolean, playbackState: Int @@ -541,7 +540,7 @@ class PlayerFragment : Fragment() { relDownloadVideo.setOnClickListener { if (!IS_DOWNLOAD_RUNNING) { val newFragment = DownloadDialog() - var bundle = Bundle() + val bundle = Bundle() bundle.putString("video_id", videoId) bundle.putParcelable("streams", response) newFragment.arguments = bundle @@ -609,7 +608,7 @@ class PlayerFragment : Fragment() { isSubscribed(subButton, channelId!!) view.findViewById(R.id.save).setOnClickListener { val newFragment = AddtoPlaylistDialog() - var bundle = Bundle() + val bundle = Bundle() bundle.putString("videoId", videoId) newFragment.arguments = bundle newFragment.show(childFragmentManager, "AddToPlaylist") @@ -650,7 +649,7 @@ class PlayerFragment : Fragment() { val name = vid.quality + " " + vid.format videosNameArray += name } - var subtitle = mutableListOf() + val subtitle = mutableListOf() if (response.subtitles!!.isNotEmpty()) { subtitle.add( SubtitleConfiguration.Builder(response.subtitles[0].url!!.toUri()) @@ -760,70 +759,69 @@ class PlayerFragment : Fragment() { val builder: MaterialAlertDialogBuilder? = activity?.let { MaterialAlertDialogBuilder(it) } - var lastPosition = exoPlayer.currentPosition + val lastPosition = exoPlayer.currentPosition builder!!.setTitle(R.string.choose_quality_dialog) .setItems( - videosNameArray, - DialogInterface.OnClickListener { _, which -> - whichQuality = which - if (response.subtitles.isNotEmpty()) { - var subtitle = - mutableListOf() - subtitle.add( - SubtitleConfiguration.Builder( - response.subtitles[0].url!!.toUri() - ) - .setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required). - .setLanguage(response.subtitles[0].code) // The subtitle language (optional). - .build() + videosNameArray + ) { _, which -> + whichQuality = which + if (response.subtitles.isNotEmpty()) { + val subtitle = + mutableListOf() + subtitle.add( + SubtitleConfiguration.Builder( + response.subtitles[0].url!!.toUri() ) - } - if (which == 0) { - val mediaItem: MediaItem = MediaItem.Builder() - .setUri(response.hls) - .setSubtitleConfigurations(subtitle) + .setMimeType(response.subtitles[0].mimeType!!) // The correct MIME type (required). + .setLanguage(response.subtitles[0].code) // The subtitle language (optional). .build() - exoPlayer.setMediaItem(mediaItem) - } else { - val dataSourceFactory: DataSource.Factory = - DefaultHttpDataSource.Factory() - val videoItem: MediaItem = MediaItem.Builder() - .setUri(response.videoStreams[which - 1].url) - .setSubtitleConfigurations(subtitle) - .build() - val videoSource: MediaSource = - DefaultMediaSourceFactory(dataSourceFactory) - .createMediaSource(videoItem) - var audioSource: MediaSource = - DefaultMediaSourceFactory(dataSourceFactory) - .createMediaSource( - fromUri(response.audioStreams!![0].url!!) - ) - if (response.videoStreams[which - 1].quality == "720p" || - response.videoStreams[which - 1].quality == "1080p" || - response.videoStreams[which - 1].quality == "480p" - ) { - audioSource = - ProgressiveMediaSource.Factory(dataSourceFactory) - .createMediaSource( - fromUri( - response.audioStreams[ - getMostBitRate( - response.audioStreams - ) - ].url!! - ) - ) - } - val mergeSource: MediaSource = - MergingMediaSource(videoSource, audioSource) - exoPlayer.setMediaSource(mergeSource) - } - exoPlayer.seekTo(lastPosition) - view.findViewById(R.id.quality_text).text = - videosNameArray[which] + ) } - ) + if (which == 0) { + val mediaItem: MediaItem = MediaItem.Builder() + .setUri(response.hls) + .setSubtitleConfigurations(subtitle) + .build() + exoPlayer.setMediaItem(mediaItem) + } else { + val dataSourceFactory: DataSource.Factory = + DefaultHttpDataSource.Factory() + val videoItem: MediaItem = MediaItem.Builder() + .setUri(response.videoStreams[which - 1].url) + .setSubtitleConfigurations(subtitle) + .build() + val videoSource: MediaSource = + DefaultMediaSourceFactory(dataSourceFactory) + .createMediaSource(videoItem) + var audioSource: MediaSource = + DefaultMediaSourceFactory(dataSourceFactory) + .createMediaSource( + fromUri(response.audioStreams!![0].url!!) + ) + if (response.videoStreams[which - 1].quality == "720p" || + response.videoStreams[which - 1].quality == "1080p" || + response.videoStreams[which - 1].quality == "480p" + ) { + audioSource = + ProgressiveMediaSource.Factory(dataSourceFactory) + .createMediaSource( + fromUri( + response.audioStreams[ + getMostBitRate( + response.audioStreams + ) + ].url!! + ) + ) + } + val mergeSource: MediaSource = + MergingMediaSource(videoSource, audioSource) + exoPlayer.setMediaSource(mergeSource) + } + exoPlayer.seekTo(lastPosition) + view.findViewById(R.id.quality_text).text = + videosNameArray[which] + } val dialog = builder.create() dialog.show() } diff --git a/app/src/main/java/com/github/libretube/preferences/AboutFragment.kt b/app/src/main/java/com/github/libretube/preferences/AboutFragment.kt index d7de5f47d..851c6a12a 100644 --- a/app/src/main/java/com/github/libretube/preferences/AboutFragment.kt +++ b/app/src/main/java/com/github/libretube/preferences/AboutFragment.kt @@ -29,40 +29,42 @@ class AboutFragment : Fragment() { val topBarText = activity?.findViewById(R.id.topBar_textView) topBarText?.text = getString(R.string.about) - val appVersion = view?.findViewById(R.id.app_version) + val appVersion = view.findViewById(R.id.app_version) appVersion.text = BuildConfig.VERSION_NAME - val website = view?.findViewById(R.id.website) - website?.setOnClickListener { + val website = view.findViewById(R.id.website) + website.setOnClickListener { openLinkFromHref("https://libre-tube.github.io/") } - val authors = view?.findViewById(R.id.authors) - authors?.setOnClickListener { + val authors = view.findViewById(R.id.authors) + authors.setOnClickListener { openLinkFromHref("https://github.com/libre-tube/LibreTube/graphs/contributors") } - val donate = view?.findViewById(R.id.donate) - donate?.setOnClickListener { + val donate = view.findViewById(R.id.donate) + donate.setOnClickListener { openLinkFromHref("https://libre-tube.github.io/#donate") } - val contributing = view?.findViewById(R.id.contributing) - contributing?.setOnClickListener { + val contributing = view.findViewById(R.id.contributing) + contributing.setOnClickListener { openLinkFromHref("https://github.com/libre-tube/LibreTube") } val license = view.findViewById(R.id.license) - license?.setOnClickListener { - val licenseString = view?.context?.assets!! + license.setOnClickListener { + val licenseString = view.context.assets .open("gpl3.html").bufferedReader().use { it.readText() } - val licenseHtml = if (Build.VERSION.SDK_INT >= 24) Html.fromHtml(licenseString, 1) - else Html.fromHtml(licenseString) + val licenseHtml = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Html.fromHtml(licenseString, 1) + } else { + Html.fromHtml(licenseString) + } - MaterialAlertDialogBuilder(view?.context!!) + MaterialAlertDialogBuilder(view.context!!) .setPositiveButton(getString(R.string.okay)) { _, _ -> } .setMessage(licenseHtml) .create() .show() - true } } diff --git a/build.gradle b/build.gradle index 738ae3345..0a229bb5e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:7.2.1' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files