Merge branch 'master' into weblate-libretube-libretube

This commit is contained in:
Bnyro 2022-09-18 11:10:19 +02:00 committed by GitHub
commit 1d0f7f7f07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 126 additions and 50 deletions

View File

@ -9,7 +9,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:name=".MyApp" android:name=".LibreTubeApp"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"

View File

@ -1,12 +1,10 @@
package com.github.libretube package com.github.libretube
import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
import android.os.StrictMode import android.os.StrictMode
import android.os.StrictMode.VmPolicy import android.os.StrictMode.VmPolicy
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationManagerCompat
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
import com.github.libretube.api.CronetHelper import com.github.libretube.api.CronetHelper
import com.github.libretube.api.RetrofitInstance import com.github.libretube.api.RetrofitInstance
@ -19,12 +17,12 @@ import com.github.libretube.util.ImageHelper
import com.github.libretube.util.NotificationHelper import com.github.libretube.util.NotificationHelper
import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.PreferenceHelper
class MyApp : Application() { class LibreTubeApp : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
/** /**
* Initialize the needed [NotificationChannel]s for DownloadService and BackgroundMode * Initialize the needed notification channels for DownloadService and BackgroundMode
*/ */
initializeNotificationChannels() initializeNotificationChannels()
@ -67,47 +65,38 @@ class MyApp : Application() {
} }
/** /**
* Initializes the required [NotificationChannel]s for the app. * Initializes the required notification channels for the app.
*/ */
@SuppressLint("InlinedApi")
private fun initializeNotificationChannels() { private fun initializeNotificationChannels() {
createNotificationChannel( val downloadChannel = NotificationChannelCompat.Builder(
DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID,
"Download Service", NotificationManagerCompat.IMPORTANCE_NONE
"Shows a notification when downloading media.",
NotificationManager.IMPORTANCE_NONE
) )
createNotificationChannel( .setName(getString(R.string.download_channel_name))
.setDescription(getString(R.string.download_channel_description))
.build()
val backgroundChannel = NotificationChannelCompat.Builder(
BACKGROUND_CHANNEL_ID, BACKGROUND_CHANNEL_ID,
"Background Mode", NotificationManagerCompat.IMPORTANCE_LOW
"Shows a notification with buttons to control the audio player",
NotificationManager.IMPORTANCE_LOW
) )
createNotificationChannel( .setName(getString(R.string.background_channel_name))
.setDescription(getString(R.string.background_channel_description))
.build()
val pushChannel = NotificationChannelCompat.Builder(
PUSH_CHANNEL_ID, PUSH_CHANNEL_ID,
"Notification Worker", NotificationManagerCompat.IMPORTANCE_DEFAULT
"Shows a notification when new streams are available.",
NotificationManager.IMPORTANCE_DEFAULT
) )
} .setName(getString(R.string.push_channel_name))
.setDescription(getString(R.string.push_channel_description))
.build()
/** val notificationManager = NotificationManagerCompat.from(this)
* Creates a [NotificationChannel] notificationManager.createNotificationChannelsCompat(
*/ listOf(
private fun createNotificationChannel( downloadChannel,
id: String, backgroundChannel,
name: String, pushChannel
descriptionText: String, )
importance: Int )
) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(id, name, importance)
channel.description = descriptionText
// Register the channel in the system
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
} }
} }

View File

