From 6e8ffbade9e03658f725622631e44dabf2995861 Mon Sep 17 00:00:00 2001
From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Date: Wed, 19 Mar 2025 18:02:06 +0100
Subject: [PATCH] feat(YouTube - SponsorBlock): Add opacity setting to category
segment colors (#4582)
---
.../ResettableEditTextPreference.java | 31 ++-
.../extension/youtube/settings/Settings.java | 10 +
...eturnYouTubeDislikePreferenceFragment.java | 3 +
.../SponsorBlockPreferenceFragment.java | 25 ++-
.../sponsorblock/SponsorBlockSettings.java | 2 +-
.../sponsorblock/SponsorBlockUtils.java | 91 ++++----
.../sponsorblock/objects/SegmentCategory.java | 171 +++++++++------
.../SegmentCategoryListPreference.java | 204 ++++++++++++++----
.../sponsorblock/objects/SponsorSegment.java | 9 +-
.../resources/addresources/values/strings.xml | 3 +
10 files changed, 382 insertions(+), 167 deletions(-)
diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ResettableEditTextPreference.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ResettableEditTextPreference.java
index 3e9a96961..98f4a715f 100644
--- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ResettableEditTextPreference.java
+++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ResettableEditTextPreference.java
@@ -1,5 +1,7 @@
package app.revanced.extension.shared.settings.preference;
+import static app.revanced.extension.shared.StringRef.str;
+
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
@@ -8,17 +10,23 @@ import android.util.AttributeSet;
import android.widget.Button;
import android.widget.EditText;
-import app.revanced.extension.shared.Utils;
-import app.revanced.extension.shared.settings.Setting;
-import app.revanced.extension.shared.Logger;
+import androidx.annotation.Nullable;
import java.util.Objects;
-import static app.revanced.extension.shared.StringRef.str;
+import app.revanced.extension.shared.Logger;
+import app.revanced.extension.shared.Utils;
+import app.revanced.extension.shared.settings.Setting;
@SuppressWarnings({"unused", "deprecation"})
public class ResettableEditTextPreference extends EditTextPreference {
+ /**
+ * Setting to reset.
+ */
+ @Nullable
+ private Setting> setting;
+
public ResettableEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -32,12 +40,22 @@ public class ResettableEditTextPreference extends EditTextPreference {
super(context);
}
+ public void setSetting(@Nullable Setting> setting) {
+ this.setting = setting;
+ }
+
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
Utils.setEditTextDialogTheme(builder);
- Setting> setting = Setting.getSettingFromPath(getKey());
+ if (setting == null) {
+ String key = getKey();
+ if (key != null) {
+ setting = Setting.getSettingFromPath(key);
+ }
+ }
+
if (setting != null) {
builder.setNeutralButton(str("revanced_settings_reset"), null);
}
@@ -54,8 +72,7 @@ public class ResettableEditTextPreference extends EditTextPreference {
}
button.setOnClickListener(v -> {
try {
- Setting> setting = Objects.requireNonNull(Setting.getSettingFromPath(getKey()));
- String defaultStringValue = setting.defaultValue.toString();
+ String defaultStringValue = Objects.requireNonNull(setting).defaultValue.toString();
EditText editText = getEditText();
editText.setText(defaultStringValue);
editText.setSelection(defaultStringValue.length()); // move cursor to end of text
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
index 954d75bb6..c0c20842b 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java
@@ -365,24 +365,34 @@ public class Settings extends BaseSettings {
public static final BooleanSetting SB_SEEN_GUIDELINES = new BooleanSetting("sb_seen_guidelines", FALSE, false, false);
public static final StringSetting SB_CATEGORY_SPONSOR = new StringSetting("sb_sponsor", SKIP_AUTOMATICALLY_ONCE.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_SPONSOR_COLOR = new StringSetting("sb_sponsor_color", "#00D400");
+ public static final FloatSetting SB_CATEGORY_SPONSOR_OPACITY = new FloatSetting("sb_sponsor_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_SELF_PROMO = new StringSetting("sb_selfpromo", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_SELF_PROMO_COLOR = new StringSetting("sb_selfpromo_color", "#FFFF00");
+ public static final FloatSetting SB_CATEGORY_SELF_PROMO_OPACITY = new FloatSetting("sb_selfpromo_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_INTERACTION = new StringSetting("sb_interaction", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_INTERACTION_COLOR = new StringSetting("sb_interaction_color", "#CC00FF");
+ public static final FloatSetting SB_CATEGORY_INTERACTION_OPACITY = new FloatSetting("sb_interaction_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_HIGHLIGHT = new StringSetting("sb_highlight", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_HIGHLIGHT_COLOR = new StringSetting("sb_highlight_color", "#FF1684");
+ public static final FloatSetting SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_INTRO = new StringSetting("sb_intro", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_INTRO_COLOR = new StringSetting("sb_intro_color", "#00FFFF");
+ public static final FloatSetting SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_OUTRO = new StringSetting("sb_outro", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_OUTRO_COLOR = new StringSetting("sb_outro_color", "#0202ED");
+ public static final FloatSetting SB_CATEGORY_OUTRO_OPACITY = new FloatSetting("sb_outro_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_PREVIEW = new StringSetting("sb_preview", IGNORE.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_PREVIEW_COLOR = new StringSetting("sb_preview_color", "#008FD6");
+ public static final FloatSetting SB_CATEGORY_PREVIEW_OPACITY = new FloatSetting("sb_preview_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_FILLER = new StringSetting("sb_filler", IGNORE.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_FILLER_COLOR = new StringSetting("sb_filler_color", "#7300FF");
+ public static final FloatSetting SB_CATEGORY_FILLER_OPACITY = new FloatSetting("sb_filler_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_MUSIC_OFFTOPIC = new StringSetting("sb_music_offtopic", MANUAL_SKIP.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_MUSIC_OFFTOPIC_COLOR = new StringSetting("sb_music_offtopic_color", "#FF9900");
+ public static final FloatSetting SB_CATEGORY_MUSIC_OFFTOPIC_OPACITY = new FloatSetting("sb_music_offtopic_opacity", 0.8f);
public static final StringSetting SB_CATEGORY_UNSUBMITTED = new StringSetting("sb_unsubmitted", SKIP_AUTOMATICALLY.reVancedKeyValue);
public static final StringSetting SB_CATEGORY_UNSUBMITTED_COLOR = new StringSetting("sb_unsubmitted_color", "#FFFFFF");
+ public static final FloatSetting SB_CATEGORY_UNSUBMITTED_OPACITY = new FloatSetting("sb_unsubmitted_opacity", 1.0f);
// Deprecated migrations
private static final StringSetting DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING = new StringSetting("uuid", ""); // Delete sometime in 2024
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
index 5e234ec28..7c367f87b 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
@@ -14,6 +14,7 @@ import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import app.revanced.extension.shared.Logger;
+import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.settings.BaseSettings;
import app.revanced.extension.youtube.patches.ReturnYouTubeDislikePatch;
@@ -237,6 +238,8 @@ public class ReturnYouTubeDislikePreferenceFragment extends PreferenceFragment {
"revanced_ryd_statistics_getNumberOfRateLimitRequestsEncountered_non_zero_summary"));
preferenceScreen.addPreference(statisticPreference);
}
+
+ Utils.setPreferenceTitlesToMultiLineIfNeeded(preferenceScreen);
} catch (Exception ex) {
Logger.printException(() -> "onCreate failure", ex);
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SponsorBlockPreferenceFragment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SponsorBlockPreferenceFragment.java
index 18cf149dc..751125274 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SponsorBlockPreferenceFragment.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SponsorBlockPreferenceFragment.java
@@ -17,6 +17,7 @@ import androidx.annotation.Nullable;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.shared.settings.Setting;
+import app.revanced.extension.shared.settings.preference.ResettableEditTextPreference;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
import app.revanced.extension.youtube.sponsorblock.SponsorBlockSettings;
@@ -44,8 +45,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
private SwitchPreference showTimeWithoutSegments;
private SwitchPreference toastOnConnectionError;
- private EditTextPreference newSegmentStep;
- private EditTextPreference minSegmentDuration;
+ private ResettableEditTextPreference newSegmentStep;
+ private ResettableEditTextPreference minSegmentDuration;
private EditTextPreference privateUserId;
private EditTextPreference importExport;
private Preference apiUrl;
@@ -159,6 +160,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
addAboutCategory(context, preferenceScreen);
+ Utils.setPreferenceTitlesToMultiLineIfNeeded(preferenceScreen);
+
updateUI();
} catch (Exception ex) {
Logger.printException(() -> "onCreate failure", ex);
@@ -268,7 +271,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
return true;
});
- newSegmentStep = new EditTextPreference(context);
+ newSegmentStep = new ResettableEditTextPreference(context);
+ newSegmentStep.setSetting(Settings.SB_CREATE_NEW_SEGMENT_STEP);
newSegmentStep.setTitle(str("revanced_sb_general_adjusting"));
newSegmentStep.setSummary(str("revanced_sb_general_adjusting_sum"));
newSegmentStep.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
@@ -326,7 +330,8 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
});
category.addPreference(trackSkips);
- minSegmentDuration = new EditTextPreference(context);
+ minSegmentDuration = new ResettableEditTextPreference(context);
+ minSegmentDuration.setSetting(Settings.SB_SEGMENT_MIN_DURATION);
minSegmentDuration.setTitle(str("revanced_sb_general_min_duration"));
minSegmentDuration.setSummary(str("revanced_sb_general_min_duration_sum"));
minSegmentDuration.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
@@ -345,7 +350,15 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
});
category.addPreference(minSegmentDuration);
- privateUserId = new EditTextPreference(context);
+ privateUserId = new EditTextPreference(context) {
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ Utils.setEditTextDialogTheme(builder);
+
+ builder.setNeutralButton(str("revanced_sb_settings_copy"), (dialog, which) -> {
+ Utils.setClipboard(getEditText().getText().toString());
+ });
+ }
+ };
privateUserId.setTitle(str("revanced_sb_general_uuid"));
privateUserId.setSummary(str("revanced_sb_general_uuid_sum"));
privateUserId.setOnPreferenceChangeListener((preference1, newValue) -> {
@@ -504,7 +517,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment {
if (stats.totalSegmentCountIncludingIgnored > 0) {
// If user has not created any segments, there's no reason to set a username.
- EditTextPreference preference = new EditTextPreference(context);
+ EditTextPreference preference = new ResettableEditTextPreference(context);
statsCategory.addPreference(preference);
String userName = stats.userName;
preference.setTitle(fromHtml(str("revanced_sb_stats_username", userName)));
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockSettings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockSettings.java
index 45739f267..e8d64fb50 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockSettings.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockSettings.java
@@ -136,7 +136,7 @@ public class SponsorBlockSettings {
for (SegmentCategory category : categories) {
JSONObject categoryObject = new JSONObject();
String categoryKey = category.keyValue;
- categoryObject.put("color", category.colorString());
+ categoryObject.put("color", category.getColorString());
barTypesObject.put(categoryKey, categoryObject);
if (category.behaviour != CategoryBehaviour.IGNORE) {
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockUtils.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockUtils.java
index 3fdfe1f9f..5edccbacd 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockUtils.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/SponsorBlockUtils.java
@@ -5,7 +5,12 @@ import static app.revanced.extension.shared.StringRef.str;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.text.Html;
+import android.graphics.Color;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
import android.widget.EditText;
import androidx.annotation.NonNull;
@@ -33,7 +38,7 @@ import app.revanced.extension.youtube.sponsorblock.ui.SponsorBlockViewController
* Not thread safe. All fields/methods must be accessed from the main thread.
*/
public class SponsorBlockUtils {
- private static final String LOCKED_COLOR = "#FFC83D";
+ private static final int LOCKED_COLOR = Color.parseColor("#FFC83D");
private static final String MANUAL_EDIT_TIME_TEXT_HINT = "hh:mm:ss.sss";
private static final Pattern manualEditTimePattern
= Pattern.compile("((\\d{1,2}):)?(\\d{1,2}):(\\d{2})(\\.(\\d{1,3}))?");
@@ -160,32 +165,34 @@ public class SponsorBlockUtils {
SegmentVote[] voteOptions = (segment.category == SegmentCategory.HIGHLIGHT)
? SegmentVote.voteTypesWithoutCategoryChange // highlight segments cannot change category
: SegmentVote.values();
- CharSequence[] items = new CharSequence[voteOptions.length];
+ final int voteOptionsLength = voteOptions.length;
+ final boolean userIsVip = Settings.SB_USER_IS_VIP.get();
+ CharSequence[] items = new CharSequence[voteOptionsLength];
- for (int i = 0; i < voteOptions.length; i++) {
+ for (int i = 0; i < voteOptionsLength; i++) {
SegmentVote voteOption = voteOptions[i];
- String title = voteOption.title.toString();
- if (Settings.SB_USER_IS_VIP.get() && segment.isLocked && voteOption.shouldHighlight) {
- items[i] = Html.fromHtml(String.format("%s", LOCKED_COLOR, title));
- } else {
- items[i] = title;
+ CharSequence title = voteOption.title.toString();
+ if (userIsVip && segment.isLocked && voteOption.highlightIfVipAndVideoIsLocked) {
+ SpannableString coloredTitle = new SpannableString(title);
+ coloredTitle.setSpan(new ForegroundColorSpan(LOCKED_COLOR),
+ 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ title = coloredTitle;
}
+ items[i] = title;
}
- new AlertDialog.Builder(context)
- .setItems(items, (dialog1, which1) -> {
- SegmentVote voteOption = voteOptions[which1];
- switch (voteOption) {
- case UPVOTE:
- case DOWNVOTE:
- SBRequester.voteForSegmentOnBackgroundThread(segment, voteOption);
- break;
- case CATEGORY_CHANGE:
- onNewCategorySelect(segment, context);
- break;
- }
- })
- .show();
+ new AlertDialog.Builder(context).setItems(items, (dialog1, which1) -> {
+ SegmentVote voteOption = voteOptions[which1];
+ switch (voteOption) {
+ case UPVOTE:
+ case DOWNVOTE:
+ SBRequester.voteForSegmentOnBackgroundThread(segment, voteOption);
+ break;
+ case CATEGORY_CHANGE:
+ onNewCategorySelect(segment, context);
+ break;
+ }
+ }).show();
} catch (Exception ex) {
Logger.printException(() -> "segmentVoteClickListener failure", ex);
}
@@ -282,7 +289,6 @@ public class SponsorBlockUtils {
return;
}
-
final int numberOfSegments = segments.length;
CharSequence[] titles = new CharSequence[numberOfSegments];
for (int i = 0; i < numberOfSegments; i++) {
@@ -290,22 +296,33 @@ public class SponsorBlockUtils {
if (segment.category == SegmentCategory.UNSUBMITTED) {
continue;
}
- StringBuilder htmlBuilder = new StringBuilder();
- htmlBuilder.append(String.format("⬤ %s
",
- segment.category.color, segment.category.title));
- htmlBuilder.append(formatSegmentTime(segment.start));
- if (segment.category != SegmentCategory.HIGHLIGHT) {
- htmlBuilder.append(" to ").append(formatSegmentTime(segment.end));
+
+ SpannableStringBuilder spannableBuilder = new SpannableStringBuilder();
+
+ spannableBuilder.append(segment.category.getTitleWithColorDot());
+ spannableBuilder.append('\n');
+
+ String startTime = formatSegmentTime(segment.start);
+ if (segment.category == SegmentCategory.HIGHLIGHT) {
+ spannableBuilder.append(startTime);
+ } else {
+ String toFromString = str("revanced_sb_vote_segment_time_to_from",
+ startTime, formatSegmentTime(segment.end));
+ spannableBuilder.append(toFromString);
}
- htmlBuilder.append("");
- if (i + 1 != numberOfSegments) // prevents trailing new line after last segment
- htmlBuilder.append("
");
- titles[i] = Html.fromHtml(htmlBuilder.toString());
+
+ if (i + 1 != numberOfSegments) {
+ // prevents trailing new line after last segment
+ spannableBuilder.append('\n');
+ }
+
+ spannableBuilder.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
+ 0, spannableBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ titles[i] = spannableBuilder;
}
- new AlertDialog.Builder(context)
- .setItems(titles, segmentVoteClickListener)
- .show();
+ new AlertDialog.Builder(context).setItems(titles, segmentVoteClickListener).show();
} catch (Exception ex) {
Logger.printException(() -> "onVotingClicked failure", ex);
}
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java
index 5be3755ae..ec1b1fca5 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategory.java
@@ -1,13 +1,14 @@
package app.revanced.extension.youtube.sponsorblock.objects;
-import static app.revanced.extension.youtube.settings.Settings.*;
import static app.revanced.extension.shared.StringRef.sf;
+import static app.revanced.extension.youtube.settings.Settings.*;
import android.graphics.Color;
import android.graphics.Paint;
-import android.text.Html;
-import android.text.Spanned;
+import android.text.Spannable;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.style.ForegroundColorSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -15,43 +16,45 @@ import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import app.revanced.extension.shared.Utils;
-import app.revanced.extension.shared.settings.StringSetting;
-import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.StringRef;
+import app.revanced.extension.shared.Utils;
+import app.revanced.extension.shared.settings.FloatSetting;
+import app.revanced.extension.shared.settings.StringSetting;
+import app.revanced.extension.youtube.settings.Settings;
public enum SegmentCategory {
SPONSOR("sponsor", sf("revanced_sb_segments_sponsor"), sf("revanced_sb_segments_sponsor_sum"), sf("revanced_sb_skip_button_sponsor"), sf("revanced_sb_skipped_sponsor"),
- SB_CATEGORY_SPONSOR, SB_CATEGORY_SPONSOR_COLOR),
+ SB_CATEGORY_SPONSOR, SB_CATEGORY_SPONSOR_COLOR, SB_CATEGORY_SPONSOR_OPACITY),
SELF_PROMO("selfpromo", sf("revanced_sb_segments_selfpromo"), sf("revanced_sb_segments_selfpromo_sum"), sf("revanced_sb_skip_button_selfpromo"), sf("revanced_sb_skipped_selfpromo"),
- SB_CATEGORY_SELF_PROMO, SB_CATEGORY_SELF_PROMO_COLOR),
+ SB_CATEGORY_SELF_PROMO, SB_CATEGORY_SELF_PROMO_COLOR, SB_CATEGORY_SELF_PROMO_OPACITY),
INTERACTION("interaction", sf("revanced_sb_segments_interaction"), sf("revanced_sb_segments_interaction_sum"), sf("revanced_sb_skip_button_interaction"), sf("revanced_sb_skipped_interaction"),
- SB_CATEGORY_INTERACTION, SB_CATEGORY_INTERACTION_COLOR),
+ SB_CATEGORY_INTERACTION, SB_CATEGORY_INTERACTION_COLOR, SB_CATEGORY_INTERACTION_OPACITY),
/**
* Unique category that is treated differently than the rest.
*/
HIGHLIGHT("poi_highlight", sf("revanced_sb_segments_highlight"), sf("revanced_sb_segments_highlight_sum"), sf("revanced_sb_skip_button_highlight"), sf("revanced_sb_skipped_highlight"),
- SB_CATEGORY_HIGHLIGHT, SB_CATEGORY_HIGHLIGHT_COLOR),
+ SB_CATEGORY_HIGHLIGHT, SB_CATEGORY_HIGHLIGHT_COLOR, SB_CATEGORY_HIGHLIGHT_OPACITY),
INTRO("intro", sf("revanced_sb_segments_intro"), sf("revanced_sb_segments_intro_sum"),
sf("revanced_sb_skip_button_intro_beginning"), sf("revanced_sb_skip_button_intro_middle"), sf("revanced_sb_skip_button_intro_end"),
sf("revanced_sb_skipped_intro_beginning"), sf("revanced_sb_skipped_intro_middle"), sf("revanced_sb_skipped_intro_end"),
- SB_CATEGORY_INTRO, SB_CATEGORY_INTRO_COLOR),
+ SB_CATEGORY_INTRO, SB_CATEGORY_INTRO_COLOR, SB_CATEGORY_INTRO_OPACITY),
OUTRO("outro", sf("revanced_sb_segments_outro"), sf("revanced_sb_segments_outro_sum"), sf("revanced_sb_skip_button_outro"), sf("revanced_sb_skipped_outro"),
- SB_CATEGORY_OUTRO, SB_CATEGORY_OUTRO_COLOR),
+ SB_CATEGORY_OUTRO, SB_CATEGORY_OUTRO_COLOR, SB_CATEGORY_OUTRO_OPACITY),
PREVIEW("preview", sf("revanced_sb_segments_preview"), sf("revanced_sb_segments_preview_sum"),
sf("revanced_sb_skip_button_preview_beginning"), sf("revanced_sb_skip_button_preview_middle"), sf("revanced_sb_skip_button_preview_end"),
sf("revanced_sb_skipped_preview_beginning"), sf("revanced_sb_skipped_preview_middle"), sf("revanced_sb_skipped_preview_end"),
- SB_CATEGORY_PREVIEW, SB_CATEGORY_PREVIEW_COLOR),
+ SB_CATEGORY_PREVIEW, SB_CATEGORY_PREVIEW_COLOR, SB_CATEGORY_PREVIEW_OPACITY),
FILLER("filler", sf("revanced_sb_segments_filler"), sf("revanced_sb_segments_filler_sum"), sf("revanced_sb_skip_button_filler"), sf("revanced_sb_skipped_filler"),
- SB_CATEGORY_FILLER, SB_CATEGORY_FILLER_COLOR),
+ SB_CATEGORY_FILLER, SB_CATEGORY_FILLER_COLOR, SB_CATEGORY_FILLER_OPACITY),
MUSIC_OFFTOPIC("music_offtopic", sf("revanced_sb_segments_nomusic"), sf("revanced_sb_segments_nomusic_sum"), sf("revanced_sb_skip_button_nomusic"), sf("revanced_sb_skipped_nomusic"),
- SB_CATEGORY_MUSIC_OFFTOPIC, SB_CATEGORY_MUSIC_OFFTOPIC_COLOR),
+ SB_CATEGORY_MUSIC_OFFTOPIC, SB_CATEGORY_MUSIC_OFFTOPIC_COLOR, SB_CATEGORY_MUSIC_OFFTOPIC_OPACITY),
UNSUBMITTED("unsubmitted", StringRef.empty, StringRef.empty, sf("revanced_sb_skip_button_unsubmitted"), sf("revanced_sb_skipped_unsubmitted"),
- SB_CATEGORY_UNSUBMITTED, SB_CATEGORY_UNSUBMITTED_COLOR),;
+ SB_CATEGORY_UNSUBMITTED, SB_CATEGORY_UNSUBMITTED_COLOR, SB_CATEGORY_UNSUBMITTED_OPACITY);
private static final StringRef skipSponsorTextCompact = sf("revanced_sb_skip_button_compact");
private static final StringRef skipSponsorTextCompactHighlight = sf("revanced_sb_skip_button_compact_highlight");
@@ -90,12 +93,10 @@ public enum SegmentCategory {
mValuesMap.put(value.keyValue, value);
}
- @NonNull
public static SegmentCategory[] categoriesWithoutUnsubmitted() {
return categoriesWithoutUnsubmitted;
}
- @NonNull
public static SegmentCategory[] categoriesWithoutHighlights() {
return categoriesWithoutHighlights;
}
@@ -106,7 +107,7 @@ public enum SegmentCategory {
}
/**
- * Must be called if behavior of any category is changed
+ * Must be called if behavior of any category is changed.
*/
public static void updateEnabledCategories() {
Utils.verifyOnMainThread();
@@ -133,32 +134,33 @@ public enum SegmentCategory {
updateEnabledCategories();
}
- @NonNull
- public final String keyValue;
- @NonNull
- public final StringSetting behaviorSetting;
- @NonNull
- private final StringSetting colorSetting;
+ public static int applyOpacityToColor(int color, float opacity) {
+ if (opacity < 0 || opacity > 1.0f) {
+ throw new IllegalArgumentException("Invalid opacity: " + opacity);
+ }
+ final int opacityInt = (int) (255 * opacity);
+ return (color & 0x00FFFFFF) | (opacityInt << 24);
+ }
+
+ public final String keyValue;
+ public final StringSetting behaviorSetting; // TODO: Replace with EnumSetting.
+ private final StringSetting colorSetting;
+ private final FloatSetting opacitySetting;
- @NonNull
public final StringRef title;
- @NonNull
public final StringRef description;
/**
* Skip button text, if the skip occurs in the first quarter of the video
*/
- @NonNull
public final StringRef skipButtonTextBeginning;
/**
* Skip button text, if the skip occurs in the middle half of the video
*/
- @NonNull
public final StringRef skipButtonTextMiddle;
/**
* Skip button text, if the skip occurs in the last quarter of the video
*/
- @NonNull
public final StringRef skipButtonTextEnd;
/**
* Skipped segment toast, if the skip occurred in the first quarter of the video
@@ -179,10 +181,7 @@ public enum SegmentCategory {
@NonNull
public final Paint paint;
- /**
- * Value must be changed using {@link #setColor(String)}.
- */
- public int color;
+ private int color;
/**
* Value must be changed using {@link #setBehaviour(CategoryBehaviour)}.
@@ -194,17 +193,20 @@ public enum SegmentCategory {
SegmentCategory(String keyValue, StringRef title, StringRef description,
StringRef skipButtonText,
StringRef skippedToastText,
- StringSetting behavior, StringSetting color) {
+ StringSetting behavior,
+ StringSetting color, FloatSetting opacity) {
this(keyValue, title, description,
skipButtonText, skipButtonText, skipButtonText,
skippedToastText, skippedToastText, skippedToastText,
- behavior, color);
+ behavior,
+ color, opacity);
}
SegmentCategory(String keyValue, StringRef title, StringRef description,
StringRef skipButtonTextBeginning, StringRef skipButtonTextMiddle, StringRef skipButtonTextEnd,
StringRef skippedToastBeginning, StringRef skippedToastMiddle, StringRef skippedToastEnd,
- StringSetting behavior, StringSetting color) {
+ StringSetting behavior,
+ StringSetting color, FloatSetting opacity) {
this.keyValue = Objects.requireNonNull(keyValue);
this.title = Objects.requireNonNull(title);
this.description = Objects.requireNonNull(description);
@@ -216,6 +218,7 @@ public enum SegmentCategory {
this.skippedToastEnd = Objects.requireNonNull(skippedToastEnd);
this.behaviorSetting = Objects.requireNonNull(behavior);
this.colorSetting = Objects.requireNonNull(color);
+ this.opacitySetting = Objects.requireNonNull(opacity);
this.paint = new Paint();
loadFromSettings();
}
@@ -232,11 +235,14 @@ public enum SegmentCategory {
this.behaviour = savedBehavior;
String colorString = colorSetting.get();
+ final float opacity = opacitySetting.get();
try {
setColor(colorString);
+ setOpacity(opacity);
} catch (Exception ex) {
- Logger.printException(() -> "Invalid color: " + colorString, ex);
+ Logger.printException(() -> "Invalid color: " + colorString + " opacity: " + opacity, ex);
colorSetting.resetToDefault();
+ opacitySetting.resetToDefault();
loadFromSettings();
}
}
@@ -245,45 +251,78 @@ public enum SegmentCategory {
this.behaviour = Objects.requireNonNull(behaviour);
this.behaviorSetting.save(behaviour.reVancedKeyValue);
}
- /**
- * @return HTML color format string
- */
- @NonNull
- public String colorString() {
- return String.format("#%06X", color);
- }
- public void setColor(@NonNull String colorString) throws IllegalArgumentException {
- final int color = Color.parseColor(colorString) & 0xFFFFFF;
- this.color = color;
+ private void updateColor() {
+ color = applyOpacityToColor(color, opacitySetting.get());
paint.setColor(color);
- paint.setAlpha(255);
- colorSetting.save(colorString); // Save after parsing.
}
- public void resetColor() {
+ /**
+ * @param opacity Segment color opacity between [0, 1].
+ */
+ public void setOpacity(float opacity) throws IllegalArgumentException {
+ if (opacity < 0 || opacity > 1) {
+ throw new IllegalArgumentException("Invalid opacity: " + opacity);
+ }
+
+ opacitySetting.save(opacity);
+ updateColor();
+ }
+
+ public float getOpacity() {
+ return opacitySetting.get();
+ }
+
+ public void resetColorAndOpacity() {
setColor(colorSetting.defaultValue);
+ setOpacity(opacitySetting.defaultValue);
}
- @NonNull
- private static String getCategoryColorDotHTML(int color) {
- color &= 0xFFFFFF;
- return String.format("⬤", color);
+ /**
+ * @param colorString Segment color with #RRGGBB format.
+ */
+ public void setColor(String colorString) throws IllegalArgumentException {
+ color = Color.parseColor(colorString);
+ colorSetting.save(colorString);
+
+ updateColor();
}
- @NonNull
- public static Spanned getCategoryColorDot(int color) {
- return Html.fromHtml(getCategoryColorDotHTML(color));
+ /**
+ * @return Integer color of #RRGGBB format.
+ */
+ public int getColorNoOpacity() {
+ return color & 0x00FFFFFF;
}
- @NonNull
- public Spanned getCategoryColorDot() {
+ /**
+ * @return Hex color string of #RRGGBB format with no opacity level.
+ */
+ public String getColorString() {
+ return String.format(Locale.US, "#%06X", getColorNoOpacity());
+ }
+
+ private static SpannableString getCategoryColorDotSpan(String text, int color) {
+ SpannableString dotSpan = new SpannableString('⬤' + text);
+ dotSpan.setSpan(new ForegroundColorSpan(color), 0, 1,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return dotSpan;
+ }
+
+ public static SpannableString getCategoryColorDot(int color) {
+ return getCategoryColorDotSpan("", color);
+ }
+
+ public SpannableString getCategoryColorDot() {
return getCategoryColorDot(color);
}
- @NonNull
- public Spanned getTitleWithColorDot() {
- return Html.fromHtml(getCategoryColorDotHTML(color) + " " + title);
+ public SpannableString getTitleWithColorDot(int categoryColor) {
+ return getCategoryColorDotSpan(" " + title, categoryColor);
+ }
+
+ public SpannableString getTitleWithColorDot() {
+ return getTitleWithColorDot(color);
}
/**
@@ -291,7 +330,6 @@ public enum SegmentCategory {
* @param videoLength length of the video
* @return the skip button text
*/
- @NonNull
StringRef getSkipButtonText(long segmentStartTime, long videoLength) {
if (Settings.SB_COMPACT_SKIP_BUTTON.get()) {
return (this == SegmentCategory.HIGHLIGHT)
@@ -300,7 +338,7 @@ public enum SegmentCategory {
}
if (videoLength == 0) {
- return skipButtonTextBeginning; // video is still loading. Assume it's the beginning
+ return skipButtonTextBeginning; // Video is still loading. Assume it's the beginning.
}
final float position = segmentStartTime / (float) videoLength;
if (position < 0.25f) {
@@ -316,10 +354,9 @@ public enum SegmentCategory {
* @param videoLength length of the video
* @return 'skipped segment' toast message
*/
- @NonNull
StringRef getSkippedToastText(long segmentStartTime, long videoLength) {
if (videoLength == 0) {
- return skippedToastBeginning; // video is still loading. Assume it's the beginning
+ return skippedToastBeginning; // Video is still loading. Assume it's the beginning.
}
final float position = segmentStartTime / (float) videoLength;
if (position < 0.25f) {
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java
index ec83d9122..ae92caaff 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SegmentCategoryListPreference.java
@@ -1,6 +1,7 @@
package app.revanced.extension.youtube.sponsorblock.objects;
import static app.revanced.extension.shared.StringRef.str;
+import static app.revanced.extension.youtube.sponsorblock.objects.SegmentCategory.applyOpacityToColor;
import android.app.AlertDialog;
import android.content.Context;
@@ -11,11 +12,10 @@ import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TableLayout;
-import android.widget.TableRow;
+import android.widget.GridLayout;
import android.widget.TextView;
+import java.util.Locale;
import java.util.Objects;
import app.revanced.extension.shared.Logger;
@@ -24,27 +24,38 @@ import app.revanced.extension.shared.Utils;
@SuppressWarnings("deprecation")
public class SegmentCategoryListPreference extends ListPreference {
private final SegmentCategory category;
- private EditText mEditText;
- private int mClickedDialogEntryIndex;
+ private TextView colorDotView;
+ private EditText colorEditText;
+ private EditText opacityEditText;
+ /**
+ * #RRGGBB
+ */
+ private int categoryColor;
+ /**
+ * [0, 1]
+ */
+ private float categoryOpacity;
+ private int selectedDialogEntryIndex;
public SegmentCategoryListPreference(Context context, SegmentCategory category) {
super(context);
- final boolean isHighlightCategory = category == SegmentCategory.HIGHLIGHT;
this.category = Objects.requireNonNull(category);
// Edit: Using preferences to sync together multiple pieces
- // of code together is messy and should be rethought.
+ // of code is messy and should be rethought.
setKey(category.behaviorSetting.key);
setDefaultValue(category.behaviorSetting.defaultValue);
+
+ final boolean isHighlightCategory = category == SegmentCategory.HIGHLIGHT;
setEntries(isHighlightCategory
? CategoryBehaviour.getBehaviorDescriptionsWithoutSkipOnce()
: CategoryBehaviour.getBehaviorDescriptions());
setEntryValues(isHighlightCategory
? CategoryBehaviour.getBehaviorKeyValuesWithoutSkipOnce()
: CategoryBehaviour.getBehaviorKeyValues());
-
setSummary(category.description.toString());
- updateTitle();
+
+ updateTitleFromCategory();
}
@Override
@@ -52,26 +63,40 @@ public class SegmentCategoryListPreference extends ListPreference {
try {
Utils.setEditTextDialogTheme(builder);
+ categoryColor = category.getColorNoOpacity();
+ categoryOpacity = category.getOpacity();
+
Context context = builder.getContext();
- TableLayout table = new TableLayout(context);
- table.setOrientation(LinearLayout.HORIZONTAL);
- table.setPadding(70, 0, 150, 0);
-
- TableRow row = new TableRow(context);
+ GridLayout gridLayout = new GridLayout(context);
+ gridLayout.setPadding(70, 0, 150, 0); // Padding for the entire layout.
+ gridLayout.setColumnCount(3);
+ gridLayout.setRowCount(2);
+ GridLayout.LayoutParams gridParams = new GridLayout.LayoutParams();
+ gridParams.rowSpec = GridLayout.spec(0); // First row.
+ gridParams.columnSpec = GridLayout.spec(0); // First column.
TextView colorTextLabel = new TextView(context);
colorTextLabel.setText(str("revanced_sb_color_dot_label"));
- row.addView(colorTextLabel);
+ colorTextLabel.setLayoutParams(gridParams);
+ gridLayout.addView(colorTextLabel);
- TextView colorDotView = new TextView(context);
- colorDotView.setText(category.getCategoryColorDot());
- colorDotView.setPadding(30, 0, 30, 0);
- row.addView(colorDotView);
+ gridParams = new GridLayout.LayoutParams();
+ gridParams.rowSpec = GridLayout.spec(0); // First row.
+ gridParams.columnSpec = GridLayout.spec(1); // Second column.
+ gridParams.setMargins(0, 0, 10, 0);
+ colorDotView = new TextView(context);
+ colorDotView.setLayoutParams(gridParams);
+ gridLayout.addView(colorDotView);
+ updateCategoryColorDot();
- mEditText = new EditText(context);
- mEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
- mEditText.setText(category.colorString());
- mEditText.addTextChangedListener(new TextWatcher() {
+ gridParams = new GridLayout.LayoutParams();
+ gridParams.rowSpec = GridLayout.spec(0); // First row.
+ gridParams.columnSpec = GridLayout.spec(2); // Third column.
+ colorEditText = new EditText(context);
+ colorEditText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
+ colorEditText.setTextLocale(Locale.US);
+ colorEditText.setText(category.getColorString());
+ colorEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@@ -81,29 +106,94 @@ public class SegmentCategoryListPreference extends ListPreference {
}
@Override
- public void afterTextChanged(Editable s) {
+ public void afterTextChanged(Editable edit) {
try {
- String colorString = s.toString();
+ String colorString = edit.toString();
+ final int colorStringLength = colorString.length();
+
if (!colorString.startsWith("#")) {
- s.insert(0, "#"); // recursively calls back into this method
+ edit.insert(0, "#"); // Recursively calls back into this method.
return;
}
- if (colorString.length() > 7) {
- s.delete(7, colorString.length());
+
+ final int maxColorStringLength = 7; // #RRGGBB
+ if (colorStringLength > maxColorStringLength) {
+ edit.delete(maxColorStringLength, colorStringLength);
return;
}
- final int color = Color.parseColor(colorString);
- colorDotView.setText(SegmentCategory.getCategoryColorDot(color));
+
+ categoryColor = Color.parseColor(colorString);
+ updateCategoryColorDot();
} catch (IllegalArgumentException ex) {
- // ignore
+ // Ignore.
}
}
});
- mEditText.setLayoutParams(new TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT, 1f));
- row.addView(mEditText);
+ colorEditText.setLayoutParams(gridParams);
+ gridLayout.addView(colorEditText);
- table.addView(row);
- builder.setView(table);
+ gridParams = new GridLayout.LayoutParams();
+ gridParams.rowSpec = GridLayout.spec(1); // Second row.
+ gridParams.columnSpec = GridLayout.spec(0, 1); // First and second column.
+ TextView opacityLabel = new TextView(context);
+ opacityLabel.setText(str("revanced_sb_color_opacity_label"));
+ opacityLabel.setLayoutParams(gridParams);
+ gridLayout.addView(opacityLabel);
+
+ gridParams = new GridLayout.LayoutParams();
+ gridParams.rowSpec = GridLayout.spec(1); // Second row.
+ gridParams.columnSpec = GridLayout.spec(2); // Third column.
+ opacityEditText = new EditText(context);
+ opacityEditText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
+ opacityEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable edit) {
+ try {
+ String editString = edit.toString();
+ final int opacityStringLength = editString.length();
+
+ final int maxOpacityStringLength = 4; // [0.00, 1.00]
+ if (opacityStringLength > maxOpacityStringLength) {
+ edit.delete(maxOpacityStringLength, opacityStringLength);
+ return;
+ }
+
+ final float opacity = opacityStringLength == 0
+ ? 0
+ : Float.parseFloat(editString);
+ if (opacity < 0) {
+ categoryOpacity = 0;
+ edit.replace(0, opacityStringLength, "0");
+ return;
+ } else if (opacity > 1.0f) {
+ categoryOpacity = 1;
+ edit.replace(0, opacityStringLength, "1.0");
+ return;
+ } else if (!editString.endsWith(".")) {
+ // Ignore "0." and "1." until the user finishes entering a valid number.
+ categoryOpacity = opacity;
+ }
+
+ updateCategoryColorDot();
+ } catch (NumberFormatException ex) {
+ // Should never happen.
+ Logger.printException(() -> "Could not parse opacity string", ex);
+ }
+ }
+ });
+ opacityEditText.setLayoutParams(gridParams);
+ gridLayout.addView(opacityEditText);
+ updateOpacityText();
+
+ builder.setView(gridLayout);
builder.setTitle(category.title.toString());
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
@@ -111,8 +201,8 @@ public class SegmentCategoryListPreference extends ListPreference {
});
builder.setNeutralButton(str("revanced_sb_reset_color"), (dialog, which) -> {
try {
- category.resetColor();
- updateTitle();
+ category.resetColorAndOpacity();
+ updateTitleFromCategory();
Utils.showToastShort(str("revanced_sb_color_reset"));
} catch (Exception ex) {
Logger.printException(() -> "setNeutralButton failure", ex);
@@ -120,8 +210,9 @@ public class SegmentCategoryListPreference extends ListPreference {
});
builder.setNegativeButton(android.R.string.cancel, null);
- mClickedDialogEntryIndex = findIndexOfValue(getValue());
- builder.setSingleChoiceItems(getEntries(), mClickedDialogEntryIndex, (dialog, which) -> mClickedDialogEntryIndex = which);
+ selectedDialogEntryIndex = findIndexOfValue(getValue());
+ builder.setSingleChoiceItems(getEntries(), selectedDialogEntryIndex,
+ (dialog, which) -> selectedDialogEntryIndex = which);
} catch (Exception ex) {
Logger.printException(() -> "onPrepareDialogBuilder failure", ex);
}
@@ -130,30 +221,51 @@ public class SegmentCategoryListPreference extends ListPreference {
@Override
protected void onDialogClosed(boolean positiveResult) {
try {
- if (positiveResult && mClickedDialogEntryIndex >= 0 && getEntryValues() != null) {
- String value = getEntryValues()[mClickedDialogEntryIndex].toString();
+ if (positiveResult && selectedDialogEntryIndex >= 0 && getEntryValues() != null) {
+ String value = getEntryValues()[selectedDialogEntryIndex].toString();
if (callChangeListener(value)) {
setValue(value);
category.setBehaviour(Objects.requireNonNull(CategoryBehaviour.byReVancedKeyValue(value)));
SegmentCategory.updateEnabledCategories();
}
- String colorString = mEditText.getText().toString();
+
try {
- if (!colorString.equals(category.colorString())) {
+ String colorString = colorEditText.getText().toString();
+ if (!colorString.equals(category.getColorString()) || categoryOpacity != category.getOpacity()) {
category.setColor(colorString);
+ category.setOpacity(categoryOpacity);
Utils.showToastShort(str("revanced_sb_color_changed"));
}
} catch (IllegalArgumentException ex) {
Utils.showToastShort(str("revanced_sb_color_invalid"));
}
- updateTitle();
+
+ updateTitleFromCategory();
}
} catch (Exception ex) {
Logger.printException(() -> "onDialogClosed failure", ex);
}
}
- private void updateTitle() {
- setTitle(category.getTitleWithColorDot());
+ private void applyOpacityToCategoryColor() {
+ categoryColor = applyOpacityToColor(categoryColor, categoryOpacity);
+ }
+
+ private void updateTitleFromCategory() {
+ categoryColor = category.getColorNoOpacity();
+ categoryOpacity = category.getOpacity();
+ applyOpacityToCategoryColor();
+
+ setTitle(category.getTitleWithColorDot(categoryColor));
+ }
+
+ private void updateCategoryColorDot() {
+ applyOpacityToCategoryColor();
+
+ colorDotView.setText(SegmentCategory.getCategoryColorDot(categoryColor));
+ }
+
+ private void updateOpacityText() {
+ opacityEditText.setText(String.format(Locale.US, "%.2f", categoryOpacity));
}
}
\ No newline at end of file
diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SponsorSegment.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SponsorSegment.java
index 811cb87c4..375de16b5 100644
--- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SponsorSegment.java
+++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/sponsorblock/objects/SponsorSegment.java
@@ -23,12 +23,15 @@ public class SponsorSegment implements Comparable {
@NonNull
public final StringRef title;
public final int apiVoteType;
- public final boolean shouldHighlight;
+ /**
+ * If the option should be highlighted for VIP users.
+ */
+ public final boolean highlightIfVipAndVideoIsLocked;
- SegmentVote(@NonNull StringRef title, int apiVoteType, boolean shouldHighlight) {
+ SegmentVote(@NonNull StringRef title, int apiVoteType, boolean highlightIfVipAndVideoIsLocked) {
this.title = title;
this.apiVoteType = apiVoteType;
- this.shouldHighlight = shouldHighlight;
+ this.highlightIfVipAndVideoIsLocked = highlightIfVipAndVideoIsLocked;
}
}
diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml
index 7e015ef08..41648df70 100644
--- a/patches/src/main/resources/addresources/values/strings.xml
+++ b/patches/src/main/resources/addresources/values/strings.xml
@@ -1068,6 +1068,8 @@ Already exists"
Downvote
Change category
There are no segments to vote for
+
+ %1$s to %2$s
Choose the segment category
Category is disabled in settings. Enable category to submit.
New SponsorBlock segment
@@ -1115,6 +1117,7 @@ Ready to submit?"
%1$s hours %2$s minutes
%1$s minutes %2$s seconds
%s seconds
+ Opacity:
Color:
Color changed
Color reset