diff --git a/app/src/main/java/pl/jakubweg/PlayerController.java b/app/src/main/java/pl/jakubweg/PlayerController.java index e884f57..f6fc42f 100644 --- a/app/src/main/java/pl/jakubweg/PlayerController.java +++ b/app/src/main/java/pl/jakubweg/PlayerController.java @@ -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 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 static void setCurrentVideoId(final String videoId) { sponsorTimer.schedule(new TimerTask() { @Override public void run() { - executeDownloadSegments(currentVideoId); + executeDownloadSegments(currentVideoId, context); } }, 0); } @@ -124,8 +123,8 @@ public static void onCreate(final Object o) { } } - 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 static void executeDownloadSegments(String videoId) { // 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 void run() { } 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 @@ private static void skipSegment(SponsorSegment segment, boolean wasClicked) { 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) { diff --git a/app/src/main/java/pl/jakubweg/SponsorBlockPreferenceFragment.java b/app/src/main/java/pl/jakubweg/SponsorBlockPreferenceFragment.java index 5f42a49..b5b16fc 100644 --- a/app/src/main/java/pl/jakubweg/SponsorBlockPreferenceFragment.java +++ b/app/src/main/java/pl/jakubweg/SponsorBlockPreferenceFragment.java @@ -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 @@ private void addSegmentsCategory(Context context, PreferenceScreen screen) { 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 @@ private void addSegmentsCategory(Context context, PreferenceScreen screen) { 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 @@ private void addSegmentsCategory(Context context, PreferenceScreen screen) { 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) diff --git a/app/src/main/java/pl/jakubweg/SponsorBlockSettings.java b/app/src/main/java/pl/jakubweg/SponsorBlockSettings.java index 5a617d0..f24fd7f 100644 --- a/app/src/main/java/pl/jakubweg/SponsorBlockSettings.java +++ b/app/src/main/java/pl/jakubweg/SponsorBlockSettings.java @@ -10,9 +10,8 @@ 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 static void update(Context context) { else SponsorBlockUtils.showVoteButton(); - SegmentBehaviour[] possibleBehaviours = SegmentBehaviour.values(); - final ArrayList 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)); - - 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; - } - } - } - if (behaviour == null) - behaviour = DefaultBehaviour; + Set enabledCategories = new HashSet<>(SegmentCategory.valuesWithoutUnsubmitted().length); + + 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; - segment.behaviour = behaviour; - if (behaviour.showOnTimeBar && segment != SegmentInfo.UNSUBMITTED) - enabledCategories.add(segment.key); + if (!behaviour.isDisabled() && category != SegmentCategory.UNSUBMITTED) { + enabledCategories.add(categoryKey); + } } - //"[%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 static void update(Context context) { } 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 static SegmentBehaviour byDesktopKey(int desktopKey) { } } - 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 enum SegmentInfo { 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 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 enum SegmentInfo { 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(); - } - public static SegmentInfo[] valuesWithoutUnsubmitted() { - return mValuesWithoutUnsubmitted; - } + this.paint = new Paint(); + this.color = defaultColor; + this.titleRef = titleRef; - public static SegmentInfo byCategoryKey(String key) { - return mValuesMap.get(key); + formatTitle(); } public void setColor(int color) { @@ -243,10 +229,25 @@ public void setColor(int color) { this.color = color; paint.setColor(color); paint.setAlpha(255); + formatTitle(); + } + + private void formatTitle() { + this.rawTitle = String.format(" %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 CharSequence getTitleWithDot() { - return Html.fromHtml(String.format(" %s", color, title)); + public static SegmentCategory[] valuesWithoutUnsubmitted() { + return valuesWithoutUnsubmitted; } } } diff --git a/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java b/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java index a05116f..12416ed 100644 --- a/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java +++ b/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java @@ -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(); + ((AlertDialog) dialog) + .getButton(DialogInterface.BUTTON_POSITIVE) + .setEnabled(enableButton); + }; + private static WeakReference appContext = new WeakReference<>(null); + 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; } - - 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); + 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 WeakReference 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(); + 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(); + 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); }; - public static String messageToToast = ""; 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 void onClick(DialogInterface dialog, int which) { 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 void onClick(DialogInterface dialog, int which) { .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 void onClick(DialogInterface dialog, int which) { .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 void onClick(DialogInterface dialog, int which) { } }) .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 static void onVotingClicked(final Context context) { List 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(" %s
%s to %s", - segment.category.color, segment.category.title, start, end)); + htmlBuilder.append(String.format("%s
%s to %s", segment.category.rawTitle, start, end)); if (i + 1 != segmentAmount) // prevents trailing new line after last segment htmlBuilder.append("
"); titles.add(Html.fromHtml(htmlBuilder.toString())); @@ -393,10 +375,10 @@ public static void onVotingClicked(final Context context) { } 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 static void onPreviewClicked(Context context) { 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 static String appendTimeWithoutSegments(String totalTime) { 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 static void importSettings(String json, Context context) { 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; + } int desktopKey = categorySelectionObject.getInt("option"); SponsorBlockSettings.SegmentBehaviour behaviour = SponsorBlockSettings.SegmentBehaviour.byDesktopKey(desktopKey); @@ -611,8 +597,8 @@ public static String exportSettings(Context context) { 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)); @@ -642,6 +628,34 @@ public static String exportSettings(Context context) { } } + public static void parseAndInsertSegments(JSONArray segmentArrayJson, List 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; } diff --git a/app/src/main/java/pl/jakubweg/objects/SponsorSegment.java b/app/src/main/java/pl/jakubweg/objects/SponsorSegment.java index 1819bba..14d7f2e 100644 --- a/app/src/main/java/pl/jakubweg/objects/SponsorSegment.java +++ b/app/src/main/java/pl/jakubweg/objects/SponsorSegment.java @@ -5,10 +5,10 @@ public class SponsorSegment implements Comparable { 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 SponsorSegment(long start, long end, SponsorBlockSettings.SegmentInfo cat @Override public String toString() { - return "SegmentInfo{" + + return "SegmentCategory{" + "start=" + start + ", end=" + end + ", category='" + category + '\'' + diff --git a/app/src/main/java/pl/jakubweg/requests/Requester.java b/app/src/main/java/pl/jakubweg/requests/Requester.java index 2b7884c..d9dc2dd 100644 --- a/app/src/main/java/pl/jakubweg/requests/Requester.java +++ b/app/src/main/java/pl/jakubweg/requests/Requester.java @@ -5,6 +5,7 @@ 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 segments = new ArrayList<>(); + public static synchronized SponsorSegment[] getSegments(String videoId, Context context) { + videoHasSegments = false; + timeWithoutSegments = ""; + + List 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) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d677c74..1565cce 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -181,10 +181,12 @@ Skipped self promotion Skipped silence Skipped preview + Skipped to highlight Skipped unsubmitted segment Skip automatically Show a skip button - Don\'t do anything + Show in the time bar + Disabled About This app uses the API from SponsorBlock Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app @@ -313,6 +315,8 @@ This time appears in brackets next to the current time. This shows the total video duration minus any segments. Preview/Recap 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. + Highlight + The part of the video that most people are looking for. Similar to "Video starts at x" comments. Stats Loading.. SponsorBlock is disabled