@ -165,8 +165,6 @@ class MainActivity : BaseActivity() {
// new way of handling back presses // new way of handling back presses
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
navController.popBackStack(R.id.searchFragment, false)
if (binding.mainMotionLayout.progress == 0F) { if (binding.mainMotionLayout.progress == 0F) {
try { try {
minimizePlayer() minimizePlayer()
@ -289,6 +287,13 @@ class MainActivity : BaseActivity() {
} }
override fun onQueryTextChange(newText: String?): Boolean { override fun onQueryTextChange(newText: String?): Boolean {
// prevent malicious navigation when the search view is getting collapsed
if (navController.currentDestination?.id == R.id.searchResultFragment &&
(newText == null || newText == "")
) {
return false
}
if (navController.currentDestination?.id != R.id.searchFragment) { if (navController.currentDestination?.id != R.id.searchFragment) {
val bundle = Bundle() val bundle = Bundle()
bundle.putString("query", newText) bundle.putString("query", newText)
@ -296,6 +301,7 @@ class MainActivity : BaseActivity() {
} else { } else {
searchViewModel.setQuery(newText) searchViewModel.setQuery(newText)
} }
return true return true
} }
}) })

View File

@ -75,6 +75,7 @@ object PreferenceKeys {
const val SKIP_BUTTONS = "skip_buttons" const val SKIP_BUTTONS = "skip_buttons"
const val PICTURE_IN_PICTURE = "picture_in_picture" const val PICTURE_IN_PICTURE = "picture_in_picture"
const val PLAYER_RESIZE_MODE = "player_resize_mode" const val PLAYER_RESIZE_MODE = "player_resize_mode"
const val SB_SKIP_MANUALLY = "sb_skip_manually_key"
/** /**
* Background mode * Background mode

View File

@ -169,6 +169,7 @@ class PlayerFragment : BaseFragment() {
private var sponsorBlockNotifications = true private var sponsorBlockNotifications = true
private var skipButtonsEnabled = false private var skipButtonsEnabled = false
private var pipEnabled = true private var pipEnabled = true
private var skipSegmentsManually = false
/** /**
* for autoplay * for autoplay
@ -336,6 +337,11 @@ class PlayerFragment : BaseFragment() {
PreferenceKeys.PICTURE_IN_PICTURE, PreferenceKeys.PICTURE_IN_PICTURE,
true true
) )
skipSegmentsManually = PreferenceHelper.getBoolean(
PreferenceKeys.SB_SKIP_MANUALLY,
false
)
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@ -709,21 +715,39 @@ class PlayerFragment : BaseFragment() {
Handler(Looper.getMainLooper()).postDelayed(this::checkForSegments, 100) Handler(Looper.getMainLooper()).postDelayed(this::checkForSegments, 100)
if (!::segmentData.isInitialized || segmentData.segments.isEmpty()) { if (!::segmentData.isInitialized || segmentData.segments.isEmpty()) return
return
}
val currentPosition = exoPlayer.currentPosition
segmentData.segments.forEach { segment: Segment -> segmentData.segments.forEach { segment: Segment ->
val segmentStart = (segment.segment!![0] * 1000f).toLong() val segmentStart = (segment.segment!![0] * 1000f).toLong()
val segmentEnd = (segment.segment[1] * 1000f).toLong() val segmentEnd = (segment.segment[1] * 1000f).toLong()
val currentPosition = exoPlayer.currentPosition
// show the button to manually skip the segment
if (currentPosition in segmentStart until segmentEnd) { if (currentPosition in segmentStart until segmentEnd) {
if (sponsorBlockNotifications) { if (skipSegmentsManually) {
Toast.makeText(context, R.string.segment_skipped, Toast.LENGTH_SHORT).show() binding.sbSkipBtn.visibility = View.VISIBLE
binding.sbSkipBtn.setOnClickListener {
exoPlayer.seekTo(segmentEnd)
}
return
} }
if (sponsorBlockNotifications) {
Toast
.makeText(
context,
R.string.segment_skipped,
Toast.LENGTH_SHORT
).show()
}
// skip the segment automatically
exoPlayer.seekTo(segmentEnd) exoPlayer.seekTo(segmentEnd)
return
} }
} }
if (skipSegmentsManually) binding.sbSkipBtn.visibility = View.GONE
} }
private fun playVideo() { private fun playVideo() {
@ -743,6 +767,9 @@ class PlayerFragment : BaseFragment() {
} }
runOnUiThread { runOnUiThread {
// hide the button to skip SponsorBlock segments manually
binding.sbSkipBtn.visibility = View.GONE
// set media sources for the player // set media sources for the player
setResolutionAndSubtitles() setResolutionAndSubtitles()
prepareExoPlayerView() prepareExoPlayerView()

View File

@ -378,8 +378,44 @@
android:layout_gravity="center" android:layout_gravity="center"
android:gravity="center" /> android:gravity="center" />
</com.github.libretube.views.CustomExoPlayerView> <com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="-10dp"
android:layout_marginBottom="60dp"
android:paddingEnd="10dp"
app:strokeWidth="1dp"
app:cardBackgroundColor="#88000000"
tools:ignore="RtlSymmetry">
<LinearLayout
android:id="@+id/sb_skip_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/skip_segment"
android:textColor="@android:color/white"
android:textSize="18sp" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_marginHorizontal="10dp"
android:src="@drawable/ic_next"
app:tint="@android:color/white" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</com.github.libretube.views.CustomExoPlayerView>
<ImageView <ImageView
android:id="@+id/close_imageView" android:id="@+id/close_imageView"

View File

@ -321,4 +321,15 @@
<string name="mobile_data">Mobile data</string> <string name="mobile_data">Mobile data</string>
<string name="new_videos_badge">Indicator for new videos</string> <string name="new_videos_badge">Indicator for new videos</string>
<string name="new_videos_badge_summary">Show a badge with the amount of new videos if there are some.</string> <string name="new_videos_badge_summary">Show a badge with the amount of new videos if there are some.</string>
</resources> <string name="skip_segment">Skip segment</string>
<string name="sb_skip_manual">Skip manually</string>
<string name="sb_skip_manual_summary">Don\'t skip segments automatically, always prompt before.</string>
<!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string>
<string name="download_channel_description">Shows a notification when downloading media.</string>
<string name="background_channel_name">Background Mode</string>
<string name="background_channel_description">Shows a notification with buttons to control the audio player.</string>
<string name="push_channel_name">Notification Worker</string>
<string name="push_channel_description">Shows a notification when new streams are available.</string>
</resources>

View File

@ -16,6 +16,12 @@
app:key="sb_notifications_key" app:key="sb_notifications_key"
app:title="@string/sponsorblock_notifications" /> app:title="@string/sponsorblock_notifications" />
<SwitchPreferenceCompat
android:summary="@string/sb_skip_manual_summary"
app:defaultValue="false"
app:key="sb_skip_manually_key"
app:title="@string/sb_skip_manual" />
<PreferenceCategory app:title="@string/category_segments"> <PreferenceCategory app:title="@string/category_segments">
<SwitchPreferenceCompat <SwitchPreferenceCompat