This commit is contained in:
caneleex 2022-01-28 00:55:35 +01:00 committed by GitHub
commit 449343a53f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 274 additions and 317 deletions

View File

@ -1,5 +1,8 @@
package pl.jakubweg;
import static pl.jakubweg.SponsorBlockSettings.skippedSegments;
import static pl.jakubweg.SponsorBlockSettings.skippedTime;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
@ -25,9 +28,6 @@ import fi.vanced.libraries.youtube.player.VideoInformation;
import pl.jakubweg.objects.SponsorSegment;
import pl.jakubweg.requests.Requester;
import static pl.jakubweg.SponsorBlockSettings.skippedSegments;
import static pl.jakubweg.SponsorBlockSettings.skippedTime;
@SuppressLint({"LongLogTag"})
public class PlayerController {
public static final String TAG = "jakubweg.PlayerController";
@ -45,7 +45,6 @@ public class PlayerController {
private static long currentVideoLength = 1L;
private static long lastKnownVideoTime = -1L;
private static final Runnable findAndSkipSegmentRunnable = () -> {
// Log.d(TAG, "findAndSkipSegmentRunnable");
findAndSkipSegment(false);
};
private static float sponsorBarLeft = 1f;
@ -89,7 +88,7 @@ public class PlayerController {
sponsorTimer.schedule(new TimerTask() {
@Override
public void run() {
executeDownloadSegments(currentVideoId);
executeDownloadSegments(currentVideoId, context);
}
}, 0);
}
@ -124,8 +123,8 @@ public class PlayerController {
}
}
public static void executeDownloadSegments(String videoId) {
SponsorSegment[] segments = Requester.getSegments(videoId);
public static void executeDownloadSegments(String videoId, Context context) {
SponsorSegment[] segments = Requester.getSegments(videoId, context);
Arrays.sort(segments);
if (VERBOSE)
@ -137,69 +136,6 @@ public class PlayerController {
// new Handler(Looper.getMainLooper()).post(findAndSkipSegmentRunnable);
}
/**
* Works in 14.x, waits some time of object to me filled with data,
* No longer used, i've found another way to get faster videoId
*/
@Deprecated
public static void asyncGetVideoLinkFromObject(final Object o) {
// code no longer used
// if (currentVideoLink != null) {
// if (VERBOSE)
// Log.w(TAG, "asyncGetVideoLinkFromObject: currentVideoLink != null probably share button was clicked");
// return;
// }
//
// new Thread(new Runnable() {
// @Override
// public void run() {
// try {
// // It used to be "b" in 14.x version, it's "a" in 15.x
// Field b = o.getClass().getDeclaredField("b");
//
// int attempts = 0;
// String videoUrl = null;
// while (true) {
// Object objLink = b.get(o);
// if (objLink == null) {
// if (VERBOSE)
// Log.e(TAG, "asyncGetVideoLinkFromObject: objLink is null");
// } else {
// videoUrl = objLink.toString();
// if (videoUrl.isEmpty())
// videoUrl = null;
// }
//
// if (videoUrl != null)
// break;
//
// if (attempts++ > 5) {
// Log.w(TAG, "asyncGetVideoLinkFromObject: attempts++ > 5");
// return;
// }
// Thread.sleep(50);
// }
//
// if (currentVideoLink == null) {
// currentVideoLink = videoUrl;
// if (VERBOSE)
// Log.d(TAG, "asyncGetVideoLinkFromObject: link set to " + videoUrl);
//
// executeDownloadSegments(substringVideoIdFromLink(videoUrl), false);
// }
//
// } catch (Exception e) {
// Log.e(TAG, "Cannot get link from object", e);
// }
// }
// }).start();
//
// Activity activity = playerActivity.get();
// if (activity != null)
// SponsorBlockUtils.addImageButton(activity);
}
/**
* Called when it's time to update the UI with new second, about once per second, only when playing, also in background
*/
@ -269,19 +205,19 @@ public class PlayerController {
}
private static void sendViewRequestAsync(final long millis, final SponsorSegment segment) {
if (segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
Context context = YouTubeTikTokRoot_Application.getAppContext();
if (context != null) {
SharedPreferences preferences = SponsorBlockSettings.getPreferences(context);
long newSkippedTime = skippedTime + (segment.end - segment.start);
preferences.edit().putInt(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS, skippedSegments + 1).apply();
preferences.edit().putLong(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME, newSkippedTime).apply();
}
if (segment.category == SponsorBlockSettings.SegmentCategory.UNSUBMITTED) {
return;
}
Context context = YouTubeTikTokRoot_Application.getAppContext();
if (context != null) {
SharedPreferences.Editor editor = SponsorBlockSettings.getPreferences(context).edit();
long newSkippedTime = skippedTime + (segment.end - segment.start);
editor.putInt(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS, skippedSegments + 1);
editor.putLong(SponsorBlockSettings.PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME, newSkippedTime);
editor.apply();
}
new Thread(() -> {
if (SponsorBlockSettings.countSkips &&
segment.category != SponsorBlockSettings.SegmentInfo.UNSUBMITTED &&
millis - segment.start < 2000) {
if (SponsorBlockSettings.countSkips && millis - segment.start < 2000) {
// Only skips from the start should count as a view
Requester.sendViewCountRequest(segment);
}
@ -509,7 +445,7 @@ public class PlayerController {
skipToMillisecond(segment.end + 2);
SkipSegmentView.hide();
if (segment.category == SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
if (segment.category == SponsorBlockSettings.SegmentCategory.UNSUBMITTED) {
SponsorSegment[] newSegments = new SponsorSegment[sponsorSegmentsOfCurrentVideo.length - 1];
int i = 0;
for (SponsorSegment sponsorSegment : sponsorSegmentsOfCurrentVideo) {

View File

@ -1,6 +1,6 @@
package pl.jakubweg;
import static pl.jakubweg.SponsorBlockSettings.DefaultBehaviour;
import static pl.jakubweg.SponsorBlockSettings.DEFAULT_BEHAVIOR;
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_ADJUST_NEW_SEGMENT_STEP;
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_COUNT_SKIPS;
import static pl.jakubweg.SponsorBlockSettings.PREFERENCES_KEY_NEW_SEGMENT_ENABLED;
@ -143,7 +143,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
preferencesToDisableWhenSBDisabled.add(category);
category.setTitle(str("diff_segments"));
String defaultValue = DefaultBehaviour.key;
String defaultValue = DEFAULT_BEHAVIOR.key;
SponsorBlockSettings.SegmentBehaviour[] segmentBehaviours = SponsorBlockSettings.SegmentBehaviour.values();
String[] entries = new String[segmentBehaviours.length];
String[] entryValues = new String[segmentBehaviours.length];
@ -153,13 +153,13 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
entryValues[i] = behaviour.key;
}
SponsorBlockSettings.SegmentInfo[] categories = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
SponsorBlockSettings.SegmentCategory[] categories = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentInfo segmentInfo : categories) {
for (SponsorBlockSettings.SegmentCategory segmentCategory : categories) {
ListPreference preference = new ListPreference(context);
preference.setTitle(segmentInfo.getTitleWithDot());
preference.setSummary(segmentInfo.description.toString());
preference.setKey(segmentInfo.key);
preference.setTitle(segmentCategory.title);
preference.setSummary(segmentCategory.description.toString());
preference.setKey(segmentCategory.key);
preference.setDefaultValue(defaultValue);
preference.setEntries(entries);
preference.setEntryValues(entryValues);
@ -174,7 +174,7 @@ public class SponsorBlockPreferenceFragment extends PreferenceFragment implement
colorPreference.setOnPreferenceClickListener(preference1 -> {
CharSequence[] items = new CharSequence[categories.length];
for (int i = 0; i < items.length; i++) {
items[i] = categories[i].getTitleWithDot();
items[i] = categories[i].title;
}
new AlertDialog.Builder(context)

View File

@ -10,9 +10,8 @@ import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class SponsorBlockSettings {
@ -30,8 +29,9 @@ public class SponsorBlockSettings {
public static final String PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME = "sb-skipped-segments-time";
public static final String PREFERENCES_KEY_SHOW_TIME_WITHOUT_SEGMENTS = "sb-length-without-segments";
public static final String PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX = "_color";
public static final String PREFERENCES_KEY_VIDEO_SEGMENTS_PREFIX = "video_";
public static final SegmentBehaviour DefaultBehaviour = SegmentBehaviour.SKIP_AUTOMATICALLY;
public static final SegmentBehaviour DEFAULT_BEHAVIOR = SegmentBehaviour.SKIP_AUTOMATICALLY;
public static boolean isSponsorBlockEnabled = false;
public static boolean seenGuidelinesPopup = false;
@ -92,37 +92,24 @@ public class SponsorBlockSettings {
else
SponsorBlockUtils.showVoteButton();
SegmentBehaviour[] possibleBehaviours = SegmentBehaviour.values();
final ArrayList<String> enabledCategories = new ArrayList<>(possibleBehaviours.length);
for (SegmentInfo segment : SegmentInfo.values()) {
String categoryColor = preferences.getString(segment.key + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX, SponsorBlockUtils.formatColorString(segment.defaultColor));
segment.setColor(Color.parseColor(categoryColor));
Set<String> enabledCategories = new HashSet<>(SegmentCategory.valuesWithoutUnsubmitted().length);
SegmentBehaviour behaviour = null;
String value = preferences.getString(segment.key, null);
if (value == null)
behaviour = DefaultBehaviour;
else {
for (SegmentBehaviour possibleBehaviour : possibleBehaviours) {
if (possibleBehaviour.key.equals(value)) {
behaviour = possibleBehaviour;
break;
}
}
for (SegmentCategory category : SegmentCategory.values()) {
String categoryKey = category.key;
String categoryColor = preferences.getString(categoryKey + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX, SponsorBlockUtils.formatColorString(category.defaultColor));
category.setColor(Color.parseColor(categoryColor));
String behaviorKey = preferences.getString(categoryKey, DEFAULT_BEHAVIOR.key);
SegmentBehaviour behaviour = SegmentBehaviour.byKey(behaviorKey);
category.behaviour = behaviour;
if (!behaviour.isDisabled() && category != SegmentCategory.UNSUBMITTED) {
enabledCategories.add(categoryKey);
}
if (behaviour == null)
behaviour = DefaultBehaviour;
segment.behaviour = behaviour;
if (behaviour.showOnTimeBar && segment != SegmentInfo.UNSUBMITTED)
enabledCategories.add(segment.key);
}
//"[%22sponsor%22,%22outro%22,%22music_offtopic%22,%22intro%22,%22selfpromo%22,%22interaction%22,%22preview%22]";
if (enabledCategories.isEmpty())
sponsorBlockUrlCategories = "[]";
else
sponsorBlockUrlCategories = "[%22" + TextUtils.join("%22,%22", enabledCategories) + "%22]";
sponsorBlockUrlCategories = "[%22" + TextUtils.join("%22,%22", enabledCategories) + "%22]";
skippedSegments = preferences.getInt(PREFERENCES_KEY_SKIPPED_SEGMENTS, skippedSegments);
skippedTime = preferences.getLong(PREFERENCES_KEY_SKIPPED_SEGMENTS_TIME, skippedTime);
@ -146,26 +133,34 @@ public class SponsorBlockSettings {
}
public enum SegmentBehaviour {
SKIP_AUTOMATICALLY("skip", 2, sf("skip_automatically"), true, true),
MANUAL_SKIP("manual-skip", 1, sf("skip_showbutton"), false, true),
IGNORE("ignore", -1, sf("skip_ignore"), false, false);
SKIP_AUTOMATICALLY("skip", 2, sf("skip_automatically"), true),
MANUAL_SKIP("manual-skip", 1, sf("skip_showbutton"), false),
SHOW("show", 0, sf("skip_show"), false),
DISABLED("disabled", -1, sf("skip_disabled"), false);
public final String key;
public final int desktopKey;
public final StringRef name;
public final boolean skip;
public final boolean showOnTimeBar;
SegmentBehaviour(String key,
int desktopKey,
StringRef name,
boolean skip,
boolean showOnTimeBar) {
SegmentBehaviour(String key, int desktopKey, StringRef name, boolean skip) {
this.key = key;
this.desktopKey = desktopKey;
this.name = name;
this.skip = skip;
this.showOnTimeBar = showOnTimeBar;
}
public boolean isDisabled() {
return this == SegmentBehaviour.DISABLED;
}
public static SegmentBehaviour byKey(String key) {
for (SegmentBehaviour behaviour : values()) {
if (behaviour.key.equals(key)) {
return behaviour;
}
}
return null;
}
public static SegmentBehaviour byDesktopKey(int desktopKey) {
@ -178,7 +173,7 @@ public class SponsorBlockSettings {
}
}
public enum SegmentInfo {
public enum SegmentCategory {
SPONSOR("sponsor", sf("segments_sponsor"), sf("skipped_sponsor"), sf("segments_sponsor_sum"), null, 0xFF00d400),
INTRO("intro", sf("segments_intermission"), sf("skipped_intermission"), sf("segments_intermission_sum"), null, 0xFF00ffff),
OUTRO("outro", sf("segments_endcards"), sf("skipped_endcard"), sf("segments_endcards_sum"), null, 0xFF0202ed),
@ -186,26 +181,10 @@ public class SponsorBlockSettings {
SELF_PROMO("selfpromo", sf("segments_selfpromo"), sf("skipped_selfpromo"), sf("segments_selfpromo_sum"), null, 0xFFffff00),
MUSIC_OFFTOPIC("music_offtopic", sf("segments_nomusic"), sf("skipped_nomusic"), sf("segments_nomusic_sum"), null, 0xFFff9900),
PREVIEW("preview", sf("segments_preview"), sf("skipped_preview"), sf("segments_preview_sum"), null, 0xFF008fd6),
HIGHLIGHT("poi_highlight", sf("segments_highlight"), sf("skipped_to_highlight"), sf("segments_highlight_sum"), null, 0xFFff1684),
UNSUBMITTED("unsubmitted", StringRef.empty, sf("skipped_unsubmitted"), StringRef.empty, SegmentBehaviour.SKIP_AUTOMATICALLY, 0xFFFFFFFF);
private static final SegmentInfo[] mValuesWithoutUnsubmitted = new SegmentInfo[]{
SPONSOR,
INTRO,
OUTRO,
INTERACTION,
SELF_PROMO,
MUSIC_OFFTOPIC,
PREVIEW
};
private static final Map<String, SegmentInfo> mValuesMap = new HashMap<>(values().length);
static {
for (SegmentInfo value : valuesWithoutUnsubmitted())
mValuesMap.put(value.key, value);
}
public final String key;
public final StringRef title;
public final StringRef skipMessage;
public final StringRef description;
public final Paint paint;
@ -213,29 +192,36 @@ public class SponsorBlockSettings {
public int color;
public SegmentBehaviour behaviour;
SegmentInfo(String key,
StringRef title,
StringRef skipMessage,
StringRef description,
SegmentBehaviour behaviour,
int defaultColor) {
private final StringRef titleRef;
public String rawTitle;
public CharSequence title;
private static final SegmentCategory[] valuesWithoutUnsubmitted;
static {
SegmentCategory[] values = values();
SegmentCategory[] withoutUnsubmitted = new SegmentCategory[values.length - 1];
for (int i = 0; i < values.length; i++) {
SegmentCategory category = values[i];
if (category != SegmentCategory.UNSUBMITTED) {
withoutUnsubmitted[i] = category;
}
}
valuesWithoutUnsubmitted = withoutUnsubmitted;
}
SegmentCategory(String key, StringRef titleRef, StringRef skipMessage, StringRef description, SegmentBehaviour behaviour, int defaultColor) {
this.key = key;
this.title = title;
this.skipMessage = skipMessage;
this.description = description;
this.behaviour = behaviour;
this.defaultColor = defaultColor;
this.color = defaultColor;
this.paint = new Paint();
}
this.color = defaultColor;
this.titleRef = titleRef;
public static SegmentInfo[] valuesWithoutUnsubmitted() {
return mValuesWithoutUnsubmitted;
}
public static SegmentInfo byCategoryKey(String key) {
return mValuesMap.get(key);
formatTitle();
}
public void setColor(int color) {
@ -243,10 +229,25 @@ public class SponsorBlockSettings {
this.color = color;
paint.setColor(color);
paint.setAlpha(255);
formatTitle();
}
public CharSequence getTitleWithDot() {
return Html.fromHtml(String.format("<font color=\"#%06X\">⬤</font> %s", color, title));
private void formatTitle() {
this.rawTitle = String.format("<font color=\"#%06X\">⬤</font> %s", color, titleRef);
this.title = Html.fromHtml(rawTitle);
}
public static SegmentCategory byCategoryKey(String key) {
for (SegmentCategory category : values()) {
if (category.key.equals(key)) {
return category;
}
}
return null;
}
public static SegmentCategory[] valuesWithoutUnsubmitted() {
return valuesWithoutUnsubmitted;
}
}
}

View File

@ -71,7 +71,6 @@ public abstract class SponsorBlockUtils {
public static final SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
public static boolean videoHasSegments = false;
public static String timeWithoutSegments = "";
private static final int sponsorBtnId = 1234;
public static final View.OnClickListener sponsorBlockBtnListener = v -> {
if (debug) {
Log.d(TAG, "Shield button clicked");
@ -88,92 +87,102 @@ public abstract class SponsorBlockUtils {
private static long newSponsorSegmentDialogShownMillis;
private static long newSponsorSegmentStartMillis = -1;
private static long newSponsorSegmentEndMillis = -1;
private static final DialogInterface.OnClickListener newSponsorSegmentDialogListener = new DialogInterface.OnClickListener() {
@SuppressLint("DefaultLocale")
@Override
public void onClick(DialogInterface dialog, int which) {
Context context = ((AlertDialog) dialog).getContext();
switch (which) {
case DialogInterface.BUTTON_NEGATIVE:
// start
newSponsorSegmentStartMillis = newSponsorSegmentDialogShownMillis;
Toast.makeText(context.getApplicationContext(), str("new_segment_time_start_set"), Toast.LENGTH_LONG).show();
break;
case DialogInterface.BUTTON_POSITIVE:
// end
newSponsorSegmentEndMillis = newSponsorSegmentDialogShownMillis;
Toast.makeText(context.getApplicationContext(), str("new_segment_time_end_set"), Toast.LENGTH_SHORT).show();
break;
}
dialog.dismiss();
private static final DialogInterface.OnClickListener newSponsorSegmentDialogListener = (dialog, which) -> {
Context context = ((AlertDialog) dialog).getContext();
switch (which) {
case DialogInterface.BUTTON_NEGATIVE:
// start
newSponsorSegmentStartMillis = newSponsorSegmentDialogShownMillis;
Toast.makeText(context.getApplicationContext(), str("new_segment_time_start_set"), Toast.LENGTH_LONG).show();
break;
case DialogInterface.BUTTON_POSITIVE:
// end
newSponsorSegmentEndMillis = newSponsorSegmentDialogShownMillis;
Toast.makeText(context.getApplicationContext(), str("new_segment_time_end_set"), Toast.LENGTH_SHORT).show();
break;
}
dialog.dismiss();
};
private static SponsorBlockSettings.SegmentInfo newSponsorBlockSegmentType;
private static final DialogInterface.OnClickListener segmentTypeListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted()[which];
boolean enableButton;
if (!segmentType.behaviour.showOnTimeBar) {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
str("new_segment_disabled_category"),
Toast.LENGTH_SHORT).show();
enableButton = false;
} else {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
segmentType.description.toString(),
Toast.LENGTH_SHORT).show();
newSponsorBlockSegmentType = segmentType;
enableButton = true;
}
((AlertDialog) dialog)
.getButton(DialogInterface.BUTTON_POSITIVE)
.setEnabled(enableButton);
private static SponsorBlockSettings.SegmentCategory newSponsorBlockSegmentType;
private static final DialogInterface.OnClickListener segmentTypeListener = (dialog, which) -> {
SponsorBlockSettings.SegmentCategory segmentType = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted()[which];
boolean enableButton;
if (segmentType.behaviour.isDisabled()) {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
str("new_segment_disabled_category"),
Toast.LENGTH_SHORT).show();
enableButton = false;
} else {
Toast.makeText(
((AlertDialog) dialog).getContext().getApplicationContext(),
segmentType.description.toString(),
Toast.LENGTH_SHORT).show();
newSponsorBlockSegmentType = segmentType;
enableButton = true;
}
};
private static final DialogInterface.OnClickListener segmentReadyDialogButtonListener = new DialogInterface.OnClickListener() {
@SuppressLint("DefaultLocale")
@Override
public void onClick(DialogInterface dialog, int which) {
NewSegmentHelperLayout.hide();
Context context = ((AlertDialog) dialog).getContext();
dialog.dismiss();
SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
CharSequence[] titles = new CharSequence[values.length];
for (int i = 0; i < values.length; i++) {
// titles[i] = values[i].title;
titles[i] = values[i].getTitleWithDot();
}
newSponsorBlockSegmentType = null;
new AlertDialog.Builder(context)
.setTitle(str("new_segment_choose_category"))
.setSingleChoiceItems(titles, -1, segmentTypeListener)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, segmentCategorySelectedDialogListener)
.show()
.getButton(DialogInterface.BUTTON_POSITIVE)
.setEnabled(false);
}
((AlertDialog) dialog)
.getButton(DialogInterface.BUTTON_POSITIVE)
.setEnabled(enableButton);
};
private static WeakReference<Context> appContext = new WeakReference<>(null);
private static final DialogInterface.OnClickListener segmentCategorySelectedDialogListener = new DialogInterface.OnClickListener() {
@SuppressLint("DefaultLocale")
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Context context = ((AlertDialog) dialog).getContext().getApplicationContext();
Toast.makeText(context, str("submit_started"), Toast.LENGTH_SHORT).show();
appContext = new WeakReference<>(context);
new Thread(submitRunnable).start();
}
};
public static String messageToToast = "";
private static final Runnable toastRunnable = () -> {
Context context = appContext.get();
if (context != null && messageToToast != null)
Toast.makeText(context, messageToToast, Toast.LENGTH_LONG).show();
};
private static final Runnable submitRunnable = () -> {
messageToToast = null;
final String uuid = SponsorBlockSettings.uuid;
final long start = newSponsorSegmentStartMillis;
final long end = newSponsorSegmentEndMillis;
final String videoId = getCurrentVideoId();
final SponsorBlockSettings.SegmentCategory segmentType = SponsorBlockUtils.newSponsorBlockSegmentType;
try {
if (start < 0 || end < 0 || start >= end || segmentType == null || videoId == null || uuid == null) {
Log.e(TAG, "Unable to submit times, invalid parameters");
return;
}
Requester.submitSegments(videoId, uuid, ((float) start) / 1000f, ((float) end) / 1000f, segmentType.key, toastRunnable);
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
} catch (Exception e) {
Log.e(TAG, "Unable to submit segment", e);
}
if (videoId != null)
PlayerController.executeDownloadSegments(videoId, appContext.get());
};
private static final DialogInterface.OnClickListener segmentCategorySelectedDialogListener = (dialog, which) -> {
dialog.dismiss();
Context context = ((AlertDialog) dialog).getContext().getApplicationContext();
Toast.makeText(context, str("submit_started"), Toast.LENGTH_SHORT).show();
appContext = new WeakReference<>(context);
new Thread(submitRunnable).start();
};
private static final DialogInterface.OnClickListener segmentReadyDialogButtonListener = (dialog, which) -> {
NewSegmentHelperLayout.hide();
Context context = ((AlertDialog) dialog).getContext();
dialog.dismiss();
SponsorBlockSettings.SegmentCategory[] values = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted();
CharSequence[] titles = new CharSequence[values.length];
for (int i = 0; i < values.length; i++) {
titles[i] = values[i].title;
}
newSponsorBlockSegmentType = null;
new AlertDialog.Builder(context)
.setTitle(str("new_segment_choose_category"))
.setSingleChoiceItems(titles, -1, segmentTypeListener)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, segmentCategorySelectedDialogListener)
.show()
.getButton(DialogInterface.BUTTON_POSITIVE)
.setEnabled(false);
};
private static final EditByHandSaveDialogListener editByHandSaveDialogListener = new EditByHandSaveDialogListener();
private static final DialogInterface.OnClickListener editByHandDialogListener = (dialog, which) -> {
Context context = ((AlertDialog) dialog).getContext();
@ -202,11 +211,6 @@ public abstract class SponsorBlockUtils {
dialog.dismiss();
};
private static final Runnable toastRunnable = () -> {
Context context = appContext.get();
if (context != null && messageToToast != null)
Toast.makeText(context, messageToToast, Toast.LENGTH_LONG).show();
};
private static final DialogInterface.OnClickListener segmentVoteClickListener = (dialog, which) -> {
final Context context = ((AlertDialog) dialog).getContext();
final SponsorSegment segment = sponsorSegmentsOfCurrentVideo[which];
@ -236,13 +240,13 @@ public abstract class SponsorBlockUtils {
.show();
};
public static final DialogInterface.OnClickListener categoryColorChangeClickListener = (dialog, which) -> {
SponsorBlockSettings.SegmentInfo segmentInfo = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted()[which];
String key = segmentInfo.key + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX;
SponsorBlockSettings.SegmentCategory segmentCategory = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted()[which];
String key = segmentCategory.key + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX;
Context context = ((AlertDialog) dialog).getContext();
EditText editText = new EditText(context);
editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setText(formatColorString(segmentInfo.color));
editText.setText(formatColorString(segmentCategory.color));
Context applicationContext = context.getApplicationContext();
SharedPreferences preferences = SponsorBlockSettings.getPreferences(context);
@ -252,7 +256,7 @@ public abstract class SponsorBlockUtils {
.setPositiveButton(str("change"), (dialog1, which1) -> {
try {
int color = Color.parseColor(editText.getText().toString());
segmentInfo.setColor(color);
segmentCategory.setColor(color);
Toast.makeText(applicationContext, str("color_changed"), Toast.LENGTH_SHORT).show();
preferences.edit().putString(key, formatColorString(color)).apply();
}
@ -261,35 +265,14 @@ public abstract class SponsorBlockUtils {
}
})
.setNeutralButton(str("reset"), (dialog1, which1) -> {
int defaultColor = segmentInfo.defaultColor;
segmentInfo.setColor(defaultColor);
int defaultColor = segmentCategory.defaultColor;
segmentCategory.setColor(defaultColor);
Toast.makeText(applicationContext, str("color_reset"), Toast.LENGTH_SHORT).show();
preferences.edit().putString(key, formatColorString(defaultColor)).apply();
})
.setNegativeButton(android.R.string.cancel, null)
.show();
};
private static final Runnable submitRunnable = () -> {
messageToToast = null;
final String uuid = SponsorBlockSettings.uuid;
final long start = newSponsorSegmentStartMillis;
final long end = newSponsorSegmentEndMillis;
final String videoId = getCurrentVideoId();
final SponsorBlockSettings.SegmentInfo segmentType = SponsorBlockUtils.newSponsorBlockSegmentType;
try {
if (start < 0 || end < 0 || start >= end || segmentType == null || videoId == null || uuid == null) {
Log.e(TAG, "Unable to submit times, invalid parameters");
return;
}
Requester.submitSegments(videoId, uuid, ((float) start) / 1000f, ((float) end) / 1000f, segmentType.key, toastRunnable);
newSponsorSegmentEndMillis = newSponsorSegmentStartMillis = -1;
} catch (Exception e) {
Log.e(TAG, "Unable to submit segment", e);
}
if (videoId != null)
PlayerController.executeDownloadSegments(videoId);
};
static {
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
@ -373,15 +356,14 @@ public abstract class SponsorBlockUtils {
List<CharSequence> titles = new ArrayList<>(segmentAmount); // I've replaced an array with a list to prevent null elements in the array as unsubmitted segments get filtered out
for (int i = 0; i < segmentAmount; i++) {
SponsorSegment segment = sponsorSegmentsOfCurrentVideo[i];
if (segment.category == SponsorBlockSettings.SegmentInfo.UNSUBMITTED) {
if (segment.category == SponsorBlockSettings.SegmentCategory.UNSUBMITTED) {
continue;
}
String start = dateFormatter.format(new Date(segment.start));
String end = dateFormatter.format(new Date(segment.end));
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append(String.format("<b><font color=\"#%06X\">⬤</font> %s<br> %s to %s",
segment.category.color, segment.category.title, start, end));
htmlBuilder.append(String.format("<b>%s<br> %s to %s", segment.category.rawTitle, start, end));
if (i + 1 != segmentAmount) // prevents trailing new line after last segment
htmlBuilder.append("<br>");
titles.add(Html.fromHtml(htmlBuilder.toString()));
@ -393,10 +375,10 @@ public abstract class SponsorBlockUtils {
}
private static void onNewCategorySelect(final SponsorSegment segment, Context context) {
final SponsorBlockSettings.SegmentInfo[] values = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
final SponsorBlockSettings.SegmentCategory[] values = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted();
CharSequence[] titles = new CharSequence[values.length];
for (int i = 0; i < values.length; i++) {
titles[i] = values[i].getTitleWithDot();
titles[i] = values[i].title;
}
new AlertDialog.Builder(context)
@ -416,7 +398,7 @@ public abstract class SponsorBlockUtils {
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
segments[segments.length - 1] = new SponsorSegment(newSponsorSegmentStartMillis, newSponsorSegmentEndMillis,
SponsorBlockSettings.SegmentInfo.UNSUBMITTED, null);
SponsorBlockSettings.SegmentCategory.UNSUBMITTED, null);
Arrays.sort(segments);
sponsorSegmentsOfCurrentVideo = segments;
@ -457,7 +439,7 @@ public abstract class SponsorBlockUtils {
return totalTime;
}
public static String getTimeWithoutSegments(SponsorSegment[] sponsorSegmentsOfCurrentVideo) {
private static String getTimeWithoutSegments(SponsorSegment[] sponsorSegmentsOfCurrentVideo) {
long currentVideoLength = getCurrentVideoLength();
if (!isSettingEnabled(showTimeWithoutSegments) || sponsorSegmentsOfCurrentVideo == null || currentVideoLength <= 1) {
return "";
@ -569,21 +551,25 @@ public abstract class SponsorBlockUtils {
SharedPreferences.Editor editor = getPreferences(context).edit();
SponsorBlockSettings.SegmentInfo[] categories = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentInfo category : categories) {
SponsorBlockSettings.SegmentCategory[] categories = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentCategory category : categories) {
String categoryKey = category.key;
JSONObject categoryObject = barTypesObject.getJSONObject(categoryKey);
String color = categoryObject.getString("color");
editor.putString(categoryKey + PREFERENCES_KEY_CATEGORY_COLOR_SUFFIX, color);
editor.putString(categoryKey, SponsorBlockSettings.SegmentBehaviour.IGNORE.key);
editor.putString(categoryKey, SponsorBlockSettings.SegmentBehaviour.DISABLED.key);
}
for (int i = 0; i < categorySelectionsArray.length(); i++) {
JSONObject categorySelectionObject = categorySelectionsArray.getJSONObject(i);
String categoryKey = categorySelectionObject.getString("name");
SponsorBlockSettings.SegmentInfo category = SponsorBlockSettings.SegmentInfo.byCategoryKey(categoryKey);
SponsorBlockSettings.SegmentCategory category = SponsorBlockSettings.SegmentCategory.byCategoryKey(categoryKey);
if (category == null) {
continue;
}
if (category == null) {
continue;
@ -615,8 +601,8 @@ public abstract class SponsorBlockUtils {
JSONObject barTypesObject = new JSONObject(); // categories' colors
JSONArray categorySelectionsArray = new JSONArray(); // categories' behavior
SponsorBlockSettings.SegmentInfo[] categories = SponsorBlockSettings.SegmentInfo.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentInfo category : categories) {
SponsorBlockSettings.SegmentCategory[] categories = SponsorBlockSettings.SegmentCategory.valuesWithoutUnsubmitted();
for (SponsorBlockSettings.SegmentCategory category : categories) {
JSONObject categoryObject = new JSONObject();
String categoryKey = category.key;
categoryObject.put("color", formatColorString(category.color));
@ -646,6 +632,34 @@ public abstract class SponsorBlockUtils {
}
}
public static void parseAndInsertSegments(JSONArray segmentArrayJson, List<SponsorSegment> segmentList) {
int length = segmentArrayJson.length();
try {
for (int i = 0; i < length; i++) {
JSONObject obj = segmentArrayJson.getJSONObject(i);
JSONArray segment = obj.getJSONArray("segment");
long start = (long) (segment.getDouble(0) * 1000);
long end = (long) (segment.getDouble(1) * 1000);
String category = obj.getString("category");
String uuid = obj.getString("UUID");
SponsorBlockSettings.SegmentCategory segmentCategory = SponsorBlockSettings.SegmentCategory.byCategoryKey(category);
if (segmentCategory != null) {
SponsorSegment sponsorSegment = new SponsorSegment(start, end, segmentCategory, uuid);
segmentList.add(sponsorSegment);
}
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setTimeWithoutSegments(SponsorSegment[] segments) {
videoHasSegments = true;
timeWithoutSegments = getTimeWithoutSegments(segments);
}
public static boolean isSettingEnabled(boolean setting) {
return isSponsorBlockEnabled && setting;
}

View File

@ -5,10 +5,10 @@ import pl.jakubweg.SponsorBlockSettings;
public class SponsorSegment implements Comparable<SponsorSegment> {
public final long start;
public final long end;
public final SponsorBlockSettings.SegmentInfo category;
public final SponsorBlockSettings.SegmentCategory category;
public final String UUID;
public SponsorSegment(long start, long end, SponsorBlockSettings.SegmentInfo category, String UUID) {
public SponsorSegment(long start, long end, SponsorBlockSettings.SegmentCategory category, String UUID) {
this.start = start;
this.end = end;
this.category = category;
@ -17,7 +17,7 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
@Override
public String toString() {
return "SegmentInfo{" +
return "SegmentCategory{" +
"start=" + start +
", end=" + end +
", category='" + category + '\'' +

View File

@ -5,6 +5,7 @@ import static pl.jakubweg.SponsorBlockUtils.videoHasSegments;
import static pl.jakubweg.StringRef.str;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.preference.Preference;
@ -36,40 +37,41 @@ public class Requester {
private Requester() {}
public static synchronized SponsorSegment[] getSegments(String videoId) {
List<SponsorSegment> segments = new ArrayList<>();
public static synchronized SponsorSegment[] getSegments(String videoId, Context context) {
videoHasSegments = false;
timeWithoutSegments = "";
List<SponsorSegment> segmentList = new ArrayList<>();
try {
HttpURLConnection connection = getConnectionFromRoute(Route.GET_SEGMENTS, videoId, SponsorBlockSettings.sponsorBlockUrlCategories);
int responseCode = connection.getResponseCode();
videoHasSegments = false;
timeWithoutSegments = "";
if (responseCode == 200) {
JSONArray responseArray = new JSONArray(parseJson(connection));
int length = responseArray.length();
for (int i = 0; i < length; i++) {
JSONObject obj = ((JSONObject) responseArray.get(i));
JSONArray segment = obj.getJSONArray("segment");
long start = (long) (segment.getDouble(0) * 1000);
long end = (long) (segment.getDouble(1) * 1000);
String category = obj.getString("category");
String uuid = obj.getString("UUID");
SponsorBlockSettings.SegmentInfo segmentCategory = SponsorBlockSettings.SegmentInfo.byCategoryKey(category);
if (segmentCategory != null && segmentCategory.behaviour.showOnTimeBar) {
SponsorSegment sponsorSegment = new SponsorSegment(start, end, segmentCategory, uuid);
segments.add(sponsorSegment);
}
}
videoHasSegments = true;
timeWithoutSegments = SponsorBlockUtils.getTimeWithoutSegments(segments.toArray(new SponsorSegment[0]));
SponsorBlockUtils.parseAndInsertSegments(responseArray, segmentList);
}
connection.disconnect();
}
catch (Exception ex) {
ex.printStackTrace();
}
return segments.toArray(new SponsorSegment[0]);
SharedPreferences preferences = SponsorBlockSettings.getPreferences(context);
String localSegmentsJson = preferences.getString(SponsorBlockSettings.PREFERENCES_KEY_VIDEO_SEGMENTS_PREFIX + videoId, null);
if (localSegmentsJson != null) {
try {
SponsorBlockUtils.parseAndInsertSegments(new JSONArray(localSegmentsJson), segmentList);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
SponsorSegment[] segments = segmentList.toArray(new SponsorSegment[0]);
if (!segmentList.isEmpty()) {
SponsorBlockUtils.setTimeWithoutSegments(segments);
}
return segments;
}
public static void submitSegments(String videoId, String uuid, float startTime, float endTime, String category, Runnable toastRunnable) {

View File

@ -181,10 +181,12 @@
<string name="skipped_selfpromo">Skipped self promotion</string>
<string name="skipped_nomusic">Skipped silence</string>
<string name="skipped_preview">Skipped preview</string>
<string name="skipped_to_highlight">Skipped to highlight</string>
<string name="skipped_unsubmitted">Skipped unsubmitted segment</string>
<string name="skip_automatically">Skip automatically</string>
<string name="skip_showbutton">Show a skip button</string>
<string name="skip_ignore">Don\'t do anything</string>
<string name="skip_show">Show in the time bar</string>
<string name="skip_disabled">Disabled</string>
<string name="about">About</string>
<string name="about_api">This app uses the API from SponsorBlock</string>
<string name="about_api_sum">Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app</string>
@ -313,6 +315,8 @@
<string name="general_time_without_sb_sum">This time appears in brackets next to the current time. This shows the total video duration minus any segments.</string>
<string name="segments_preview">Preview/Recap</string>
<string name="segments_preview_sum">Quick recap of previous episodes, or a preview of what\'s coming up later in the current video. Meant for edited together clips, not for spoken summaries.</string>
<string name="segments_highlight">Highlight</string>
<string name="segments_highlight_sum">The part of the video that most people are looking for. Similar to "Video starts at x" comments.</string>
<string name="stats">Stats</string>
<string name="stats_loading">Loading..</string>
<string name="stats_sb_disabled">SponsorBlock is disabled</string>