mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 16:30:31 +05:30
Custom SponsorBlock segment colors option (#4055)
Co-authored-by: Bnyro <bnyro@tutanota.com>
This commit is contained in:
parent
332978a100
commit
2e56db0219
@ -2,6 +2,7 @@ package com.github.libretube.enums
|
||||
|
||||
enum class SbSkipOptions {
|
||||
OFF,
|
||||
VISIBLE,
|
||||
MANUAL,
|
||||
AUTOMATIC
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ object PlayerHelper {
|
||||
}
|
||||
}
|
||||
seekTo(segmentEnd)
|
||||
} else {
|
||||
} else if (sponsorBlockConfig[segment.category] == SbSkipOptions.MANUAL) {
|
||||
return segmentEnd
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,130 @@
|
||||
package com.github.libretube.ui.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.databinding.DialogColorPickerBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
class ColorPickerDialog(
|
||||
private val context: Context,
|
||||
private val initialColor: Int,
|
||||
private val onColorSelectedListener: OnColorSelectedListener
|
||||
) : DialogFragment(), SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
private var _binding: DialogColorPickerBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
_binding = DialogColorPickerBinding.inflate(layoutInflater)
|
||||
|
||||
// Set initial color
|
||||
setColor(initialColor)
|
||||
|
||||
binding.alphaSeekBar.setOnSeekBarChangeListener(this)
|
||||
binding.redSeekBar.setOnSeekBarChangeListener(this)
|
||||
binding.greenSeekBar.setOnSeekBarChangeListener(this)
|
||||
binding.blueSeekBar.setOnSeekBarChangeListener(this)
|
||||
|
||||
// Add listener to text input
|
||||
binding.colorHexInput.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int,
|
||||
after: Int) = Unit
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int,
|
||||
count: Int) = Unit
|
||||
|
||||
var isValid = true
|
||||
var oldHex = ""
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
// Update color when text input changes
|
||||
val hexColor = s.toString()
|
||||
if (hexColor.length == 9 && oldHex != hexColor) {
|
||||
isValid = try {
|
||||
oldHex = hexColor
|
||||
val color = Color.parseColor(hexColor)
|
||||
setColor(color, true)
|
||||
true
|
||||
} catch (e: IllegalArgumentException) {
|
||||
if (isValid) {
|
||||
showInvalidColorMessage()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(R.string.okay) { _, _ ->
|
||||
onColorSelectedListener.onColorSelected(getColor())
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
// Update color preview when SeekBar progress changes
|
||||
setColorPreview(getColor())
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) = Unit
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
val newColorString = colorToString(getColor())
|
||||
|
||||
if (newColorString != binding.colorHexInput.text.toString()) {
|
||||
binding.colorHexInput.setText(newColorString)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showInvalidColorMessage() {
|
||||
Toast.makeText(context, R.string.invalid_color, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// Get the color from the SeekBar progress values
|
||||
private fun getColor() = Color.argb(binding.alphaSeekBar.progress, binding.redSeekBar.progress,
|
||||
binding.greenSeekBar.progress, binding.blueSeekBar.progress)
|
||||
|
||||
private fun setColor(color: Int, textUpdate: Boolean = false) {
|
||||
// Set the SeekBar progress values based on the color
|
||||
binding.alphaSeekBar.progress = Color.alpha(color)
|
||||
binding.redSeekBar.progress = Color.red(color)
|
||||
binding.greenSeekBar.progress = Color.green(color)
|
||||
binding.blueSeekBar.progress = Color.blue(color)
|
||||
|
||||
// Set the hex color input value
|
||||
if (!textUpdate) {
|
||||
binding.colorHexInput.setText(colorToString(color))
|
||||
}
|
||||
binding.colorPreview.setBackgroundColor(color)
|
||||
}
|
||||
|
||||
private fun setColorPreview(color: Int) {
|
||||
// Set the color preview
|
||||
binding.colorPreview.setBackgroundColor(color)
|
||||
}
|
||||
|
||||
private fun colorToString(color: Int): String {
|
||||
return String.format("#%08X", color)
|
||||
}
|
||||
|
||||
fun interface OnColorSelectedListener {
|
||||
fun onColorSelected(color: Int)
|
||||
}
|
||||
}
|
@ -672,7 +672,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun playVideo() {
|
||||
|
@ -0,0 +1,74 @@
|
||||
package com.github.libretube.ui.views
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.ui.dialogs.ColorPickerDialog
|
||||
|
||||
class ColorPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
|
||||
private lateinit var circleView: View
|
||||
private var currentColor: Int? = null
|
||||
|
||||
init {
|
||||
layoutResource = R.layout.color_preference
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
|
||||
holder.itemView.findViewById<TextView>(android.R.id.title)?.text = title
|
||||
circleView = holder.itemView.findViewById(R.id.circle)
|
||||
updateColorView()
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
showColorPickerDialog()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setColor(color: Int) {
|
||||
currentColor = color
|
||||
persistInt(color)
|
||||
updateColorView()
|
||||
}
|
||||
|
||||
|
||||
override fun onGetDefaultValue(ta: TypedArray, index: Int): Any {
|
||||
return Color.parseColor(ta.getString(index))
|
||||
}
|
||||
|
||||
override fun onSetInitialValue(defaultValue: Any?) {
|
||||
val color = if (defaultValue is Int) {
|
||||
getPersistedInt(defaultValue)
|
||||
} else {
|
||||
getPersistedInt(Color.WHITE)
|
||||
}
|
||||
currentColor = color
|
||||
persistInt(color)
|
||||
}
|
||||
|
||||
private fun updateColorView() {
|
||||
(if (currentColor is Int) currentColor else Color.WHITE)?.let {
|
||||
circleView.setBackgroundColor(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showColorPickerDialog() {
|
||||
(if (currentColor is Int) currentColor else Color.BLACK)?.let {
|
||||
val dialog = ColorPickerDialog(context, it) { color -> setColor(color) }
|
||||
dialog.show((context as AppCompatActivity).supportFragmentManager, this::class.java.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTitle(): CharSequence? {
|
||||
return "${super.getTitle()}:"
|
||||
}
|
||||
|
||||
}
|
@ -45,6 +45,7 @@ class MarkableTimeBar(
|
||||
val horizontalOffset = (parent as View).marginLeft
|
||||
length = canvas.width - horizontalOffset * 2
|
||||
val marginY = canvas.height / 2 - progressBarHeight / 2
|
||||
val themeColor = ThemeHelper.getThemeColor(context, R.attr.colorOnSecondary,)
|
||||
|
||||
segments.forEach {
|
||||
canvas.drawRect(
|
||||
@ -55,10 +56,11 @@ class MarkableTimeBar(
|
||||
canvas.height - marginY,
|
||||
),
|
||||
Paint().apply {
|
||||
color = ThemeHelper.getThemeColor(
|
||||
context,
|
||||
R.attr.colorOnSecondary,
|
||||
)
|
||||
color = if (PreferenceHelper.getBoolean("sb_enable_custom_colors", false)) {
|
||||
PreferenceHelper.getInt(it.category + "_color", themeColor)
|
||||
} else {
|
||||
themeColor
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
6
app/src/main/res/drawable/circle.xml
Normal file
6
app/src/main/res/drawable/circle.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="#000" />
|
||||
|
||||
</shape>
|
36
app/src/main/res/layout/color_preference.xml
Normal file
36
app/src/main/res/layout/color_preference.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
style="?android:attr/preferenceStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:fadingEdge="horizontal"
|
||||
android:singleLine="true"
|
||||
android:text="Title"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<View
|
||||
android:id="@+id/circle"
|
||||
android:layout_width="20sp"
|
||||
android:layout_height="20sp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="@drawable/circle"
|
||||
android:layout_marginStart="16dp"/>
|
||||
|
||||
</LinearLayout>
|
92
app/src/main/res/layout/dialog_color_picker.xml
Normal file
92
app/src/main/res/layout/dialog_color_picker.xml
Normal file
@ -0,0 +1,92 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingTop="30dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="10dp"
|
||||
app:cardCornerRadius="10dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/colorPreview"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:background="#000000" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="R"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/redSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:max="255"
|
||||
android:progress="0" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="G"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/greenSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:max="255"
|
||||
android:progress="0" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="B"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/blueSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:max="255"
|
||||
android:progress="0" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="A"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/alphaSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="5dp"
|
||||
android:max="255"
|
||||
android:progress="255" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/colorHexInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="5dp"
|
||||
android:hint="#00000000"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
@ -424,12 +424,14 @@
|
||||
|
||||
<string-array name="sb_skip_options">
|
||||
<item>@string/off</item>
|
||||
<item>@string/visible</item>
|
||||
<item>@string/manual</item>
|
||||
<item>@string/automatic</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="sb_skip_options_values">
|
||||
<item>off</item>
|
||||
<item>visible</item>
|
||||
<item>manual</item>
|
||||
<item>automatic</item>
|
||||
</string-array>
|
||||
|
@ -303,6 +303,11 @@
|
||||
<string name="queue">Queue</string>
|
||||
<string name="sb_markers">Markers</string>
|
||||
<string name="sb_markers_summary">Mark the segments on the time bar.</string>
|
||||
<string name="sb_color_enable">Toggles custom color segments for sponsor block segments</string>
|
||||
<string name="sb_custom_colors">Custom segment colors</string>
|
||||
<string name="color">Color</string>
|
||||
<string name="invalid_color">Invalid color value entered!</string>
|
||||
<string name="enter_hex_value">Enter Color Hex Value</string>
|
||||
<string name="livestreams">Livestreams</string>
|
||||
<string name="alternative_videos_layout">Alternative videos layout</string>
|
||||
<string name="defaultIconLight">Default light</string>
|
||||
@ -419,9 +424,10 @@
|
||||
<string name="change_playlist_description">Change playlist description</string>
|
||||
<string name="playlist_description">Playlist description</string>
|
||||
<string name="emptyPlaylistDescription">The playlist description can\'t be empty</string>
|
||||
<string name="off">Off</string>
|
||||
<string name="manual">Manual</string>
|
||||
<string name="automatic">Automatic</string>
|
||||
<string name="off">Disable</string>
|
||||
<string name="visible">Show in seek bar</string>
|
||||
<string name="manual">Manual skip</string>
|
||||
<string name="automatic">Auto skip</string>
|
||||
|
||||
<!-- Backup & Restore Settings -->
|
||||
<string name="import_subscriptions_from">Import subscriptions from</string>
|
||||
|
@ -24,6 +24,12 @@
|
||||
app:key="sb_show_markers"
|
||||
app:title="@string/sb_markers" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:summary="@string/sb_color_enable"
|
||||
app:defaultValue="false"
|
||||
android:dependency="sb_enabled_key"
|
||||
app:key="sb_enable_custom_colors"
|
||||
app:title="@string/sb_custom_colors" />
|
||||
|
||||
<PreferenceCategory app:title="@string/category_segments">
|
||||
|
||||
@ -33,6 +39,10 @@
|
||||
app:title="@string/category_sponsor"
|
||||
app:defaultValue="automatic"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="sponsor_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#00d400" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="selfpromo_category"
|
||||
@ -40,42 +50,77 @@
|
||||
app:title="@string/category_selfpromo"
|
||||
app:defaultValue="automatic"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="selfpromo_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#ffff00" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="interaction_category"
|
||||
app:summary="@string/category_interaction_description"
|
||||
app:title="@string/category_interaction"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="interaction_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#cc00ff" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="intro_category"
|
||||
app:summary="@string/category_intro_description"
|
||||
app:title="@string/category_intro"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="intro_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#00ffff" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="outro_category"
|
||||
app:summary="@string/category_outro_description"
|
||||
app:title="@string/category_outro"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="outro_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#0202ED" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="filler_category"
|
||||
app:summary="@string/category_filler_description"
|
||||
app:title="@string/category_filler"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="filler_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#7300ff" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="music_offtopic_category"
|
||||
app:summary="@string/category_music_offtopic_description"
|
||||
app:title="@string/category_music_offtopic"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="music_offtopic_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#ff9900" />
|
||||
|
||||
<com.github.libretube.ui.views.SbSpinnerPreference
|
||||
app:key="preview_category"
|
||||
app:summary="@string/category_preview_description"
|
||||
app:title="@string/category_preview"
|
||||
app:defaultValue="off"/>
|
||||
|
||||
<com.github.libretube.ui.views.ColorPreference
|
||||
app:key="preview_color"
|
||||
app:title="@string/color"
|
||||
app:defaultValue="#008fd6" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
Loading…
x
Reference in New Issue
Block a user